diff --git a/src/fe-gtk/fe-gtk.c b/src/fe-gtk/fe-gtk.c index 5345ab5f..9a1365c7 100644 --- a/src/fe-gtk/fe-gtk.c +++ b/src/fe-gtk/fe-gtk.c @@ -28,6 +28,7 @@ #ifdef WIN32 #include +#include #else #include #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 (); diff --git a/src/fe-gtk/fe-gtk.h b/src/fe-gtk/fe-gtk.h index 03e55508..626bfb2a 100644 --- a/src/fe-gtk/fe-gtk.h +++ b/src/fe-gtk/fe-gtk.h @@ -211,6 +211,8 @@ gboolean fe_dark_mode_is_enabled (void); gboolean fe_dark_mode_is_enabled_for (unsigned int mode); void fe_set_auto_dark_mode_state (gboolean enabled); void fe_refresh_auto_dark_mode (void); +gboolean fe_apply_theme_for_mode (unsigned int mode, gboolean *palette_changed); +void fe_apply_theme_to_toplevel (GtkWidget *window); #define SPELL_ENTRY_GET_TEXT(e) ((char *)(gtk_entry_get_text (GTK_ENTRY(e)))) #define SPELL_ENTRY_SET_TEXT(e,txt) gtk_entry_set_text(GTK_ENTRY(e),txt) diff --git a/src/fe-gtk/maingui.c b/src/fe-gtk/maingui.c index 5a59b876..ec5e6b6c 100644 --- a/src/fe-gtk/maingui.c +++ b/src/fe-gtk/maingui.c @@ -3944,6 +3944,7 @@ mg_create_topwindow (session *sess) mg_place_userlist_and_chanview (sess->gui); gtk_widget_show (win); + fe_apply_theme_to_toplevel (win); #ifdef G_OS_WIN32 parent_win = gtk_widget_get_window (win); @@ -4118,6 +4119,7 @@ mg_create_tabwindow (session *sess) mg_place_userlist_and_chanview (sess->gui); gtk_widget_show (win); + fe_apply_theme_to_toplevel (win); #ifdef G_OS_WIN32 parent_win = gtk_widget_get_window (win); @@ -4141,6 +4143,8 @@ mg_apply_setup (void) ((xtext_buffer *)sess->res->buffer)->needs_recalc = TRUE; if (!sess->gui->is_tab || !done_main) mg_place_userlist_and_chanview (sess->gui); + if (sess->gui->window) + fe_apply_theme_to_toplevel (sess->gui->window); if (sess->gui->is_tab) done_main = TRUE; list = list->next; diff --git a/src/fe-gtk/meson.build b/src/fe-gtk/meson.build index a845ab05..b66dfd73 100644 --- a/src/fe-gtk/meson.build +++ b/src/fe-gtk/meson.build @@ -77,6 +77,7 @@ zoitechat_gtk_ldflags = [] if host_machine.system() == 'windows' zoitechat_gtk_sources += 'notifications/notification-windows.c' + zoitechat_gtk_deps += cc.find_library('dwmapi', required: true) # TODO: mingw doesn't have these headers or libs # add_languages('cpp') diff --git a/src/fe-gtk/setup.c b/src/fe-gtk/setup.c index 0402e27e..84eff508 100644 --- a/src/fe-gtk/setup.c +++ b/src/fe-gtk/setup.c @@ -3059,7 +3059,9 @@ setup_apply (struct zoitechatprefs *pr) * the preference flips but the palette stays the same (aka: "nothing happens"). */ { - gboolean pal_changed = palette_apply_dark_mode (fe_dark_mode_is_enabled_for (prefs.hex_gui_dark_mode)); + gboolean pal_changed = FALSE; + + fe_apply_theme_for_mode (prefs.hex_gui_dark_mode, &pal_changed); if (prefs.hex_gui_dark_mode != old_dark_mode || pal_changed) color_change = TRUE; }