[gtk+] Add gtk_style_context_cancel_animations()



commit e6277d3b82440168e073bc83bf10fceb76d63995
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon Jan 10 03:31:35 2011 +0100

    Add gtk_style_context_cancel_animations()
    
    This function takes a region ID and cancels all animations
    on or beneath that region (as in push/pop_animatable_region).
    
    First user of this is GtkWidget itself, so unmapped widgets
    have looping animations cancelled. Fixes bug #638119, reported
    by Jesse van den Kieboom.

 docs/reference/gtk/gtk3-sections.txt |    1 +
 gtk/gtk.symbols                      |    1 +
 gtk/gtkstylecontext.c                |   72 +++++++++++++++++++++++++++++----
 gtk/gtkstylecontext.h                |    3 +
 gtk/gtkwidget.c                      |    3 +
 5 files changed, 71 insertions(+), 9 deletions(-)
---
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index 3ae7fa8..16372a5 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -5547,6 +5547,7 @@ gtk_style_context_lookup_icon_set
 gtk_style_context_notify_state_change
 gtk_style_context_pop_animatable_region
 gtk_style_context_push_animatable_region
+gtk_style_context_cancel_animations
 gtk_style_context_remove_provider
 gtk_style_context_remove_provider_for_screen
 gtk_style_context_reset_widgets
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index 919ddd4..ead590e 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -2461,6 +2461,7 @@ gtk_style_context_add_class
 gtk_style_context_add_provider
 gtk_style_context_add_provider_for_screen
 gtk_style_context_add_region
+gtk_style_context_cancel_animations
 gtk_style_context_get
 gtk_style_context_get_background_color
 gtk_style_context_get_border
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index 162c971..3d1b0aa 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -454,6 +454,12 @@ struct AnimationInfo
   GtkTimeline *timeline;
 
   gpointer region_id;
+
+  /* Region stack (until region_id) at the time of
+   * rendering, this is used for nested cancellation.
+   */
+  GSList *parent_regions;
+
   GdkWindow *window;
   GtkStateType state;
   gboolean target_value;
@@ -749,6 +755,7 @@ animation_info_free (AnimationInfo *info)
     cairo_region_destroy (info->invalidation_region);
 
   g_array_free (info->rectangles, TRUE);
+  g_slist_free (info->parent_regions);
   g_slice_free (AnimationInfo, info);
 }
 
@@ -1572,7 +1579,6 @@ context_has_animatable_region (GtkStyleContext *context,
                                gpointer         region_id)
 {
   GtkStyleContextPrivate *priv;
-  GSList *r;
 
   /* NULL region_id means everything
    * rendered through the style context
@@ -1581,14 +1587,7 @@ context_has_animatable_region (GtkStyleContext *context,
     return TRUE;
 
   priv = context->priv;
-
-  for (r = priv->animation_regions; r; r = r->next)
-    {
-      if (r->data == region_id)
-        return TRUE;
-    }
-
-  return FALSE;
+  return g_slist_find (priv->animation_regions, region_id) != NULL;
 }
 
 /**
@@ -2920,6 +2919,53 @@ gtk_style_context_notify_state_change (GtkStyleContext *context,
 }
 
 /**
+ * gtk_style_context_cancel_animations:
+ * @context: a #GtkStyleContext
+ * @region_id: (allow-none): animatable region to stop, or %NULL.
+ *     See gtk_style_context_push_animatable_region()
+ *
+ * Stops all running animations for @region_id and all animatable
+ * regions underneath.
+ *
+ * A %NULL @region_id will stop all ongoing animations in @context,
+ * when dealing with a #GtkStyleContext obtained through
+ * gtk_widget_get_style_context(), this is normally done for you
+ * in all circumstances you would expect all widget to be stopped,
+ * so this should be only used in complex widgets with different
+ * animatable regions.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_style_context_cancel_animations (GtkStyleContext *context,
+                                     gpointer         region_id)
+{
+  GtkStyleContextPrivate *priv;
+  AnimationInfo *info;
+  GSList *l, *node;
+
+  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+
+  priv = context->priv;
+  l = priv->animations;
+
+  while (l)
+    {
+      info = l->data;
+      node = l;
+      l = l->next;
+
+      if (!region_id ||
+          info->region_id == region_id ||
+          g_slist_find (info->parent_regions, region_id))
+        {
+          priv->animations = g_slist_remove (priv->animations, info);
+          animation_info_free (info);
+        }
+    }
+}
+
+/**
  * gtk_style_context_push_animatable_region:
  * @context: a #GtkStyleContext
  * @region_id: unique identifier for the animatable region
@@ -3096,6 +3142,14 @@ store_animation_region (GtkStyleContext *context,
           rect.height = (gint) height;
 
           g_array_append_val (info->rectangles, rect);
+
+          if (!info->parent_regions)
+            {
+              GSList *parent_regions;
+
+              parent_regions = g_slist_find (priv->animation_regions, info->region_id);
+              info->parent_regions = g_slist_copy (parent_regions);
+            }
         }
     }
 }
diff --git a/gtk/gtkstylecontext.h b/gtk/gtkstylecontext.h
index ab9be70..ceedc52 100644
--- a/gtk/gtkstylecontext.h
+++ b/gtk/gtkstylecontext.h
@@ -522,6 +522,9 @@ void  gtk_style_context_notify_state_change (GtkStyleContext *context,
                                              gpointer         region_id,
                                              GtkStateType     state,
                                              gboolean         state_value);
+void  gtk_style_context_cancel_animations   (GtkStyleContext *context,
+                                             gpointer         region_id);
+
 void gtk_style_context_push_animatable_region (GtkStyleContext *context,
                                                gpointer         region_id);
 void gtk_style_context_pop_animatable_region  (GtkStyleContext *context);
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index b7c3141..f0c56b4 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -4191,6 +4191,9 @@ gtk_widget_unmap (GtkWidget *widget)
       g_signal_emit (widget, widget_signals[UNMAP], 0);
 
       gtk_widget_pop_verify_invariants (widget);
+
+      if (priv->context)
+        gtk_style_context_cancel_animations (priv->context, NULL);
     }
 }
 



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