Fixed the GTK3 theme dropdown population to include all expected sources again (ZoiteChat local store, user local themes, and system theme dirs), which resolves the “messed up selector” behavior from the previous change.

Restored proper initial selection logic so the dropdown now prefers saved gui_gtk3_theme_name when present, and otherwise falls back to the current GTK gtk-theme-name.

    Fixed selection UX by not forcing index 0; it starts unselected and selects only if a real match is found. Also made Apply button sensitivity follow actual selection state.

    Updated the status text to reflect mixed-source theme discovery and added cleanup for allocated selection strings/path entries in this code path.
This commit is contained in:
2026-02-26 00:47:04 -07:00
parent a796f78884
commit 1c1110847c
5 changed files with 147 additions and 12 deletions

View File

@@ -419,6 +419,7 @@ const struct prefs vars[] =
{"gui_input_nick", P_OFFINT (hex_gui_input_nick), TYPE_BOOL},
{"gui_input_spell", P_OFFINT (hex_gui_input_spell), TYPE_BOOL},
{"gui_input_style", P_OFFINT (hex_gui_input_style), TYPE_BOOL},
{"gui_gtk3_theme_name", P_OFFSET (hex_gui_gtk3_theme_name), TYPE_STR},
{"gui_join_dialog", P_OFFINT (hex_gui_join_dialog), TYPE_BOOL},
{"gui_lagometer", P_OFFINT (hex_gui_lagometer), TYPE_INT},
{"gui_lang", P_OFFINT (hex_gui_lang), TYPE_INT},

View File

@@ -297,6 +297,7 @@ struct zoitechatprefs
char hex_dcc_completed_dir[PATHLEN + 1];
char hex_dcc_dir[PATHLEN + 1];
char hex_dcc_ip[DOMAINLEN + 1];
char hex_gui_gtk3_theme_name[128];
char hex_gui_ulist_doubleclick[256];
char hex_input_command_char[4];
char hex_irc_extra_hilight[300];

View File

@@ -590,6 +590,109 @@ fe_system_prefers_dark (void)
static gboolean auto_dark_mode_enabled = FALSE;
static gboolean dark_mode_state_initialized = FALSE;
static GtkCssProvider *gtk3_theme_provider = NULL;
static char *gtk3_theme_provider_name = NULL;
static gboolean gtk3_theme_provider_dark = FALSE;
gboolean
fe_apply_gtk3_theme (const char *theme_name, GError **error)
{
GdkScreen *screen = gdk_screen_get_default ();
char *theme_dir = NULL;
char *gtk3_dir = NULL;
char *gtk_css = NULL;
char *gtk_dark_css = NULL;
const char *selected_css = NULL;
gboolean dark = fe_dark_mode_is_enabled ();
GList *toplevels, *node;
if (!theme_name || !*theme_name)
{
if (gtk3_theme_provider && screen)
{
gtk_style_context_remove_provider_for_screen (
screen,
GTK_STYLE_PROVIDER (gtk3_theme_provider));
}
g_clear_object (&gtk3_theme_provider);
g_clear_pointer (&gtk3_theme_provider_name, g_free);
gtk3_theme_provider_dark = FALSE;
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 TRUE;
}
if (gtk3_theme_provider_name
&& g_strcmp0 (gtk3_theme_provider_name, theme_name) == 0
&& gtk3_theme_provider_dark == dark)
{
return TRUE;
}
theme_dir = g_build_filename (get_xdir (), "gtk3-themes", theme_name, NULL);
gtk3_dir = g_build_filename (theme_dir, "gtk-3.0", NULL);
gtk_css = g_build_filename (gtk3_dir, "gtk.css", NULL);
gtk_dark_css = g_build_filename (gtk3_dir, "gtk-dark.css", NULL);
if (!g_file_test (gtk_css, G_FILE_TEST_IS_REGULAR))
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT,
_("GTK3 theme '%s' is missing gtk-3.0/gtk.css."), theme_name);
g_free (gtk_dark_css);
g_free (gtk_css);
g_free (gtk3_dir);
g_free (theme_dir);
return FALSE;
}
if (dark && g_file_test (gtk_dark_css, G_FILE_TEST_IS_REGULAR))
selected_css = gtk_dark_css;
else
selected_css = gtk_css;
if (!gtk3_theme_provider)
gtk3_theme_provider = gtk_css_provider_new ();
if (!gtk_css_provider_load_from_path (gtk3_theme_provider, selected_css, error))
{
g_free (gtk_dark_css);
g_free (gtk_css);
g_free (gtk3_dir);
g_free (theme_dir);
return FALSE;
}
if (screen)
{
gtk_style_context_add_provider_for_screen (
screen,
GTK_STYLE_PROVIDER (gtk3_theme_provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
gtk_style_context_reset_widgets (screen);
}
g_free (gtk3_theme_provider_name);
gtk3_theme_provider_name = g_strdup (theme_name);
gtk3_theme_provider_dark = dark;
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);
g_free (gtk_dark_css);
g_free (gtk_css);
g_free (gtk3_dir);
g_free (theme_dir);
return TRUE;
}
static void
fe_set_gtk_prefer_dark_theme (gboolean dark)
{
@@ -722,6 +825,12 @@ fe_apply_theme_for_mode (unsigned int mode, gboolean *palette_changed)
if (input_style)
create_input_style (input_style);
if (!fe_apply_gtk3_theme (prefs.hex_gui_gtk3_theme_name, NULL)
&& prefs.hex_gui_gtk3_theme_name[0] != '\0')
{
fe_message (_("Failed to apply configured GTK3 theme from gtk3-themes."), FE_MSG_ERROR);
}
/* Existing toplevel windows also need the class refreshed for selectors like
* .zoitechat-dark / .zoitechat-light to update immediately. */
toplevels = gtk_window_list_toplevels ();

View File

@@ -193,6 +193,7 @@ gboolean fe_dark_mode_state_is_initialized (void);
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);
gboolean fe_apply_gtk3_theme (const char *theme_name, GError **error);
void fe_apply_theme_to_toplevel (GtkWidget *window);
#define SPELL_ENTRY_GET_TEXT(e) ((char *)(gtk_entry_get_text (GTK_ENTRY(e))))

