[gimp/gtk3-port: 135/444] Port theme and gtkrc file loading to CSS files using GtkCssProvider



commit 02a07638f3528b8e047fadbe695e7b3a57fc76f1
Author: Michael Natterer <mitch gimp org>
Date:   Wed Dec 29 15:16:23 2010 +0100

    Port theme and gtkrc file loading to CSS files using GtkCssProvider

 app/gui/themes.c |  199 +++++++++++++++++++-----------------------------------
 libgimp/gimpui.c |  136 +++++++++----------------------------
 2 files changed, 100 insertions(+), 235 deletions(-)
---
diff --git a/app/gui/themes.c b/app/gui/themes.c
index 8bf9d61..54cf671 100644
--- a/app/gui/themes.c
+++ b/app/gui/themes.c
@@ -52,22 +52,11 @@ static void   themes_theme_change_notify (GimpGuiConfig          *config,
                                           GParamSpec             *pspec,
                                           Gimp                   *gimp);
 
-static void   themes_fix_pixbuf_style    (void);
-static void   themes_draw_pixbuf_layout  (GtkStyle               *style,
-                                          GdkWindow              *window,
-                                          GtkStateType            state_type,
-                                          gboolean                use_text,
-                                          GdkRectangle           *area,
-                                          GtkWidget              *widget,
-                                          const gchar            *detail,
-                                          gint                    x,
-                                          gint                    y,
-                                          PangoLayout            *layout);
 
 /*  private variables  */
 
-static GHashTable    *themes_hash        = NULL;
-static GtkStyleClass *pixbuf_style_class = NULL;
+static GHashTable       *themes_hash           = NULL;
+static GtkStyleProvider *themes_style_provider = NULL;
 
 
 /*  public functions  */
@@ -76,7 +65,6 @@ void
 themes_init (Gimp *gimp)
 {
   GimpGuiConfig *config;
-  gchar         *themerc;
 
   g_return_if_fail (GIMP_IS_GIMP (gimp));
 
@@ -143,17 +131,27 @@ themes_init (Gimp *gimp)
       g_list_free_full (path, (GDestroyNotify) g_object_unref);
     }
 
-  themes_apply_theme (gimp, config->theme);
 
-  themerc = gimp_personal_rc_file ("themerc");
-  gtk_rc_parse (themerc);
-  g_free (themerc);
+  g_object_set (gtk_settings_get_for_screen (gdk_screen_get_default ()),
+                "gtk-application-prefer-dark-theme", TRUE,
+                NULL);
+
+  themes_style_provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
 
-  themes_fix_pixbuf_style ();
+  /*  Use GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1 so theme files
+   *  override default styles provided by widgets themselves.
+   */
+  gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+                                             themes_style_provider,
+                                             GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1);
+
+  g_object_unref (themes_style_provider);
 
   g_signal_connect (config, "notify::theme",
                     G_CALLBACK (themes_theme_change_notify),
                     gimp);
+
+  themes_theme_change_notify (config, NULL, gimp);
 }
 
 void
@@ -171,7 +169,7 @@ themes_exit (Gimp *gimp)
       themes_hash = NULL;
     }
 
-  g_clear_pointer (&pixbuf_style_class, g_type_class_unref);
+  g_clear_object (&themes_style_provider);
 }
 
 gchar **
