From 0ad93ad3a03992c1c45e658d1dfc615312c32a50 Mon Sep 17 00:00:00 2001 From: Bruno Marques Date: Tue, 20 Aug 2024 17:55:08 +0100 Subject: [PATCH] Using PyWinRT visual layer --- prefs.py | 2 +- requirements-win.txt | 17 +++++++++++++++++ requirements.txt | 7 ------- theme.py | 24 ++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 requirements-win.txt diff --git a/prefs.py b/prefs.py index 0c7f156fc..6d9e015cb 100644 --- a/prefs.py +++ b/prefs.py @@ -1293,7 +1293,7 @@ def apply(self) -> None: # noqa: CCR001 config.set('dark_text', self.theme_colors[0]) config.set('dark_highlight', self.theme_colors[1]) theme.apply() - if self.plugdir.get() != config.get('plugin_dir'): + if self.plugdir.get() != config.get_str('plugin_dir'): config.set( 'plugin_dir', str(Path(config.home_path, self.plugdir.get()[2:])) if self.plugdir.get().startswith('~') else diff --git a/requirements-win.txt b/requirements-win.txt new file mode 100644 index 000000000..b87e41243 --- /dev/null +++ b/requirements-win.txt @@ -0,0 +1,17 @@ +simplesystray==0.1.0 +pywin32==306 + +winrt-Microsoft.UI==2.2.0 +winrt-Microsoft.UI.Interop==2.2.0 +winrt-Microsoft.UI.Windowing==2.2.0 +winrt-Microsoft.Windows.ApplicationModel.DynamicDependency==2.2.0 +winrt-Microsoft.Windows.ApplicationModel.DynamicDependency.Bootstrap==2.2.0 +winrt-Windows.Foundation.Numerics==2.2.0 +winrt-Windows.System==2.2.0 +winrt-Windows.System.Interop==2.2.0 +winrt-Windows.UI==2.2.0 +winrt-Windows.UI.Composition==2.2.0 +winrt-Windows.UI.Composition.Desktop==2.2.0 +winrt-Windows.UI.Composition.Interop==2.2.0 + +-r requirements.txt diff --git a/requirements.txt b/requirements.txt index ba09a40ce..a1ef51c11 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,12 +1,5 @@ requests==2.32.3 pillow==10.3.0 watchdog==4.0.1 -simplesystray==0.1.0; sys_platform == 'win32' semantic-version==2.10.0 -# For manipulating folder permissions and the like. -pywin32==306; sys_platform == 'win32' psutil==5.9.8 -winrt-Microsoft.UI==2.1.0; sys_platform == 'win32' -winrt-Microsoft.UI.Interop==2.1.0; sys_platform == 'win32' -winrt-Microsoft.UI.Windowing==2.1.0; sys_platform == 'win32' -winrt-Microsoft.Windows.ApplicationModel.DynamicDependency.Bootstrap==2.1.0.post1; sys_platform == 'win32' diff --git a/theme.py b/theme.py index 4b127aa21..5c4155f70 100644 --- a/theme.py +++ b/theme.py @@ -28,6 +28,11 @@ import win32gui from winrt.microsoft.ui.interop import get_window_id_from_window from winrt.microsoft.ui.windowing import AppWindow + from winrt.windows.foundation.numerics import Vector2, Vector3 + from winrt.windows.system.interop import create_dispatcher_queue_controller + from winrt.windows.ui import Color + from winrt.windows.ui.composition import Compositor, ContainerVisual + from winrt.windows.ui.composition.interop import create_desktop_window_target from ctypes import windll FR_PRIVATE = 0x10 fonts_loaded = windll.gdi32.AddFontResourceExW(str(config.respath_path / 'EUROCAPS.TTF'), FR_PRIVATE, 0) @@ -129,6 +134,9 @@ class _Theme: } style: ttk.Style root: tk.Tk + dispatcher = None + compositor = None + compositor_target = None def __init__(self) -> None: self.active: int | None = None # Starts out with no theme @@ -153,6 +161,15 @@ def initialize(self, root: tk.Tk): except tk.TclError: logger.exception(f'Failure loading theme package "{theme_file}"') + if sys.platform == 'win32': + self.dispatcher = create_dispatcher_queue_controller() + self.compositor = Compositor() + self.compositor_target = create_desktop_window_target(self.compositor, self.root.winfo_id()) + c_root = self.compositor.create_container_visual() + c_root.relative_size_adjustment = Vector2(1, 1) + c_root.offset = Vector3(0, 0, 0) + self.compositor_target.root = c_root + def register(self, widget: tk.Widget | tk.BitmapImage) -> None: assert isinstance(widget, (tk.BitmapImage, tk.Widget)), widget warnings.warn('theme.register() is no longer necessary as theme attributes are set on tk level', @@ -200,6 +217,13 @@ def apply(self) -> None: window.title_bar.extends_content_into_title_bar = True title_gap['height'] = window.title_bar.height + visuals = ContainerVisual._from(self.compositor_target.root).children + element = self.compositor.create_sprite_visual() + element.brush = self.compositor.create_color_brush(Color(255, 10, 10, 10)) + element.size = Vector2(self.root.winfo_width(), 48) + element.offset = Vector3(0, 0, 0) + visuals.insert_at_top(element) + if theme == self.THEME_TRANSPARENT: win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, win32con.WS_EX_APPWINDOW | win32con.WS_EX_LAYERED) # Add to taskbar