diff --git a/src/xpra/client/gtk3/gtk3_client_window.py b/src/xpra/client/gtk3/gtk3_client_window.py index 03968d853c..e1798791df 100644 --- a/src/xpra/client/gtk3/gtk3_client_window.py +++ b/src/xpra/client/gtk3/gtk3_client_window.py @@ -11,7 +11,7 @@ from xpra.client.gtk3.window_menu import WindowMenuHelper from xpra.gtk_common.gtk_util import WINDOW_NAME_TO_HINT, scaled_image from xpra.util import envbool -from xpra.os_util import bytestostr, is_gnome, OSX +from xpra.os_util import bytestostr, is_gnome, OSX, WIN32 from xpra.log import Logger paintlog = Logger("paint") @@ -97,6 +97,10 @@ def add_header_bar(self): button.connect("clicked", self.show_xpra_menu) hb.pack_end(button) self.set_titlebar(hb) + if WIN32: + from xpra.platform.win32.dwm_color import match_window_color + match_window_color() + def show_xpra_menu(self, *_args): mh = getattr(self._client, "menu_helper", None) diff --git a/src/xpra/platform/win32/dwm_color.py b/src/xpra/platform/win32/dwm_color.py new file mode 100644 index 0000000000..ca107f114c --- /dev/null +++ b/src/xpra/platform/win32/dwm_color.py @@ -0,0 +1,118 @@ +# This file is part of Xpra. +# Copyright (C) 2020 Antoine Martin +# Xpra is released under the terms of the GNU GPL v2, or, at your option, any +# later version. See the file COPYING for details. + +from ctypes import WinDLL, windll, c_int, byref, Structure, POINTER +from ctypes.wintypes import DWORD, PDWORD, PBOOL, BOOL, UINT + +from gi.repository import Gdk, Gtk + +from xpra.log import Logger + +log = Logger("win32") +log.enable_debug() + + +COLORREF = DWORD #0x00bbggrr + +class COLORIZATIONPARAMS(Structure): + _fields_ = ( + ('Color', COLORREF), + ('Afterglow', COLORREF), + ('ColorBalance', UINT), + ('AfterglowBalance', UINT), + ('BlurBalance', UINT), + ('GlassReflectionIntensity', UINT), + ('Opaque', BOOL), + ) +PCOLORIZATIONPARAMS = POINTER(COLORIZATIONPARAMS) + +try: + DwmGetColorizationParameters = windll.dwmapi[127] +except Exception: + DwmGetColorizationParameters = None +else: + DwmGetColorizationParameters.argyptes = [PCOLORIZATIONPARAMS] + DwmGetColorizationParameters.restype = c_int + +def rgba(c): + r, g, b = (c >> 16) & 0xFF, (c >> 8) & 0xFF, c & 0xFF + a = (c >> 24) & 0xff + return (r, g, b, a) + +def get_frame_color(): + params = COLORIZATIONPARAMS() + r = DwmGetColorizationParameters(byref(params)) + log("DwmGetColorizationParameters(..)=%i", r) + if r: + return None + return params.Color + +def get_colorization_color(): + dwmapi = WinDLL("dwmapi", use_last_error=True) + DwmGetColorizationColor = dwmapi.DwmGetColorizationColor + DwmGetColorizationColor.restype = c_int + DwmGetColorizationColor.argtypes = [PDWORD, PBOOL] + color = DWORD() + opaque = BOOL() + r = DwmGetColorizationColor(byref(color), byref(opaque)) + log("DwmGetColorizationColor(..)=%i", r) + if r: + return None + return color.value + + +def match_window_color(): + color = get_frame_color() or get_colorization_color() + if not color: + return + r, g, b, a = rgba(color) + log("rgba(%#x)=%s", color, (r, g, b, a)) + #color_str = "#"+hex(c)[-6:] + #color should be: 10893e + color_str = "rgba(%i, %i, %i, %.2f)" % (r, g, b, a/255) + if min(r, g, b)<128: + title_color_str = "white" + else: + title_color_str = "black" + if max(abs(0x99-c) for c in (r, g, b))>64: + title_unfocused_color_str = "#999999" + else: + title_unfocused_color_str = "#333333" + if max(abs(0xff-c) for c in (r, g, b))>64: + unfocused_color_str = "white" + else: + unfocused_color_str = "#666666" + style_provider = Gtk.CssProvider() + css_data = """ +.titlebar { + background-color: %s; + background-image: none; +} +headerbar .title { + color : %s; +} +headerbar .titlebutton { + color: %s; +} +.titlebar:backdrop { + background-color: %s; +} +.titlebar:backdrop .title { + color : %s; +} +headerbar:backdrop .titlebutton { + color: %s; +} +""" % ( + color_str, title_color_str, title_color_str, + unfocused_color_str, title_unfocused_color_str, title_unfocused_color_str, +) + log("match_window_color() css=%r", css_data) + style_provider.load_from_data(css_data.encode("latin1")) + Gtk.StyleContext.add_provider_for_screen( + Gdk.Screen.get_default(), + style_provider, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION+1 + )