@@ -275,18 +273,18 @@ static void
 themes_apply_theme (Gimp        *gimp,
                     const gchar *theme_name)
 {
-  GFile         *themerc;
+  GFile         *theme_css;
   GOutputStream *output;
   GError        *error = NULL;
 
   g_return_if_fail (GIMP_IS_GIMP (gimp));
 
-  themerc = gimp_directory_file ("themerc", NULL);
+  theme_css = gimp_directory_file ("theme.css", NULL);
 
   if (gimp->be_verbose)
-    g_print ("Writing '%s'\n", gimp_file_get_utf8_name (themerc));
+    g_print ("Writing '%s'\n", gimp_file_get_utf8_name (theme_css));
 
-  output = G_OUTPUT_STREAM (g_file_replace (themerc,
+  output = G_OUTPUT_STREAM (g_file_replace (theme_css,
                                             NULL, FALSE, G_FILE_CREATE_NONE,
                                             NULL, &error));
   if (! output)
@@ -297,63 +295,67 @@ themes_apply_theme (Gimp        *gimp,
   else
     {
       GFile *theme_dir = themes_get_theme_dir (gimp, theme_name);
-      GFile *gtkrc_theme;
-      GFile *gtkrc_user;
-      gchar *esc_gtkrc_theme;
-      gchar *esc_gtkrc_user;
+      GFile *css_theme;
+      GFile *css_user;
+      gchar *esc_css_theme;
+      gchar *esc_css_user;
       gchar *tmp;
 
       if (theme_dir)
         {
-          gtkrc_theme = g_file_get_child (theme_dir, "gtkrc");
+          css_theme = g_file_get_child (theme_dir, "gimp.css");
         }
       else
         {
-          /*  get the hardcoded default theme gtkrc  */
-          gtkrc_theme = g_file_new_for_path (gimp_gtkrc ());
+          tmp = g_build_filename (gimp_data_directory (),
+                                  "themes", "Default", "gimp.css",
+                                  NULL);
+          css_theme = g_file_new_for_path (tmp);
+          g_free (tmp);
         }
 
-      gtkrc_user = gimp_directory_file ("gtkrc", NULL);
+      css_user = gimp_directory_file ("gimp.css", NULL);
 
-      tmp = g_file_get_path (gtkrc_theme);
-      esc_gtkrc_theme = g_strescape (tmp, NULL);
+      tmp = g_file_get_path (css_theme);
+      esc_css_theme = g_strescape (tmp, NULL);
       g_free (tmp);
 
-      tmp = g_file_get_path (gtkrc_user);
-      esc_gtkrc_user = g_strescape (tmp, NULL);
+      tmp = g_file_get_path (css_user);
+      esc_css_user = g_strescape (tmp, NULL);
       g_free (tmp);
 
       if (! g_output_stream_printf
             (output, NULL, NULL, &error,
-             "# GIMP themerc\n"
-             "#\n"
-             "# This file is written on GIMP startup and on every theme change.\n"
-             "# It is NOT supposed to be edited manually. Edit your personal\n"
-             "# gtkrc file instead (%s).\n"
+             "/* GIMP theme.css\n"
+             " *\n"
+             " * This file is written on GIMP startup and on every theme change.\n"
+             " * It is NOT supposed to be edited manually. Edit your personal\n"
+             " * gimp.css file instead (%s).\n"
+             " */\n"
              "\n"
-             "include \"%s\"\n"
-             "include \"%s\"\n"
+             "@import url(\"%s\");\n"
+             "@import url(\"%s\");\n"
              "\n"
-             "# end of themerc\n",
-             gimp_file_get_utf8_name (gtkrc_user),
-             esc_gtkrc_theme,
-             esc_gtkrc_user) ||
+             "/* end of theme.css */\n",
+             gimp_file_get_utf8_name (css_user),
+             esc_css_theme,
+             esc_css_user) ||
           ! g_output_stream_close (output, NULL, &error))
         {
           gimp_message (gimp, NULL, GIMP_MESSAGE_ERROR,
                         _("Error writing '%s': %s"),
-                        gimp_file_get_utf8_name (themerc), error->message);
+                        gimp_file_get_utf8_name (theme_css), error->message);
           g_clear_error (&error);
         }
 
-      g_free (esc_gtkrc_theme);
-      g_free (esc_gtkrc_user);
-      g_object_unref (gtkrc_theme);
-      g_object_unref (gtkrc_user);
+      g_free (esc_css_theme);
+      g_free (esc_css_user);
+      g_object_unref (css_theme);
+      g_object_unref (css_user);
       g_object_unref (output);
     }
 
-  g_object_unref (themerc);
+  g_object_unref (theme_css);
 }
 
 static void
@@ -380,89 +382,26 @@ themes_theme_change_notify (GimpGuiConfig *config,
                             GParamSpec    *pspec,
                             Gimp          *gimp)
 {
-  themes_apply_theme (gimp, config->theme);
+  GFile  *theme_css;
+  GError *error = NULL;
 
-  gtk_rc_reparse_all ();
+  themes_apply_theme (gimp, config->theme);
 
-  themes_fix_pixbuf_style ();
-}
+  theme_css = gimp_directory_file ("theme.css", NULL);
 
-static void
-themes_fix_pixbuf_style (void)
-{
-  /* This is a "quick'n dirty" trick to get appropriate colors for
-   * themes in GTK+2, and in particular dark themes which would display
-   * insensitive items with a barely readable layout.
-   *
-   * This piece of code partly duplicates code from GTK+2 (slightly
-   * modified to get readable insensitive items) and will likely have to
-   * be removed for GIMP 3.
-   *
-   * See https://bugzilla.gnome.org/show_bug.cgi?id=770424
-   */
+  if (gimp->be_verbose)
+    g_print ("Parsing '%s'\n",
+             gimp_file_get_utf8_name (theme_css));
 
-  if (! pixbuf_style_class)
+  if (! gtk_css_provider_load_from_file (GTK_CSS_PROVIDER (themes_style_provider),
+                                         theme_css, &error))
     {
-      GType type = g_type_from_name ("PixbufStyle");
-
-      if (type)
-        {
-          pixbuf_style_class = g_type_class_ref (type);
-
-          if (pixbuf_style_class)
-            pixbuf_style_class->draw_layout = themes_draw_pixbuf_layout;
-        }
+      g_printerr ("%s: error parsing %s: %s\n", G_STRFUNC,
+                  gimp_file_get_utf8_name (theme_css), error->message);
+      g_clear_error (&error);
     }
-}
-
-static void
-themes_draw_pixbuf_layout (GtkStyle      *style,
-                           GdkWindow     *window,
-                           GtkStateType   state_type,
-                           gboolean       use_text,
-                           GdkRectangle  *area,
-                           GtkWidget     *widget,
-                           const gchar   *detail,
-                           gint           x,
-                           gint           y,
-                           PangoLayout   *layout)
-{
-  GdkGC *gc;
-
-  gc = use_text ? style->text_gc[state_type] : style->fg_gc[state_type];
-
-  if (area)
-    gdk_gc_set_clip_rectangle (gc, area);
-
-  if (state_type == GTK_STATE_INSENSITIVE)
-    {
-      GdkGC       *copy = gdk_gc_new (window);
-      GdkGCValues  orig;
-      GdkColor     fore;
-      guint16      r, g, b;
 
-      gdk_gc_copy (copy, gc);
-      gdk_gc_get_values (gc, &orig);
-
-      r = 0x40 + (((orig.foreground.pixel >> 16) & 0xff) >> 1);
-      g = 0x40 + (((orig.foreground.pixel >>  8) & 0xff) >> 1);
-      b = 0x40 + (((orig.foreground.pixel >>  0) & 0xff) >> 1);
-
-      fore.pixel = (r << 16) | (g << 8) | b;
-      fore.red   = r * 257;
-      fore.green = g * 257;
-      fore.blue  = b * 257;
-
-      gdk_gc_set_foreground (copy, &fore);
-      gdk_draw_layout (window, copy, x, y, layout);
-
-      g_object_unref (copy);
-    }
-  else
-    {
-      gdk_draw_layout (window, gc, x, y, layout);
-    }
+  g_object_unref (theme_css);
 
-  if (area)
-    gdk_gc_set_clip_rectangle (gc, NULL);
+  gtk_style_context_reset_widgets (gdk_screen_get_default ());
 }
diff --git a/libgimp/gimpui.c b/libgimp/gimpui.c
index d433ae5..78ea044 100644
--- a/libgimp/gimpui.c
+++ b/libgimp/gimpui.c
@@ -66,19 +66,6 @@ static void      gimp_window_transient_realized (GtkWidget     *window,
 static gboolean  gimp_window_set_transient_for  (GtkWindow     *window,
                                                  GdkWindow     *parent);
 
-static void      gimp_ui_theme_changed          (void);
-static void      gimp_ui_fix_pixbuf_style       (void);
-static void      gimp_ui_draw_pixbuf_layout     (GtkStyle      *style,
-                                                 GdkWindow     *window,
-                                                 GtkStateType   state_type,
-                                                 gboolean       use_text,
-                                                 GdkRectangle  *area,
-                                                 GtkWidget     *widget,
-                                                 const gchar   *detail,
-                                                 gint           x,
-                                                 gint           y,
-                                                 PangoLayout   *layout);
-
 
 static gboolean gimp_ui_initialized = FALSE;
 
@@ -107,10 +94,12 @@ void
 gimp_ui_init (const gchar *prog_name,
               gboolean     preview)
 {
-  const gchar  *display_name;
-  gchar        *themerc;
-  GFileMonitor *rc_monitor;
-  GFile        *file;
+  const gchar    *display_name;
+  GtkCssProvider *css_provider;
+  gchar          *theme_css;
+  GFileMonitor   *css_monitor;
+  GFile          *file;
+  GError         *error = NULL;
 
   g_return_if_fail (prog_name != NULL);
 
@@ -143,18 +132,36 @@ gimp_ui_init (const gchar *prog_name,
 
   gtk_init (NULL, NULL);
 
-  themerc = gimp_personal_rc_file ("themerc");
-  gtk_rc_parse (themerc);
+  css_provider = gtk_css_provider_new ();
+
+  gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+                                             GTK_STYLE_PROVIDER (css_provider),
+                                             GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+  g_object_unref (css_provider);
+
+  theme_css = gimp_personal_rc_file ("theme.css");
+
+  if (! gtk_css_provider_load_from_path (css_provider,
+                                         theme_css, &error))
+    {
+      g_printerr ("%s: error parsing %s: %s\n", G_STRFUNC,
+                  gimp_filename_to_utf8 (theme_css), error->message);
+      g_clear_error (&error);
+    }
 
-  file = g_file_new_for_path (themerc);
-  g_free (themerc);
+  file = g_file_new_for_path (theme_css);
+  g_free (theme_css);
 
-  rc_monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, NULL);
+  css_monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, NULL);
   g_object_unref (file);
 
-  g_signal_connect (rc_monitor, "changed",
-                    G_CALLBACK (gimp_ui_theme_changed),
+#if 0
+  /* FIXME CSS: do we still need such code on gtk3? */
+  g_signal_connect (css_monitor, "changed",
+                    G_CALLBACK (gtk_rc_reparse_all),
                     NULL);
+#endif
 
   gdk_set_program_class (gimp_wm_class ());
 
@@ -401,84 +408,3 @@ gimp_window_set_transient_for (GtkWindow *window,
 
   return FALSE;
 }
-
-static void
-gimp_ui_theme_changed (void)
-{
-  gtk_rc_reparse_all ();
-
-  gimp_ui_fix_pixbuf_style ();
-}
-
-static void
-gimp_ui_fix_pixbuf_style (void)
-{
-  /*  Same hack as in app/gui/themes.c, to be removed for GTK+ 3.x  */
-
-  static GtkStyleClass *pixbuf_style_class = NULL;
-
-  if (! pixbuf_style_class)
-    {
-      GType type = g_type_from_name ("PixbufStyle");
-
-      if (type)
-        {
-          pixbuf_style_class = g_type_class_ref (type);
-
-          if (pixbuf_style_class)
-            pixbuf_style_class->draw_layout = gimp_ui_draw_pixbuf_layout;
-        }
-    }
-}
-
-static void
-gimp_ui_draw_pixbuf_layout (GtkStyle      *style,
-                            GdkWindow     *window,
-                            GtkStateType   state_type,
-                            gboolean       use_text,
-                            GdkRectangle  *area,
-                            GtkWidget     *widget,
-                            const gchar   *detail,
-                            gint           x,
-                            gint           y,
-                            PangoLayout   *layout)
-{
-  GdkGC *gc;
-
-  gc = use_text ? style->text_gc[state_type] : style->fg_gc[state_type];
-
-  if (area)
-    gdk_gc_set_clip_rectangle (gc, area);
-
-  if (state_type == GTK_STATE_INSENSITIVE)
-    {
-      GdkGC       *copy = gdk_gc_new (window);
-      GdkGCValues  orig;
-      GdkColor     fore;
-      guint16      r, g, b;
-
-      gdk_gc_copy (copy, gc);
-      gdk_gc_get_values (gc, &orig);
-
-      r = 0x40 + (((orig.foreground.pixel >> 16) & 0xff) >> 1);
-      g = 0x40 + (((orig.foreground.pixel >>  8) & 0xff) >> 1);
-      b = 0x40 + (((orig.foreground.pixel >>  0) & 0xff) >> 1);
-
-      fore.pixel = (r << 16) | (g << 8) | b;
-      fore.red   = r * 257;
-      fore.green = g * 257;
-      fore.blue  = b * 257;
-
-      gdk_gc_set_foreground (copy, &fore);
-      gdk_draw_layout (window, copy, x, y, layout);
-
-      g_object_unref (copy);
-    }
-  else
-    {
-      gdk_draw_layout (window, gc, x, y, layout);
-    }
-
-  if (area)
-    gdk_gc_set_clip_rectangle (gc, NULL);
-}


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