[gtk+/gtk-style-context: 222/260] GtkStyleContext: Add gtk_style_context_[add|remove]_provider_for_screen()



commit c4ec4ac0baaa59b903af3b6263fbbc3b61232f42
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sat Sep 11 12:42:35 2010 +0200

    GtkStyleContext: Add gtk_style_context_[add|remove]_provider_for_screen()
    
    These functions allow per-screen style providers. also, the changed signal
    will be emitted whenever a style context changes.

 gtk/gtkstylecontext.c |  233 ++++++++++++++++++++++++++++++++++++-------------
 gtk/gtkstylecontext.h |    6 ++
 2 files changed, 178 insertions(+), 61 deletions(-)
---
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index c738e91..106f78a 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -28,6 +28,7 @@
 #include "gtkthemingengine.h"
 #include "gtkintl.h"
 #include "gtkwidget.h"
+#include "gtkwindow.h"
 #include "gtkprivate.h"
 #include "gtkanimationdescription.h"
 #include "gtktimeline.h"
@@ -119,6 +120,8 @@ enum {
 
 guint signals[LAST_SIGNAL] = { 0 };
 
+static GQuark provider_list_quark = 0;
+
 static void gtk_style_context_finalize (GObject *object);
 
 static void gtk_style_context_impl_set_property (GObject      *object,
@@ -484,24 +487,55 @@ gtk_style_context_impl_get_property (GObject    *object,
     }
 }
 
+GList *
+find_next_candidate (GList *local,
+                     GList *global)
+{
+  if (local && global)
+    {
+      GtkStyleProviderData *local_data, *global_data;
+
+      local_data = local->data;
+      global_data = global->data;
+
+      if (local_data->priority >= global_data->priority)
+        return local;
+      else
+        return global;
+    }
+  else if (local)
+    return local;
+  else if (global)
+    return global;
+
+  return NULL;
+}
+
 static void
 rebuild_properties (GtkStyleContext *context)
 {
   GtkStyleContextPrivate *priv;
-  GList *list;
+  GList *elem, *list, *global_list = NULL;
 
   priv = context->priv;
   list = priv->providers;
 
+  if (priv->screen)
+    global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
+
   gtk_style_set_clear (priv->store);
 
-  while (list)
+  while ((elem = find_next_candidate (list, global_list)) != NULL)
     {
       GtkStyleProviderData *data;
       GtkStyleSet *provider_style;
 
-      data = list->data;
-      list = list->next;
+      data = elem->data;
+
+      if (elem == list)
+        list = list->next;
+      else
+        global_list = global_list->next;
 
       provider_style = gtk_style_provider_get_style (data->provider,
                                                      priv->widget_path);
@@ -525,7 +559,7 @@ static void
 rebuild_icon_factories (GtkStyleContext *context)
 {
   GtkStyleContextPrivate *priv;
-  GList *providers;
+  GList *elem, *list, *global_list = NULL;
 
   priv = context->priv;
 
@@ -533,12 +567,26 @@ rebuild_icon_factories (GtkStyleContext *context)
   g_slist_free (priv->icon_factories);
   priv->icon_factories = NULL;
 
-  for (providers = priv->providers_last; providers; providers = providers->prev)
+  list = priv->providers_last;
+
+  if (priv->screen)
+    {
+      global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
+      global_list = g_list_last (global_list);
+    }
+
+  while ((elem = find_next_candidate (list, global_list)) != NULL)
     {
       GtkIconFactory *factory;
       GtkStyleProviderData *data;
 
-      data = providers->data;
+      data = elem->data;
+
+      if (elem == list)
+        list = list->prev;
+      else
+        global_list = global_list->prev;
+
       factory = gtk_style_provider_get_icon_factory (data->provider,
 						     priv->widget_path);
 
@@ -547,28 +595,22 @@ rebuild_icon_factories (GtkStyleContext *context)
     }
 }
 
-void
-gtk_style_context_add_provider (GtkStyleContext  *context,
-                                GtkStyleProvider *provider,
-                                guint             priority)
+static void
+style_provider_add (GList            **list,
+                    GtkStyleProvider  *provider,
+                    guint              priority)
 {
-  GtkStyleContextPrivate *priv;
   GtkStyleProviderData *new_data;
   gboolean added = FALSE;
-  GList *list;
+  GList *l = *list;
 
-  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
-  g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
-
-  priv = context->priv;
   new_data = style_provider_data_new (provider, priority);
-  list = priv->providers;
 
-  while (list)
+  while (l)
     {
       GtkStyleProviderData *data;
 
-      data = list->data;
+      data = l->data;
 
       /* Provider was already attached to the style
        * context, remove in order to add the new data
@@ -577,11 +619,11 @@ gtk_style_context_add_provider (GtkStyleContext  *context,
         {
           GList *link;
 
-          link = list;
-          list = list->next;
+          link = l;
+          l = l->next;
 
           /* Remove and free link */
-          priv->providers = g_list_remove_link (priv->providers, link);
+          *list = g_list_remove_link (*list, link);
           style_provider_data_free (link->data);
           g_list_free_1 (link);
 
@@ -591,24 +633,59 @@ gtk_style_context_add_provider (GtkStyleContext  *context,
       if (!added &&
           data->priority > priority)
         {
-          priv->providers = g_list_insert_before (priv->providers, list, new_data);
+          *list = g_list_insert_before (*list, l, new_data);
           added = TRUE;
         }
 
-      list = list->next;
+      l = l->next;
     }
 
   if (!added)
-    priv->providers = g_list_append (priv->providers, new_data);
+    *list = g_list_append (*list, new_data);
+}
 
-  priv->providers_last = g_list_last (priv->providers);
+static gboolean
+style_provider_remove (GList            **list,
+                       GtkStyleProvider  *provider)
+{
+  GList *l = *list;
 
-  if (priv->widget_path)
+  while (l)
     {
-      rebuild_properties (context);
-      clear_property_cache (context);
-      rebuild_icon_factories (context);
+      GtkStyleProviderData *data;
+
+      data = l->data;
+
+      if (data->provider == provider)
+        {
+          *list = g_list_remove_link (*list, l);
+          style_provider_data_free (l->data);
+          g_list_free_1 (l);
+
+          return TRUE;
+        }
+
+      l = l->next;
     }
+
+  return FALSE;
+}
+
+void
+gtk_style_context_add_provider (GtkStyleContext  *context,
+                                GtkStyleProvider *provider,
+                                guint             priority)
+{
+  GtkStyleContextPrivate *priv;
+
+  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+  g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
+
+  priv = context->priv;
+  style_provider_add (&priv->providers, provider, priority);
+  priv->providers_last = g_list_last (priv->providers);
+
+  gtk_style_context_invalidate (context);
 }
 
 void
@@ -616,45 +693,81 @@ gtk_style_context_remove_provider (GtkStyleContext  *context,
                                    GtkStyleProvider *provider)
 {
   GtkStyleContextPrivate *priv;
-  gboolean removed = FALSE;
-  GList *list;
 
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
   g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
 
   priv = context->priv;
-  list = priv->providers;
 
-  while (list)
+  if (style_provider_remove (&priv->providers, provider))
     {
-      GtkStyleProviderData *data;
+      priv->providers_last = g_list_last (priv->providers);
 
-      data = list->data;
+      gtk_style_context_invalidate (context);
+    }
+}
 
-      if (data->provider == provider)
-        {
-          priv->providers = g_list_remove_link (priv->providers, list);
-          style_provider_data_free (list->data);
-          g_list_free_1 (list);
+static void
+reset_toplevels (GdkScreen *screen)
+{
+  GList *list, *toplevels;
 
-          removed = TRUE;
+  toplevels = gtk_window_list_toplevels ();
+  g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
 
-          break;
-        }
+  for (list = toplevels; list; list = list->next)
+    {
+      if (gtk_widget_get_screen (list->data) == screen)
+        gtk_widget_reset_style (list->data);
 
-      list = list->next;
+      g_object_unref (list->data);
     }
 
-  if (removed)
+  g_list_free (toplevels);
+}
+
+void
+gtk_style_context_add_provider_for_screen (GdkScreen        *screen,
+                                           GtkStyleProvider *provider,
+                                           guint             priority)
+{
+  GList *providers, *list;
+
+  g_return_if_fail (GDK_IS_SCREEN (screen));
+  g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
+
+  if (G_UNLIKELY (!provider_list_quark))
+    provider_list_quark = g_quark_from_static_string ("gtk-provider-list-quark");
+
+  list = providers = g_object_get_qdata (G_OBJECT (screen), provider_list_quark);
+  style_provider_add (&list, provider, priority);
+
+  if (list != providers)
+    g_object_set_qdata (G_OBJECT (screen), provider_list_quark, list);
+
+  reset_toplevels (screen);
+}
+
+void
+gtk_style_context_remove_provider_for_screen (GdkScreen        *screen,
+                                              GtkStyleProvider *provider)
+{
+  GList *providers, *list;
+
+  g_return_if_fail (GDK_IS_SCREEN (screen));
+  g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
+
+  if (G_UNLIKELY (!provider_list_quark))
+    return;
+
+  list = providers = g_object_get_qdata (G_OBJECT (screen), provider_list_quark);
+
+  if (style_provider_remove (&list, provider))
     {
-      priv->providers_last = g_list_last (priv->providers);
+      if (list != providers)
+        g_object_set_qdata (G_OBJECT (screen), provider_list_quark, list);
 
-      if (priv->widget_path)
-        {
-          rebuild_properties (context);
-          clear_property_cache (context);
-	  rebuild_icon_factories (context);
-        }
+      reset_toplevels (screen);
     }
 }
 
@@ -833,9 +946,7 @@ gtk_style_context_set_path (GtkStyleContext *context,
   if (path)
     {
       priv->widget_path = gtk_widget_path_copy (path);
-      rebuild_properties (context);
-      clear_property_cache (context);
-      rebuild_icon_factories (context);
+      gtk_style_context_invalidate (context);
     }
 }
 
@@ -1040,7 +1151,7 @@ gtk_style_context_set_class (GtkStyleContext *context,
       if (priv->widget_path)
         {
           gtk_widget_path_iter_add_class (priv->widget_path, 0, class_name);
-          rebuild_properties (context);
+          gtk_style_context_invalidate (context);
         }
     }
 }
@@ -1074,7 +1185,7 @@ gtk_style_context_unset_class (GtkStyleContext *context,
       if (priv->widget_path)
         {
           gtk_widget_path_iter_remove_class (priv->widget_path, 0, class_name);
-          rebuild_properties (context);
+          gtk_style_context_invalidate (context);
         }
     }
 }
@@ -1192,7 +1303,7 @@ gtk_style_context_set_region (GtkStyleContext *context,
       if (priv->widget_path)
         {
           gtk_widget_path_iter_add_region (priv->widget_path, 0, class_name, flags);
-          rebuild_properties (context);
+          gtk_style_context_invalidate (context);
         }
     }
 }
@@ -1226,7 +1337,7 @@ gtk_style_context_unset_region (GtkStyleContext    *context,
       if (priv->widget_path)
         {
           gtk_widget_path_iter_remove_region (priv->widget_path, 0, class_name);
-          rebuild_properties (context);
+          gtk_style_context_invalidate (context);
         }
     }
 }
diff --git a/gtk/gtkstylecontext.h b/gtk/gtkstylecontext.h
index fba6028..07cec5b 100644
--- a/gtk/gtkstylecontext.h
+++ b/gtk/gtkstylecontext.h
@@ -51,6 +51,12 @@ struct GtkStyleContextClass
 
 GType gtk_style_context_get_type (void) G_GNUC_CONST;
 
+void gtk_style_context_add_provider_for_screen    (GdkScreen        *screen,
+                                                   GtkStyleProvider *provider,
+                                                   guint             priority);
+void gtk_style_context_remove_provider_for_screen (GdkScreen        *screen,
+                                                   GtkStyleProvider *provider);
+
 void gtk_style_context_add_provider    (GtkStyleContext  *context,
                                         GtkStyleProvider *provider,
                                         guint             priority);



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