[gtk+] settings: Provide a default style cascade per scale



commit 808bfe0a98ac4cd2e11ea4eed82a66470121c19b
Author: Benjamin Otte <otte redhat com>
Date:   Fri Feb 6 10:13:11 2015 +0100

    settings: Provide a default style cascade per scale
    
    This guarantees we only create 1 extra style cascade in total for hidpi
    and not one per style context.
    
    Style cascades are now nested like this:
    
    GtkSettings root cascade (scale == 1)
     |
     +-- GtkSettings per scale cascade (for any scale, no custom providers)
     |
     +-- GtkStyleContext custom cascade (for any scale, custom providers)
    
    This requires a bunch of care when changing cascade-related properties
    inside GtkStyleContext, so that it ends up with a properly setup
    cascade, but I think I got those cases right.
    
    The only thing we don't do yet is reverting to a GtkSettings cascade
    when the last custom provider is removed from a custom cascade.

 gtk/gtksettings.c        |   41 ++++++++++++++++++++++++++++--------
 gtk/gtksettingsprivate.h |    3 +-
 gtk/gtkstylecontext.c    |   52 +++++++++++++++++++++++++++------------------
 3 files changed, 65 insertions(+), 31 deletions(-)
---
diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c
index 6908675..e509b30 100644
--- a/gtk/gtksettings.c
+++ b/gtk/gtksettings.c
@@ -121,7 +121,7 @@ struct _GtkSettingsPrivate
   GData *queued_settings;      /* of type GtkSettingsValue* */
   GtkSettingsPropertyValue *property_values;
   GdkScreen *screen;
-  GtkStyleCascade *style_cascade;
+  GSList *style_cascades;
   GtkCssProvider *theme_provider;
   GtkCssProvider *key_theme_provider;
 };
@@ -294,7 +294,7 @@ gtk_settings_init (GtkSettings *settings)
   g_datalist_init (&priv->queued_settings);
   object_list = g_slist_prepend (object_list, settings);
 
-  priv->style_cascade = _gtk_style_cascade_new ();
+  priv->style_cascades = g_slist_prepend (NULL, _gtk_style_cascade_new ());
   priv->theme_provider = gtk_css_provider_new ();
 
   /* build up property array for all yet existing properties and queue
@@ -1745,24 +1745,46 @@ gtk_settings_finalize (GObject *object)
 
   settings_update_provider (priv->screen, &priv->theme_provider, NULL);
   settings_update_provider (priv->screen, &priv->key_theme_provider, NULL);
-  g_clear_object (&priv->style_cascade);
+  g_slist_free_full (priv->style_cascades, g_object_unref);
 
   G_OBJECT_CLASS (gtk_settings_parent_class)->finalize (object);
 }
 
 GtkStyleCascade *
-_gtk_settings_get_style_cascade (GtkSettings *settings)
+_gtk_settings_get_style_cascade (GtkSettings *settings,
+                                 gint         scale)
 {
+  GtkSettingsPrivate *priv = settings->priv;
+  GtkStyleCascade *new_cascade;
+  GSList *list;
+
   g_return_val_if_fail (GTK_IS_SETTINGS (settings), NULL);
 
-  return settings->priv->style_cascade;
+  for (list = priv->style_cascades; list; list = list->next)
+    {
+      if (_gtk_style_cascade_get_scale (list->data) == scale)
+        return list->data;
+    }
+
+  /* We are guaranteed to have the special cascade with scale == 1.
+   * It's created in gtk_settings_init()
+   */
+  g_assert (scale != 1);
+
+  new_cascade = _gtk_style_cascade_new ();
+  _gtk_style_cascade_set_parent (new_cascade, _gtk_settings_get_style_cascade (settings, 1));
+  _gtk_style_cascade_set_scale (new_cascade, scale);
+
+  priv->style_cascades = g_slist_prepend (priv->style_cascades, new_cascade);
+
+  return new_cascade;
 }
 
 static void
 settings_init_style (GtkSettings *settings)
 {
   static GtkCssProvider *css_provider = NULL;
-  GtkSettingsPrivate *priv = settings->priv;
+  GtkStyleCascade *cascade;
 
   /* Add provider for user file */
   if (G_UNLIKELY (!css_provider))
@@ -1782,15 +1804,16 @@ settings_init_style (GtkSettings *settings)
       g_free (css_path);
     }
 