View File

@@ -72,6 +72,7 @@ typedef struct
GtkWidget *gtk3_combo;
GtkWidget *gtk3_import_button;
GtkWidget *gtk3_apply_button;
GtkWidget *gtk3_use_system_button;
GtkWidget *gtk3_status_label;
} setup_theme_ui;
@@ -2068,12 +2069,14 @@ setup_theme_populate_gtk3 (setup_theme_ui *ui)
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (ui->gtk3_combo), g_ptr_array_index (names, i));
settings = gtk_settings_get_default ();
if (settings)
if (prefs.hex_gui_gtk3_theme_name[0] != '\0')
current_theme = g_strdup (prefs.hex_gui_gtk3_theme_name);
else if (settings)
g_object_get (settings, "gtk-theme-name", &current_theme, NULL);
if (names->len > 0)
{
gtk_combo_box_set_active (GTK_COMBO_BOX (ui->gtk3_combo), 0);
gtk_combo_box_set_active (GTK_COMBO_BOX (ui->gtk3_combo), -1);
if (current_theme)
{
for (i = 0; i < names->len; i++)
@@ -2087,9 +2090,10 @@ setup_theme_populate_gtk3 (setup_theme_ui *ui)
}
}
gtk_widget_set_sensitive (ui->gtk3_apply_button, names->len > 0);
gtk_widget_set_sensitive (ui->gtk3_apply_button,
gtk_combo_box_get_active (GTK_COMBO_BOX (ui->gtk3_combo)) >= 0);
gtk_label_set_text (GTK_LABEL (ui->gtk3_status_label),
names->len > 0 ? _("Select a GTK3 theme to activate for the interface.") : _("No GTK3 themes found."));
names->len > 0 ? _("Select a GTK3 theme to activate from the dropdown, or use the system GTK theme.") : _("No GTK3 themes found."));
g_ptr_array_free (names, TRUE);
g_hash_table_destroy (seen);
@@ -2169,28 +2173,42 @@ static void
setup_theme_gtk3_apply_cb (GtkWidget *button, gpointer user_data)
{
setup_theme_ui *ui = user_data;
GtkSettings *settings;
char *theme;
GError *error = NULL;
theme = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (ui->gtk3_combo));
if (!theme)
return;
settings = gtk_settings_get_default ();
if (!settings)
if (!fe_apply_gtk3_theme (theme, &error))
{
setup_theme_show_message (GTK_MESSAGE_ERROR, _("GTK settings are unavailable, cannot activate GTK3 theme."));
setup_theme_show_message (GTK_MESSAGE_ERROR,
error ? error->message : _("Failed to apply GTK3 theme."));
g_clear_error (&error);
g_free (theme);
return;
}
g_object_set (settings, "gtk-theme-name", theme, NULL);
gtk_label_set_text (GTK_LABEL (ui->gtk3_status_label), _("GTK3 theme activated for this session."));
setup_theme_show_message (GTK_MESSAGE_INFO, _("GTK3 theme activated. Application palette settings were not changed."));
safe_strcpy (prefs.hex_gui_gtk3_theme_name, theme, sizeof (prefs.hex_gui_gtk3_theme_name));
save_config ();
gtk_label_set_text (GTK_LABEL (ui->gtk3_status_label), _("GTK3 theme activated from ZoiteChat's local theme store."));
setup_theme_show_message (GTK_MESSAGE_INFO, _("GTK3 theme activated and saved."));
g_free (theme);
}
static void
setup_theme_gtk3_use_system_cb (GtkWidget *button, gpointer user_data)
{
setup_theme_ui *ui = user_data;
fe_apply_gtk3_theme (NULL, NULL);
prefs.hex_gui_gtk3_theme_name[0] = '\0';
save_config ();
gtk_label_set_text (GTK_LABEL (ui->gtk3_status_label), _("Using system GTK theme."));
setup_theme_show_message (GTK_MESSAGE_INFO, _("Using system GTK theme."));
}
static GtkWidget *
setup_create_theme_page (void)
{
@@ -2262,7 +2280,7 @@ setup_create_theme_page (void)
gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
gtk_container_add (GTK_CONTAINER (frame), hbox);
label = gtk_label_new (_("Import a GTK3 theme archive or select an installed GTK3 theme."));
label = gtk_label_new (_("Import a GTK3 theme archive or select a GTK3 theme installed in ZoiteChat's local theme store."));
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
@@ -2285,6 +2303,11 @@ setup_create_theme_page (void)
g_signal_connect (G_OBJECT (ui->gtk3_apply_button), "clicked",
G_CALLBACK (setup_theme_gtk3_apply_cb), ui);
ui->gtk3_use_system_button = gtk_button_new_with_mnemonic (_("Use _System GTK Theme"));
gtk_box_pack_start (GTK_BOX (button_box), ui->gtk3_use_system_button, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (ui->gtk3_use_system_button), "clicked",
G_CALLBACK (setup_theme_gtk3_use_system_cb), ui);
ui->gtk3_status_label = gtk_label_new (NULL);
gtk_widget_set_halign (ui->gtk3_status_label, GTK_ALIGN_START);
gtk_widget_set_valign (ui->gtk3_status_label, GTK_ALIGN_CENTER);