From 4551509af1e5e3825646231530c31d2840a85ca3 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 6 May 2010 20:35:52 +0100 Subject: [PATCH] Make it easy for apps to have dark themes Some types of applications would benefit from having "dark" themes, usually black backgrounds, such as: * Movie players * Photo management and display applications To make it easy for those applications to prefer a dark theme, we're adding the "gtk-application-prefer-dark-theme" GtkSetting, which will make the theme loading code automatically look for a "gtkrc-dark" file in the same directory you would usually find a gtkrc file. the same name and a "-dark" suffix. If no "-dark" gtkrc variant is available, the normal gtkrc will be used. https://bugzilla.gnome.org/show_bug.cgi?id=617955 --- demos/gtk-demo/appwindow.c | 16 +++++++++ docs/reference/gtk/tmpl/gtkrc.sgml | 15 +++++++++ gtk/gtkrc.c | 53 +++++++++++++++++++++++------- gtk/gtksettings.c | 29 +++++++++++++++- 4 files changed, 100 insertions(+), 13 deletions(-) diff --git a/demos/gtk-demo/appwindow.c b/demos/gtk-demo/appwindow.c index b934be8d2f..2f62d63df7 100644 --- a/demos/gtk-demo/appwindow.c +++ b/demos/gtk-demo/appwindow.c @@ -19,6 +19,16 @@ activate_action (GtkAction *action) GtkWidget *dialog; + if (g_str_equal (name, "DarkTheme")) + { + gboolean value = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + GtkSettings *settings = gtk_settings_get_default (); + + g_object_set (G_OBJECT (settings), + "gtk-application-prefer-dark-theme", value, + NULL); + return; + } dialog = gtk_message_dialog_new (GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, @@ -212,6 +222,11 @@ static GtkToggleActionEntry toggle_entries[] = { "Bold", /* tooltip */ G_CALLBACK (activate_action), TRUE }, /* is_active */ + { "DarkTheme", NULL, /* name, stock id */ + "_Prefer Dark Theme", NULL, /* label, accelerator */ + "Prefer Dark Theme", /* tooltip */ + G_CALLBACK (activate_action), + FALSE }, /* is_active */ }; static guint n_toggle_entries = G_N_ELEMENTS (toggle_entries); @@ -265,6 +280,7 @@ static const gchar *ui_info = " " " " " " +" " " " " " " " diff --git a/docs/reference/gtk/tmpl/gtkrc.sgml b/docs/reference/gtk/tmpl/gtkrc.sgml index 305bc63e36..0dce9d20a5 100644 --- a/docs/reference/gtk/tmpl/gtkrc.sgml +++ b/docs/reference/gtk/tmpl/gtkrc.sgml @@ -125,6 +125,21 @@ that GTK+ creates internally. +Theme gtkrc files + + +Theme RC files are loaded first from under the ~/.themes/, +then from the directory from gtk_rc_get_theme_dir(). The files looked at will +be gtk-3.0/gtkrc. + + +When the application prefers dark themes +(see the #GtkSettings:gtk-application-prefer-dark-theme property for details), +gtk-3.0/gtkrc-dark will be loaded first, and if not present +gtk-3.0/gtkrc will be loaded. + + + Optimizing RC Style Matches diff --git a/gtk/gtkrc.c b/gtk/gtkrc.c index a23a605785..42963a1086 100644 --- a/gtk/gtkrc.c +++ b/gtk/gtkrc.c @@ -117,9 +117,10 @@ struct _GtkRcContext /* The files we have parsed, to reread later if necessary */ GSList *rc_files; - gchar *theme_name; - gchar *key_theme_name; - gchar *font_name; + gchar *theme_name; + gboolean prefer_dark_theme; + gchar *key_theme_name; + gchar *font_name; gchar **pixmap_path; @@ -160,9 +161,10 @@ static GtkStyle * gtk_rc_style_to_style (GtkRcContext *context, static GtkStyle* gtk_rc_init_style (GtkRcContext *context, GSList *rc_styles); static void gtk_rc_parse_default_files (GtkRcContext *context); -static void gtk_rc_parse_named (GtkRcContext *context, +static gboolean gtk_rc_parse_named (GtkRcContext *context, const gchar *name, - const gchar *type); + const gchar *type, + const gchar *variant); static void gtk_rc_context_parse_file (GtkRcContext *context, const gchar *filename, gint priority, @@ -624,6 +626,7 @@ gtk_rc_settings_changed (GtkSettings *settings, { gchar *new_theme_name; gchar *new_key_theme_name; + gboolean new_prefer_dark_theme; if (context->reloading) return; @@ -631,12 +634,14 @@ gtk_rc_settings_changed (GtkSettings *settings, g_object_get (settings, "gtk-theme-name", &new_theme_name, "gtk-key-theme-name", &new_key_theme_name, + "gtk-application-prefer-dark-theme", &new_prefer_dark_theme, NULL); if ((new_theme_name != context->theme_name && !(new_theme_name && context->theme_name && strcmp (new_theme_name, context->theme_name) == 0)) || (new_key_theme_name != context->key_theme_name && - !(new_key_theme_name && context->key_theme_name && strcmp (new_key_theme_name, context->key_theme_name) == 0))) + !(new_key_theme_name && context->key_theme_name && strcmp (new_key_theme_name, context->key_theme_name) == 0)) || + new_prefer_dark_theme != context->prefer_dark_theme) { gtk_rc_reparse_all_for_settings (settings, TRUE); } @@ -692,6 +697,7 @@ gtk_rc_context_get (GtkSettings *settings) "gtk-key-theme-name", &context->key_theme_name, "gtk-font-name", &context->font_name, "color-hash", &context->color_hash, + "gtk-application-prefer-dark-theme", &context->prefer_dark_theme, NULL); g_signal_connect (settings, @@ -710,6 +716,10 @@ gtk_rc_context_get (GtkSettings *settings) "notify::color-hash", G_CALLBACK (gtk_rc_color_hash_changed), context); + g_signal_connect (settings, + "notify::gtk-application-prefer-dark-theme", + G_CALLBACK (gtk_rc_settings_changed), + context); context->pixmap_path = NULL; @@ -785,22 +795,27 @@ _gtk_rc_context_destroy (GtkSettings *settings) settings->rc_context = NULL; } -static void +static gboolean gtk_rc_parse_named (GtkRcContext *context, const gchar *name, - const gchar *type) + const gchar *type, + const gchar *variant) { gchar *path = NULL; const gchar *home_dir; gchar *subpath; + gboolean retval; + + retval = FALSE; if (type) subpath = g_strconcat ("gtk-3.0-", type, G_DIR_SEPARATOR_S "gtkrc", NULL); else - subpath = g_strdup ("gtk-3.0" G_DIR_SEPARATOR_S "gtkrc"); - + subpath = g_strconcat ("gtk-3.0" G_DIR_SEPARATOR_S "gtkrc", + variant, NULL); + /* First look in the users home directory */ home_dir = g_get_home_dir (); @@ -831,9 +846,12 @@ gtk_rc_parse_named (GtkRcContext *context, { gtk_rc_context_parse_file (context, path, GTK_PATH_PRIO_THEME, FALSE); g_free (path); + retval = TRUE; } g_free (subpath); + + return retval; } static void @@ -1824,12 +1842,23 @@ gtk_rc_reparse_all_for_settings (GtkSettings *settings, g_object_get (context->settings, "gtk-theme-name", &context->theme_name, "gtk-key-theme-name", &context->key_theme_name, + "gtk-application-prefer-dark-theme", &context->prefer_dark_theme, NULL); if (context->theme_name && context->theme_name[0]) - gtk_rc_parse_named (context, context->theme_name, NULL); + { + if (context->prefer_dark_theme) + { + if (!gtk_rc_parse_named (context, context->theme_name, NULL, "-dark")) + gtk_rc_parse_named (context, context->theme_name, NULL, NULL); + } + else + { + gtk_rc_parse_named (context, context->theme_name, NULL, NULL); + } + } if (context->key_theme_name && context->key_theme_name[0]) - gtk_rc_parse_named (context, context->key_theme_name, "key"); + gtk_rc_parse_named (context, context->key_theme_name, "key", NULL); context->reloading = FALSE; diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c index a7ca546a08..99dcb844ee 100644 --- a/gtk/gtksettings.c +++ b/gtk/gtksettings.c @@ -125,7 +125,8 @@ enum { PROP_ENABLE_TOOLTIPS, PROP_TOOLBAR_STYLE, PROP_TOOLBAR_ICON_SIZE, - PROP_AUTO_MNEMONICS + PROP_AUTO_MNEMONICS, + PROP_APPLICATION_PREFER_DARK_THEME }; @@ -1017,6 +1018,32 @@ gtk_settings_class_init (GtkSettingsClass *class) GTK_PARAM_READWRITE), NULL); g_assert (result == PROP_AUTO_MNEMONICS); + + /** + * GtkSettings:gtk-application-prefer-dark-theme: + * + * Whether the application prefers to use a dark theme. If a GTK+ theme + * includes a dark variant, it will be used instead of the configured + * theme. + * + * Some applications benefit from minimizing the amount of light pollution that + * interferes with the content. Good candidates for dark themes are photo and + * video editors that make the actual content get all the attention and minimize + * the distraction of the chrome. + * + * Dark themes should not be used for documents, where large spaces are white/light + * and the dark chrome creates too much contrast (web browser, text editor...). + * + * Since: 2.22 + */ + result = settings_install_property_parser (class, + g_param_spec_boolean ("gtk-application-prefer-dark-theme", + P_("Application prefers a dark theme"), + P_("Whether the application prefers to have a dark theme."), + FALSE, + GTK_PARAM_READWRITE), + NULL); + g_assert (result == PROP_APPLICATION_PREFER_DARK_THEME); } static void