-  _gtk_style_cascade_add_provider (priv->style_cascade,
+  cascade = _gtk_settings_get_style_cascade (settings, 1);
+  _gtk_style_cascade_add_provider (cascade,
                                    GTK_STYLE_PROVIDER (css_provider),
                                    GTK_STYLE_PROVIDER_PRIORITY_USER);
 
-  _gtk_style_cascade_add_provider (priv->style_cascade,
+  _gtk_style_cascade_add_provider (cascade,
                                    GTK_STYLE_PROVIDER (settings),
                                    GTK_STYLE_PROVIDER_PRIORITY_SETTINGS);
 
-  _gtk_style_cascade_add_provider (priv->style_cascade,
+  _gtk_style_cascade_add_provider (cascade,
                                    GTK_STYLE_PROVIDER (settings->priv->theme_provider),
                                    GTK_STYLE_PROVIDER_PRIORITY_SETTINGS);
 
diff --git a/gtk/gtksettingsprivate.h b/gtk/gtksettingsprivate.h
index 4ba07cd..e14ec5f 100644
--- a/gtk/gtksettingsprivate.h
+++ b/gtk/gtksettingsprivate.h
@@ -38,7 +38,8 @@ gboolean            _gtk_settings_parse_convert              (GtkRcPropertyParse
                                                               GParamSpec             *pspec,
                                                               GValue                 *dest_value);
 GdkScreen          *_gtk_settings_get_screen                 (GtkSettings            *settings);
-GtkStyleCascade    *_gtk_settings_get_style_cascade          (GtkSettings            *settings);
+GtkStyleCascade    *_gtk_settings_get_style_cascade          (GtkSettings            *settings,
+                                                              gint                    scale);
 
 typedef enum
 {
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index a7f700a..9b4798e 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -423,7 +423,7 @@ gtk_style_context_init (GtkStyleContext *style_context)
   priv->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
 
   gtk_style_context_set_cascade (style_context,
-                                 _gtk_settings_get_style_cascade (gtk_settings_get_for_screen 
(priv->screen)));
+                                 _gtk_settings_get_style_cascade (gtk_settings_get_for_screen 
(priv->screen), 1));
 }
 
 static void
@@ -703,11 +703,18 @@ create_query_path (GtkStyleContext              *context,
 }
 
 static gboolean
-may_use_global_parent_cache (GtkStyleContext *context)
+gtk_style_context_has_custom_cascade (GtkStyleContext *context)
 {
   GtkStyleContextPrivate *priv = context->priv;
+  GtkSettings *settings = gtk_settings_get_for_screen (context->priv->screen);
+
+  return priv->cascade != _gtk_settings_get_style_cascade (settings, _gtk_style_cascade_get_scale 
(priv->cascade));
+}
 
-  if (priv->cascade != _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen)))
+static gboolean
+may_use_global_parent_cache (GtkStyleContext *context)
+{
+  if (gtk_style_context_has_custom_cascade (context))
     return FALSE;
 
   return TRUE;
@@ -1036,12 +1043,14 @@ gtk_style_context_add_provider (GtkStyleContext  *context,
 
   priv = context->priv;
 
-  if (priv->cascade == _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen)))
+  if (!gtk_style_context_has_custom_cascade (context))
     {
       GtkStyleCascade *new_cascade;
       
       new_cascade = _gtk_style_cascade_new ();
-      _gtk_style_cascade_set_parent (new_cascade, priv->cascade);
+      _gtk_style_cascade_set_scale (new_cascade, _gtk_style_cascade_get_scale (priv->cascade));
+      _gtk_style_cascade_set_parent (new_cascade,
+                                     _gtk_settings_get_style_cascade (gtk_settings_get_for_screen 
(priv->screen), 1));
       _gtk_style_cascade_add_provider (new_cascade, provider, priority);
       gtk_style_context_set_cascade (context, new_cascade);
       g_object_unref (new_cascade);
@@ -1072,7 +1081,7 @@ gtk_style_context_remove_provider (GtkStyleContext  *context,
 
   priv = context->priv;
 
-  if (priv->cascade == _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen)))
+  if (!gtk_style_context_has_custom_cascade (context))
     return;
 
   _gtk_style_cascade_remove_provider (priv->cascade, provider);
@@ -1145,7 +1154,7 @@ gtk_style_context_add_provider_for_screen (GdkScreen        *screen,
   g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
   g_return_if_fail (!GTK_IS_SETTINGS (provider) || _gtk_settings_get_screen (GTK_SETTINGS (provider)) == 
screen);
 
-  cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen));
+  cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen), 1);
   _gtk_style_cascade_add_provider (cascade, provider, priority);
 }
 
@@ -1168,7 +1177,7 @@ gtk_style_context_remove_provider_for_screen (GdkScreen        *screen,
   g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
   g_return_if_fail (!GTK_IS_SETTINGS (provider));
 
-  cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen));
+  cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen), 1);
   _gtk_style_cascade_remove_provider (cascade, provider);
 }
 
@@ -1440,17 +1449,18 @@ gtk_style_context_set_scale (GtkStyleContext *context,
   if (scale == _gtk_style_cascade_get_scale (priv->cascade))
     return;
 
-  if (priv->cascade == _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen)))
+  if (gtk_style_context_has_custom_cascade (context))
+    {
+      _gtk_style_cascade_set_scale (priv->cascade, scale);
+    }
+  else
     {
       GtkStyleCascade *new_cascade;
-      
-      new_cascade = _gtk_style_cascade_new ();
-      _gtk_style_cascade_set_parent (new_cascade, priv->cascade);
+
+      new_cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen),
+                                                     scale);
       gtk_style_context_set_cascade (context, new_cascade);
-      g_object_unref (new_cascade);
     }
-
-  _gtk_style_cascade_set_scale (priv->cascade, scale);
 }
 
 /**
@@ -2368,7 +2378,6 @@ gtk_style_context_set_screen (GtkStyleContext *context,
 {
   GtkStyleContextPrivate *priv;
   GtkStyleCascade *screen_cascade;
-  GtkStyleCascade *old_screen_cascade;
 
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
   g_return_if_fail (GDK_IS_SCREEN (screen));
@@ -2377,15 +2386,16 @@ gtk_style_context_set_screen (GtkStyleContext *context,
   if (priv->screen == screen)
     return;
 
-  screen_cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen));
-  old_screen_cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen));
-  if (priv->cascade == old_screen_cascade)
+  if (gtk_style_context_has_custom_cascade (context))
     {
-      gtk_style_context_set_cascade (context, screen_cascade);
+      screen_cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen), 1);
+      _gtk_style_cascade_set_parent (priv->cascade, screen_cascade);
     }
   else
     {
-      _gtk_style_cascade_set_parent (priv->cascade, screen_cascade);
+      screen_cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen),
+                                                        _gtk_style_cascade_get_scale (priv->cascade));
+      gtk_style_context_set_cascade (context, screen_cascade);
     }
 
   priv->screen = screen;


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