mirror of
https://github.com/ZoiteChat/zoitechat.git
synced 2026-03-10 16:00:18 +00:00
Implemented a Windows-specific theme detection path with High Contrast safeguards, including helpers to detect HC mode, read Windows system theme preference from the registry, and gate native titlebar dark mode updates when HC is active. Also added DWM header usage for native titlebar APIs.
Added a unified theme application pipeline via fe_apply_theme_for_mode() and fe_apply_theme_to_toplevel(), and routed auto-mode refresh logic through it so palette + GTK input styling are applied consistently from one place. Switched startup and settings-apply flows to use the unified theming function, replacing direct palette-only calls so system-mode detection → theme apply is consistent across initialization and preferences changes. Applied native titlebar updates when top-level windows are shown and during setup reapply across open sessions, and wired Windows builds to link dwmapi in both Meson and MSVC project files.
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <dwmapi.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
@@ -285,6 +286,8 @@ const char cursor_color_rc[] =
|
||||
"}"
|
||||
"widget \"*.zoitechat-inputbox\" style : application \"xc-ib-st\"";
|
||||
|
||||
InputStyle *create_input_style (InputStyle *style);
|
||||
|
||||
static const char adwaita_workaround_rc[] =
|
||||
"style \"zoitechat-input-workaround\""
|
||||
"{"
|
||||
@@ -301,6 +304,85 @@ static const char adwaita_workaround_rc[] =
|
||||
"}"
|
||||
"widget \"*.zoitechat-inputbox\" style \"zoitechat-input-workaround\"";
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
|
||||
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
fe_win32_high_contrast_is_enabled (void)
|
||||
{
|
||||
HIGHCONTRASTW hc;
|
||||
|
||||
ZeroMemory (&hc, sizeof (hc));
|
||||
hc.cbSize = sizeof (hc);
|
||||
if (!SystemParametersInfoW (SPI_GETHIGHCONTRAST, sizeof (hc), &hc, 0))
|
||||
return FALSE;
|
||||
|
||||
return (hc.dwFlags & HCF_HIGHCONTRASTON) != 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fe_win32_try_get_system_dark (gboolean *prefer_dark)
|
||||
{
|
||||
DWORD value = 1;
|
||||
DWORD value_size = sizeof (value);
|
||||
LSTATUS status;
|
||||
|
||||
status = RegGetValueW (HKEY_CURRENT_USER,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
|
||||
L"AppsUseLightTheme",
|
||||
RRF_RT_REG_DWORD,
|
||||
NULL,
|
||||
&value,
|
||||
&value_size);
|
||||
if (status != ERROR_SUCCESS)
|
||||
status = RegGetValueW (HKEY_CURRENT_USER,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
|
||||
L"SystemUsesLightTheme",
|
||||
RRF_RT_REG_DWORD,
|
||||
NULL,
|
||||
&value,
|
||||
&value_size);
|
||||
|
||||
if (status != ERROR_SUCCESS)
|
||||
return FALSE;
|
||||
|
||||
*prefer_dark = (value == 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fe_win32_apply_native_titlebar (GtkWidget *window, gboolean dark_mode)
|
||||
{
|
||||
HWND hwnd;
|
||||
BOOL use_dark;
|
||||
|
||||
if (!window || !gtk_widget_get_realized (window))
|
||||
return;
|
||||
|
||||
hwnd = gdk_win32_window_get_handle (gtk_widget_get_window (window));
|
||||
if (!hwnd)
|
||||
return;
|
||||
|
||||
if (fe_win32_high_contrast_is_enabled ())
|
||||
return;
|
||||
|
||||
use_dark = dark_mode ? TRUE : FALSE;
|
||||
DwmSetWindowAttribute (hwnd,
|
||||
DWMWA_USE_IMMERSIVE_DARK_MODE,
|
||||
&use_dark,
|
||||
sizeof (use_dark));
|
||||
}
|
||||
#else
|
||||
static void
|
||||
fe_win32_apply_native_titlebar (GtkWidget *window, gboolean dark_mode)
|
||||
{
|
||||
(void) window;
|
||||
(void) dark_mode;
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
fe_system_prefers_dark (void)
|
||||
{
|
||||
@@ -309,42 +391,16 @@ fe_system_prefers_dark (void)
|
||||
char *theme_name = NULL;
|
||||
#ifdef G_OS_WIN32
|
||||
gboolean have_win_pref = FALSE;
|
||||
|
||||
if (fe_win32_high_contrast_is_enabled ())
|
||||
return FALSE;
|
||||
#endif
|
||||
|
||||
if (!settings)
|
||||
return FALSE;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
{
|
||||
DWORD value = 1;
|
||||
DWORD value_size = sizeof (value);
|
||||
LSTATUS status;
|
||||
|
||||
status = RegGetValueW (HKEY_CURRENT_USER,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
|
||||
L"AppsUseLightTheme",
|
||||
RRF_RT_REG_DWORD,
|
||||
NULL,
|
||||
&value,
|
||||
&value_size);
|
||||
if (status != ERROR_SUCCESS)
|
||||
status = RegGetValueW (HKEY_CURRENT_USER,
|
||||
L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
|
||||
L"SystemUsesLightTheme",
|
||||
RRF_RT_REG_DWORD,
|
||||
NULL,
|
||||
&value,
|
||||
&value_size);
|
||||
|
||||
if (status == ERROR_SUCCESS)
|
||||
{
|
||||
prefer_dark = (value == 0);
|
||||
have_win_pref = TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
have_win_pref = fe_win32_try_get_system_dark (&prefer_dark);
|
||||
if (!have_win_pref)
|
||||
#endif
|
||||
if (g_object_class_find_property (G_OBJECT_GET_CLASS (settings),
|
||||
@@ -388,7 +444,7 @@ fe_auto_dark_mode_changed (GtkSettings *settings, GParamSpec *pspec, gpointer da
|
||||
return;
|
||||
|
||||
auto_dark_mode_enabled = enabled;
|
||||
palette_apply_dark_mode (enabled);
|
||||
fe_apply_theme_for_mode (ZOITECHAT_DARK_MODE_AUTO, NULL);
|
||||
setup_apply_real (0, TRUE, FALSE, FALSE);
|
||||
}
|
||||
|
||||
@@ -404,6 +460,30 @@ fe_refresh_auto_dark_mode (void)
|
||||
fe_auto_dark_mode_changed (NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
fe_apply_theme_for_mode (unsigned int mode, gboolean *palette_changed)
|
||||
{
|
||||
gboolean enabled = fe_dark_mode_is_enabled_for (mode);
|
||||
gboolean changed = palette_apply_dark_mode (enabled);
|
||||
|
||||
if (palette_changed)
|
||||
*palette_changed = changed;
|
||||
|
||||
if (input_style)
|
||||
create_input_style (input_style);
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
void
|
||||
fe_apply_theme_to_toplevel (GtkWidget *window)
|
||||
{
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
fe_win32_apply_native_titlebar (window, fe_dark_mode_is_enabled ());
|
||||
}
|
||||
|
||||
gboolean
|
||||
fe_dark_mode_is_enabled_for (unsigned int mode)
|
||||
{
|
||||
@@ -625,7 +705,7 @@ fe_init (void)
|
||||
GtkSettings *settings;
|
||||
|
||||
palette_load ();
|
||||
palette_apply_dark_mode (fe_dark_mode_is_enabled ());
|
||||
fe_apply_theme_for_mode (prefs.hex_gui_dark_mode, NULL);
|
||||
key_init ();
|
||||
pixmaps_init ();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user