From 3888a8855fe030136d0922bd1f14243ea1f8bff3 Mon Sep 17 00:00:00 2001 From: mar77i Date: Tue, 21 Jan 2025 18:41:34 +0100 Subject: [PATCH] import zenbook_conf --- ui/__init__.py | 0 ui/ui.py | 65 +++++++++++- zenbook_conf.py | 15 +++ zenbook_conf/shapes.py | 2 +- zenbook_conf/zenbook_conf.py | 191 +++++++++++++++++++++++++++++++++++ 5 files changed, 269 insertions(+), 4 deletions(-) create mode 100644 ui/__init__.py create mode 100755 zenbook_conf.py create mode 100644 zenbook_conf/zenbook_conf.py diff --git a/ui/__init__.py b/ui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ui/ui.py b/ui/ui.py index 3a84628..27c2035 100644 --- a/ui/ui.py +++ b/ui/ui.py @@ -355,14 +355,21 @@ class Switch(UIChild): if self.moving_since is not nan: self.dirty = True + def set_value(self, value): + if value == self.value: + return + self.value = value + if value is None: + self.moving_since = time() - self.MOVE_FOR_SEC / 2 + else: + self.moving_since = time() + def handle_mousebuttondown(self, ev): if ev.button == 1 and self.rect.collidepoint(ev.pos): if self.moving_since is not nan: self.flip_again = True return - self.value = bool(self.value) ^ True - offset = self.MOVE_FOR_SEC / 2 if self.value is None else 0 - self.moving_since = time() - offset + self.set_value(bool(self.value) ^ True) class Cursor(EventMethodDispatcher): @@ -602,3 +609,55 @@ class TextInput(UIChild): self.focus() elif self.cursor is not None: self.blur(True) + + +class FPSWidget(UIChild): + FPS_COLOR = "yellow" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.clock = self.parent.clock + self.current_fps = None + + def update(self): + new_fps = int(self.clock.get_fps()) + if self.current_fps != new_fps: + self.current_fps = new_fps + self.dirty = True + + def draw(self): + surf_size = self.surf.get_size() + fs = self.font.render( + f"{int(self.current_fps)} FPS", True, self.FPS_COLOR + ) + fs_size = fs.get_size() + self.surf.blit( + fs, (surf_size[0] - fs_size[0] - 7, surf_size[1] - fs_size[1] - 7) + ) + + +class Icon(UIChild): + def __init__(self, parent, shape): + super().__init__(parent) + self.shape = shape + + def draw(self): + self.shape.draw(self.surf, "gray") + + +class IconButton(Button): + def __init__(self, parent, shape, *args, **kwargs): + super().__init__(parent, *args, **kwargs) + self.shape = shape + + def draw(self): + if self.pushed: + pygame.draw.rect(self.parent.surf, "honeydew4", self.rect) + self.shape.draw(self.parent.surf, "black" if self.pushed else "white") + if self.is_active: + color = "lime" + elif self.pushed: + color = "red" + else: + color = "gray" + pygame.draw.rect(self.parent.surf, color, self.rect, 8) diff --git a/zenbook_conf.py b/zenbook_conf.py new file mode 100755 index 0000000..fd44ccb --- /dev/null +++ b/zenbook_conf.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +import sys +from contextlib import redirect_stdout +from io import StringIO +from pathlib import Path + +sys.path.append(str(Path(__file__).parent)) + +from zenbook_conf.zenbook_conf import ZenbookConf + +with redirect_stdout(StringIO()): + import pygame # type: ignore + +ZenbookConf().run() diff --git a/zenbook_conf/shapes.py b/zenbook_conf/shapes.py index 4d7be4b..a9c7c6d 100644 --- a/zenbook_conf/shapes.py +++ b/zenbook_conf/shapes.py @@ -1,6 +1,6 @@ from math import cos, pi, sin, tau -from vectors import ( +from vectors.vectors import ( Polygon, Rect, Shapes, StrokeCircleSegment, StrokeRoundLine, StrokeSquareLine ) diff --git a/zenbook_conf/zenbook_conf.py b/zenbook_conf/zenbook_conf.py new file mode 100644 index 0000000..e6f3f49 --- /dev/null +++ b/zenbook_conf/zenbook_conf.py @@ -0,0 +1,191 @@ +from functools import partial + +import pygame + +from .bluetooth import BluetoothConf +from ui.ui import Button, FPSWidget, Icon, IconButton, Switch, UIParent +from .shapes import ( + bluetooth, + laptop_double, + laptop_single, + laptop_vertical, + touchscreen, + stylus, +) +from .xinput import XinputConf +from .xrandr import XrandrConf + + +class ZenbookConf(UIParent): + BACKGROUND_COLOR = 0x333333 + + def __init__(self): + pygame.init() + pygame.display.set_icon(self.get_icon()) + pygame.display.set_caption("Zenbook Config") + window_size = (1536, 1200) + super().__init__( + pygame.display.set_mode(window_size, display=0), + pygame.font.Font(None, size=96), + ) + self.current_display = 0 + self.xrandr_conf = XrandrConf() + self.xinput_conf = XinputConf(self.xrandr_conf) + self.bluetooth_conf = BluetoothConf() + bt_switch = Switch( + self, + pygame.Rect((128, 612), (256, 128)), + self.bluetooth_conf.update, + self.bluetooth_conf.conf + ) + touch_switch = Switch( + self, + pygame.Rect((128, 808), (256, 128)), + partial(self.xinput_conf.update_by_type, "touchpad"), + self.xinput_conf.conf_by_type("touchpad"), + ) + stylus_switch = Switch( + self, + pygame.Rect((128, 1004), (256, 128)), + partial(self.xinput_conf.update_by_type, "stylus"), + self.xinput_conf.conf_by_type("stylus"), + ) + top = 128 + self.single_button = IconButton( + self, + laptop_single.fit((100, top + 32), (16, 16)), + pygame.Rect((68, top), (416, 416)), + None, + partial( + self.laptop_cb, "single", bt_switch, touch_switch, stylus_switch + ), + self.xrandr_conf.is_active("single"), + ) + self.double_button = IconButton( + self, + laptop_double.fit((600, top + 32), (16, 16)), + pygame.Rect((568, top), (416, 416)), + None, + partial( + self.laptop_cb, "double", bt_switch, touch_switch, stylus_switch + ), + self.xrandr_conf.is_active("double"), + ) + self.vertical_button = IconButton( + self, + laptop_vertical.fit((1100, top + 32), (16, 16)), + pygame.Rect((1068, top), (416, 416)), + None, + partial( + self.laptop_cb, + "vertical", + bt_switch, + touch_switch, + stylus_switch, + ), + self.xrandr_conf.is_active("vertical"), + ) + self.children.extend( + ( + FPSWidget(self), + self.single_button, + self.double_button, + self.vertical_button, + bt_switch, + Icon( + self, + bluetooth.fit( + (bt_switch.rect.right + 68, bt_switch.rect.centery - 88), + (8, 8), + ), + ), + touch_switch, + Icon( + self, + touchscreen.fit( + (touch_switch.rect.right + 68, touch_switch.rect.centery - 88), + (8, 8), + ), + ), + stylus_switch, + Icon( + self, + stylus.fit( + ( + stylus_switch.rect.right + 68, + stylus_switch.rect.centery - 88, + ), + (8, 8), + ), + ), + Button( + self, + pygame.Rect((784, touch_switch.rect.top), (384, 128)), + "Re-apply", + partial(self.xinput_conf.reapply_by_type, "touchpad") + ), + Button( + self, + pygame.Rect((784, stylus_switch.rect.top), (384, 128)), + "Re-apply", + partial(self.xinput_conf.reapply_by_type, "stylus") + ), + Button( + self, + pygame.Rect((window_size[0] - 128, 0), (128, 96)), + "×", + self.quit, + ), + Button( + self, + pygame.Rect((window_size[0] - 256, 0), (128, 96)), + "_", + self.iconify, + ), + Button( + self, + pygame.Rect((window_size[0] - 384, 0), (128, 96)), + "»", + self.next_display, + ), + ) + ) + + def get_icon(self): + surf = pygame.Surface((512, 512), pygame.SRCALPHA, 32) + surf.fill(0x0) + v = 512 // 22 + laptop_single.fit((0, 0), (v, v)).draw(surf, "white") + return pygame.transform.scale(surf, (32, 32)) + + def laptop_cb(self, name, bt_switch, touch_switch, stylus_switch): + self.xrandr_conf.update(name) + if name != "single": + self.bluetooth_conf.update(True) + bt_switch.set_value(True) + settings_per_device_type = { + "touchpad": touch_switch.value, + "stylus": stylus_switch.value, + } + for device_type, value in settings_per_device_type.items(): + if value is not None: + self.xinput_conf.update_by_type(device_type, value) + self.single_button.is_active = self.xrandr_conf.is_active("single") + self.double_button.is_active = self.xrandr_conf.is_active("double") + self.vertical_button.is_active = self.xrandr_conf.is_active("vertical") + self.dirty = True + + def quit(self): + self.running = False + + def iconify(self): + pygame.display.iconify() + + def next_display(self): + current_display = (self.current_display + 1) % self.xrandr_conf.count_active() + if current_display != self.current_display: + self.current_display = current_display + self.surf = pygame.display.set_mode( + self.surf.get_size(), display=self.current_display + ) + self.dirty = True -- 2.51.0