[gtk+] Make it easy for apps to have dark themes



commit 4551509af1e5e3825646231530c31d2840a85ca3
Author: Bastien Nocera <hadess hadess net>
Date:   Thu May 6 20:35:52 2010 +0100

    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 b934be8..2f62d63 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 =
 "      <menuitem action='Quit'/>"
 "    </menu>"
 "    <menu action='PreferencesMenu'>"
+"      <menuitem action='DarkTheme'/>"
 "      <menu action='ColorMenu'>"
 "	<menuitem action='Red'/>"
 "	<menuitem action='Green'/>"
diff --git a/docs/reference/gtk/tmpl/gtkrc.sgml b/docs/reference/gtk/tmpl/gtkrc.sgml
index 305bc63..0dce9d2 100644
--- a/docs/reference/gtk/tmpl/gtkrc.sgml
+++ b/docs/reference/gtk/tmpl/gtkrc.sgml
@@ -125,6 +125,21 @@ that GTK+ creates internally.
 
 </refsect2>
 
+<refsect2><title>Theme gtkrc files</title>
+<anchor id="theme-gtkrc-files"/>
+<para>
+Theme RC files are loaded first from under the <filename>~/.themes/</filename>,
+then from the directory from gtk_rc_get_theme_dir(). The files looked at will
+be <filename>gtk-3.0/gtkrc</filename>.
+</para>
+<para>
+When the application prefers dark themes
+(see the #GtkSettings:gtk-application-prefer-dark-theme property for details),
+<filename>gtk-3.0/gtkrc-dark</filename> will be loaded first, and if not present
+<filename>gtk-3.0/gtkrc</filename> will be loaded.
+</para>
+</refsect2>
+
 <refsect2>
 <anchor id="optimizing-rc-style-matches"/>
 <title>Optimizing RC Style Matches</title>
diff --git a/gtk/gtkrc.c b/gtk/gtkrc.c
index a23a605..42963a1 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 a7ca546..99dcb84 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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]