From 6310ab245ceb003dca1918a7264e8538befd78a1 Mon Sep 17 00:00:00 2001 From: deepend Date: Wed, 25 Feb 2026 20:39:48 -0700 Subject: [PATCH] Updated fe_apply_theme_for_mode() to immediately reapply fe_apply_theme_to_toplevel() across all currently-open GTK toplevel windows (gtk_window_list_toplevels()), so mode switches update existing windows without reopening them. Added/kept lifecycle call sites for main and detached/channel windows, with comments explaining that .zoitechat-dark / .zoitechat-light classes are required for GTK CSS selectors. This includes top/tab windows and server list/edit windows. Wired dialog/toplevel creation paths in src/fe-gtk/ to call fe_apply_theme_to_toplevel() (without duplicating platform logic), including common prompt/message dialogs and feature-specific dialogs (join, notify, setup, ignore/ban, etc.), each with the requested brief comment near the new call site. --- src/fe-gtk/banlist.c | 5 ++++- src/fe-gtk/fe-gtk.c | 16 +++++++++++++++- src/fe-gtk/gtkutil.c | 9 +++++++++ src/fe-gtk/ignoregui.c | 5 ++++- src/fe-gtk/joind.c | 3 +++ src/fe-gtk/maingui.c | 10 ++++++++++ src/fe-gtk/menu.c | 3 +++ src/fe-gtk/notifygui.c | 3 +++ src/fe-gtk/servlistgui.c | 19 +++++++++++++------ src/fe-gtk/setup.c | 6 ++++++ 10 files changed, 70 insertions(+), 9 deletions(-) diff --git a/src/fe-gtk/banlist.c b/src/fe-gtk/banlist.c index c8a21a02..c5be63bd 100644 --- a/src/fe-gtk/banlist.c +++ b/src/fe-gtk/banlist.c @@ -562,7 +562,10 @@ banlist_clear (GtkWidget * wid, banlist_info *banl) dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, - _("Are you sure you want to remove all listed items in %s?"), banl->sess->channel); + _("Are you sure you want to remove all listed items in %s?"), banl->sess->channel); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ + fe_apply_theme_to_toplevel (dialog); g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (banlist_clear_cb), banl); diff --git a/src/fe-gtk/fe-gtk.c b/src/fe-gtk/fe-gtk.c index ea7cefad..a694fd0d 100644 --- a/src/fe-gtk/fe-gtk.c +++ b/src/fe-gtk/fe-gtk.c @@ -105,6 +105,9 @@ create_msg_dialog (gchar *title, gchar *message) GtkWidget *dialog; dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "%s", message); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ + fe_apply_theme_to_toplevel (dialog); gtk_window_set_title (GTK_WINDOW (dialog), title); /* On Win32 we automatically have the icon. If we try to load it explicitly, it will look ugly for some reason. */ @@ -665,6 +668,7 @@ gboolean fe_apply_theme_for_mode (unsigned int mode, gboolean *palette_changed) { gboolean enabled = fe_dark_mode_is_enabled_for (mode); + GList *toplevels, *node; /* Apply the optional global GTK preference first, then reapply palette-driven * chat/input colors so Preferences > Colors continues to take precedence. */ @@ -681,6 +685,13 @@ fe_apply_theme_for_mode (unsigned int mode, gboolean *palette_changed) if (input_style) create_input_style (input_style); + /* Existing toplevel windows also need the class refreshed for selectors like + * .zoitechat-dark / .zoitechat-light to update immediately. */ + toplevels = gtk_window_list_toplevels (); + for (node = toplevels; node; node = node->next) + fe_apply_theme_to_toplevel (GTK_WIDGET (node->data)); + g_list_free (toplevels); + return enabled; } @@ -1068,7 +1079,10 @@ fe_message (char *msg, int flags) type = GTK_MESSAGE_INFO; dialog = gtk_message_dialog_new (GTK_WINDOW (parent_window), 0, type, - GTK_BUTTONS_OK, "%s", msg); + GTK_BUTTONS_OK, "%s", msg); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ + fe_apply_theme_to_toplevel (dialog); if (flags & FE_MSG_MARKUP) gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), msg); g_signal_connect (G_OBJECT (dialog), "response", diff --git a/src/fe-gtk/gtkutil.c b/src/fe-gtk/gtkutil.c index a2e64cd1..9b1264b8 100644 --- a/src/fe-gtk/gtkutil.c +++ b/src/fe-gtk/gtkutil.c @@ -977,6 +977,9 @@ fe_get_str (char *msg, char *def, void *callback, void *userdata) _("_Cancel"), GTK_RESPONSE_REJECT, _("_OK"), GTK_RESPONSE_ACCEPT, NULL); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ + fe_apply_theme_to_toplevel (dialog); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window)); gtk_box_set_homogeneous (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), TRUE); @@ -1072,6 +1075,9 @@ fe_get_int (char *msg, int def, void *callback, void *userdata) _("_Cancel"), GTK_RESPONSE_REJECT, _("_OK"), GTK_RESPONSE_ACCEPT, NULL); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ + fe_apply_theme_to_toplevel (dialog); gtk_box_set_homogeneous (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), TRUE); gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window)); @@ -1112,6 +1118,9 @@ fe_get_bool (char *title, char *prompt, void *callback, void *userdata) _("_No"), GTK_RESPONSE_REJECT, _("_Yes"), GTK_RESPONSE_ACCEPT, NULL); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ + fe_apply_theme_to_toplevel (dialog); gtk_box_set_homogeneous (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), TRUE); gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window)); diff --git a/src/fe-gtk/ignoregui.c b/src/fe-gtk/ignoregui.c index e0f8df4a..6f99cb77 100644 --- a/src/fe-gtk/ignoregui.c +++ b/src/fe-gtk/ignoregui.c @@ -294,7 +294,10 @@ ignore_clear_entry_clicked (GtkWidget * wid) dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, - _("Are you sure you want to remove all ignores?")); + _("Are you sure you want to remove all ignores?")); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ + fe_apply_theme_to_toplevel (dialog); g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (ignore_clear_cb), NULL); gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE); diff --git a/src/fe-gtk/joind.c b/src/fe-gtk/joind.c index ae07d3d5..22f96e10 100644 --- a/src/fe-gtk/joind.c +++ b/src/fe-gtk/joind.c @@ -129,6 +129,9 @@ joind_show_dialog (server *serv) char buf2[256]; serv->gui->joind_win = dialog1 = gtk_dialog_new (); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ + fe_apply_theme_to_toplevel (dialog1); g_snprintf(buf, sizeof(buf), _("Connection Complete - %s"), _(DISPLAY_NAME)); gtk_window_set_title (GTK_WINDOW (dialog1), buf); gtk_window_set_type_hint (GTK_WINDOW (dialog1), GDK_WINDOW_TYPE_HINT_DIALOG); diff --git a/src/fe-gtk/maingui.c b/src/fe-gtk/maingui.c index 648076ad..01366211 100644 --- a/src/fe-gtk/maingui.c +++ b/src/fe-gtk/maingui.c @@ -1362,6 +1362,9 @@ mg_tab_close (session *sess) GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL, _("This server still has %d channels or dialogs associated with it. " "Close them all?"), i); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ + fe_apply_theme_to_toplevel (dialog); g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (mg_tab_close_cb), sess); if (prefs.hex_gui_tab_layout) @@ -1459,6 +1462,9 @@ mg_open_quit_dialog (gboolean minimize_button) } dialog = gtk_dialog_new (); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ + fe_apply_theme_to_toplevel (dialog); gtk_container_set_border_width (GTK_CONTAINER (dialog), 6); gtk_window_set_title (GTK_WINDOW (dialog), _("Quit ZoiteChat?")); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window)); @@ -3681,6 +3687,8 @@ mg_create_topwindow (session *sess) mg_place_userlist_and_chanview (sess->gui); gtk_widget_show (win); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ fe_apply_theme_to_toplevel (win); #ifdef G_OS_WIN32 @@ -3857,6 +3865,8 @@ mg_create_tabwindow (session *sess) mg_place_userlist_and_chanview (sess->gui); gtk_widget_show (win); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ fe_apply_theme_to_toplevel (win); #ifdef G_OS_WIN32 diff --git a/src/fe-gtk/menu.c b/src/fe-gtk/menu.c index b94d1762..f27312fd 100644 --- a/src/fe-gtk/menu.c +++ b/src/fe-gtk/menu.c @@ -1520,6 +1520,9 @@ menu_join (GtkWidget * wid, gpointer none) _("_Cancel"), GTK_RESPONSE_REJECT, _("_OK"), GTK_RESPONSE_ACCEPT, NULL); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ + fe_apply_theme_to_toplevel (dialog); { GtkWidget *button; diff --git a/src/fe-gtk/notifygui.c b/src/fe-gtk/notifygui.c index 9099e8e9..ab4102b5 100644 --- a/src/fe-gtk/notifygui.c +++ b/src/fe-gtk/notifygui.c @@ -373,6 +373,9 @@ fe_notify_ask (char *nick, char *networks) LABEL_NOTIFY_CANCEL, GTK_RESPONSE_REJECT, LABEL_NOTIFY_OK, GTK_RESPONSE_ACCEPT, NULL); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ + fe_apply_theme_to_toplevel (dialog); if (parent_window) gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window)); gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE); diff --git a/src/fe-gtk/servlistgui.c b/src/fe-gtk/servlistgui.c index 1084577d..b01c7f09 100644 --- a/src/fe-gtk/servlistgui.c +++ b/src/fe-gtk/servlistgui.c @@ -781,12 +781,15 @@ servlist_deletenet_cb (GtkWidget *item, ircnet *net) if (!net) return; dialog = gtk_message_dialog_new (GTK_WINDOW (serverlist_win), - GTK_DIALOG_DESTROY_WITH_PARENT | - GTK_DIALOG_MODAL, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_OK_CANCEL, - _("Really remove network \"%s\" and all its servers?"), - net->name); + GTK_DIALOG_DESTROY_WITH_PARENT | + GTK_DIALOG_MODAL, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_OK_CANCEL, + _("Really remove network \"%s\" and all its servers?"), + net->name); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ + fe_apply_theme_to_toplevel (dialog); g_signal_connect (dialog, "response", G_CALLBACK (servlist_deletenetdialog_cb), net); gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE); @@ -1799,6 +1802,8 @@ servlist_open_edit (GtkWidget *parent, ircnet *net) gtk_window_set_modal (GTK_WINDOW (editwindow), TRUE); gtk_window_set_type_hint (GTK_WINDOW (editwindow), GDK_WINDOW_TYPE_HINT_DIALOG); gtk_window_set_role (GTK_WINDOW (editwindow), "editserv"); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ fe_apply_theme_to_toplevel (editwindow); vbox5 = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0); @@ -2079,6 +2084,8 @@ servlist_open_networks (void) gtk_window_set_default_size (GTK_WINDOW (servlist), netlist_win_width, netlist_win_height); gtk_window_set_role (GTK_WINDOW (servlist), "servlist"); gtk_window_set_type_hint (GTK_WINDOW (servlist), GDK_WINDOW_TYPE_HINT_DIALOG); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ fe_apply_theme_to_toplevel (servlist); if (current_sess) gtk_window_set_transient_for (GTK_WINDOW (servlist), GTK_WINDOW (current_sess->gui->window)); diff --git a/src/fe-gtk/setup.c b/src/fe-gtk/setup.c index 26c5625c..dc46013b 100644 --- a/src/fe-gtk/setup.c +++ b/src/fe-gtk/setup.c @@ -1759,6 +1759,9 @@ setup_theme_show_message (GtkMessageType message_type, const char *primary) dialog = gtk_message_dialog_new (GTK_WINDOW (setup_window), GTK_DIALOG_MODAL, message_type, GTK_BUTTONS_CLOSE, "%s", primary); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ + fe_apply_theme_to_toplevel (dialog); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } @@ -1849,6 +1852,9 @@ setup_theme_apply_cb (GtkWidget *button, gpointer user_data) dialog = gtk_message_dialog_new (GTK_WINDOW (setup_window), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL, "%s", _("Applying a theme will overwrite your current colors and event settings.\nContinue?")); + /* Window classes are required for GTK CSS selectors like + * .zoitechat-dark / .zoitechat-light. */ + fe_apply_theme_to_toplevel (dialog); response = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog);