]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkstylecontext.c
css: Remove old animation code
[~andy/gtk] / gtk / gtkstylecontext.c
index eaff91bcccc67bc9595ad66e840c641299046d0e..42f6795b0dbe7eaebca3ebbfbe5716e2a371402f 100644 (file)
@@ -12,9 +12,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "config.h"
 #include <gobject/gvaluecollector.h>
 
 #include "gtkstylecontextprivate.h"
+#include "gtkcssenginevalueprivate.h"
+#include "gtkcssrgbavalueprivate.h"
 #include "gtkstylepropertiesprivate.h"
 #include "gtktypebuiltins.h"
-#include "gtkthemingengine.h"
+#include "gtkthemingengineprivate.h"
 #include "gtkintl.h"
 #include "gtkwidget.h"
 #include "gtkwindow.h"
 #include "gtkprivate.h"
-#include "gtksymboliccolor.h"
-#include "gtkanimationdescription.h"
-#include "gtktimeline.h"
+#include "gtksymboliccolorprivate.h"
+#include "gtkcssnumbervalueprivate.h"
 #include "gtkiconfactory.h"
+#include "gtkwidgetpath.h"
 #include "gtkwidgetprivate.h"
+#include "gtkstylecascadeprivate.h"
+#include "gtkstyleproviderprivate.h"
+#include "gtksettings.h"
 
 /**
  * SECTION:gtkstylecontext
  * </refsect2>
  */
 
-typedef struct GtkStyleProviderData GtkStyleProviderData;
+/* When these change we do a full restyling. Otherwise we try to figure out
+ * if we need to change things. */
+#define GTK_STYLE_CONTEXT_RADICAL_CHANGE (GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_CLASS)
+/* When these change we don't clear the cache. This takes more memory but makes
+ * things go faster. */
+#define GTK_STYLE_CONTEXT_CACHED_CHANGE (GTK_CSS_CHANGE_STATE)
+
 typedef struct GtkStyleInfo GtkStyleInfo;
 typedef struct GtkRegion GtkRegion;
 typedef struct PropertyValue PropertyValue;
-typedef struct AnimationInfo AnimationInfo;
 typedef struct StyleData StyleData;
 
 struct GtkRegion
@@ -312,12 +320,6 @@ struct GtkRegion
   GtkRegionFlags flags;
 };
 
-struct GtkStyleProviderData
-{
-  GtkStyleProvider *provider;
-  guint priority;
-};
-
 struct PropertyValue
 {
   GType       widget_type;
@@ -332,61 +334,44 @@ struct GtkStyleInfo
   GArray *regions;
   GtkJunctionSides junction_sides;
   GtkStateFlags state_flags;
+  StyleData *data;
 };
 
 struct StyleData
 {
-  GtkStyleProperties *store;
-  GSList *icon_factories;
+  GtkCssComputedValues *store;
   GArray *property_cache;
 };
 
-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;
-
-  cairo_region_t *invalidation_region;
-  GArray *rectangles;
-};
-
 struct _GtkStyleContextPrivate
 {
   GdkScreen *screen;
 
-  GList *providers;
-  GList *providers_last;
+  GtkStyleCascade *cascade;
 
+  GtkStyleContext *parent;
+  GSList *children;
+  GtkWidget *widget;            
   GtkWidgetPath *widget_path;
   GHashTable *style_data;
   GSList *info_stack;
-  StyleData *current_data;
-
-  GSList *animation_regions;
-  GSList *animations;
 
   GtkThemingEngine *theming_engine;
 
   GtkTextDirection direction;
 
-  guint animations_invalidated : 1;
+  GtkCssChange relevant_changes;
+  GtkCssChange pending_changes;
+
   guint invalidating_context : 1;
+  guint invalid : 1;
 };
 
 enum {
   PROP_0,
   PROP_SCREEN,
-  PROP_DIRECTION
+  PROP_DIRECTION,
+  PROP_PARENT
 };
 
 enum {
@@ -396,8 +381,6 @@ enum {
 
 static 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,
@@ -408,10 +391,22 @@ static void gtk_style_context_impl_get_property (GObject      *object,
                                                  guint         prop_id,
                                                  GValue       *value,
                                                  GParamSpec   *pspec);
+static GtkSymbolicColor *
+            gtk_style_context_color_lookup_func (gpointer      contextp,
+                                                 const char   *name);
 
 
 G_DEFINE_TYPE (GtkStyleContext, gtk_style_context, G_TYPE_OBJECT)
 
+static void
+gtk_style_context_real_changed (GtkStyleContext *context)
+{
+  GtkStyleContextPrivate *priv = context->priv;
+
+  if (priv->widget)
+    _gtk_widget_style_context_invalidated (priv->widget);
+}
+
 static void
 gtk_style_context_class_init (GtkStyleContextClass *klass)
 {
@@ -421,6 +416,8 @@ gtk_style_context_class_init (GtkStyleContextClass *klass)
   object_class->set_property = gtk_style_context_impl_set_property;
   object_class->get_property = gtk_style_context_impl_get_property;
 
+  klass->changed = gtk_style_context_real_changed;
+
   signals[CHANGED] =
     g_signal_new (I_("changed"),
                   G_TYPE_FROM_CLASS (object_class),
@@ -445,6 +442,21 @@ gtk_style_context_class_init (GtkStyleContextClass *klass)
                                                       GTK_TYPE_TEXT_DIRECTION,
                                                       GTK_TEXT_DIR_LTR,
                                                       GTK_PARAM_READWRITE));
+  /**
+   * GtkStyleContext:parent:
+   *
+   * Sets or gets the style context's parent. See gtk_style_context_set_parent()
+   * for details.
+   *
+   * Since: 3.4
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_PARENT,
+                                   g_param_spec_object ("parent",
+                                                        P_("Parent"),
+                                                        P_("The parent style context"),
+                                                        GTK_TYPE_STYLE_CONTEXT,
+                                                        GTK_PARAM_READWRITE));
 
   g_type_class_add_private (object_class, sizeof (GtkStyleContextPrivate));
 }
@@ -485,6 +497,7 @@ style_info_copy (const GtkStyleInfo *info)
 
   copy->junction_sides = info->junction_sides;
   copy->state_flags = info->state_flags;
+  copy->data = info->data;
 
   return copy;
 }
@@ -513,7 +526,7 @@ style_info_hash (gconstpointer elem)
       hash <<= 5;
     }
 
-  return hash;
+  return hash ^ info->state_flags;
 }
 
 static gboolean
@@ -525,6 +538,9 @@ style_info_equal (gconstpointer elem1,
   info1 = elem1;
   info2 = elem2;
 
+  if (info1->state_flags != info2->state_flags)
+    return FALSE;
+
   if (info1->junction_sides != info2->junction_sides)
     return FALSE;
 
@@ -553,7 +569,6 @@ style_data_new (void)
   StyleData *data;
 
   data = g_slice_new0 (StyleData);
-  data->store = gtk_style_properties_new ();
 
   return data;
 }
@@ -584,8 +599,6 @@ style_data_free (StyleData *data)
   g_object_unref (data->store);
   clear_property_cache (data);
 
-  g_slist_free_full (data->icon_factories, g_object_unref);
-
   g_slice_free (StyleData, data);
 }
 
@@ -608,214 +621,38 @@ gtk_style_context_init (GtkStyleContext *style_context)
   priv->direction = GTK_TEXT_DIR_LTR;
 
   priv->screen = gdk_screen_get_default ();
+  priv->cascade = _gtk_style_cascade_get_for_screen (priv->screen);
+  g_object_ref (priv->cascade);
+  priv->relevant_changes = GTK_CSS_CHANGE_ANY;
 
   /* Create default info store */
   info = style_info_new ();
   priv->info_stack = g_slist_prepend (priv->info_stack, info);
 }
 
-static GtkStyleProviderData *
-style_provider_data_new (GtkStyleProvider *provider,
-                         guint             priority)
-{
-  GtkStyleProviderData *data;
-
-  data = g_slice_new (GtkStyleProviderData);
-  data->provider = g_object_ref (provider);
-  data->priority = priority;
-
-  return data;
-}
-
-static void
-style_provider_data_free (GtkStyleProviderData *data)
-{
-  g_object_unref (data->provider);
-  g_slice_free (GtkStyleProviderData, data);
-}
-
-static void
-animation_info_free (AnimationInfo *info)
-{
-  g_object_unref (info->timeline);
-  g_object_unref (info->window);
-
-  if (info->invalidation_region)
-    cairo_region_destroy (info->invalidation_region);
-
-  g_array_free (info->rectangles, TRUE);
-  g_slist_free (info->parent_regions);
-  g_slice_free (AnimationInfo, info);
-}
-
-static AnimationInfo *
-animation_info_lookup_by_timeline (GtkStyleContext *context,
-                                   GtkTimeline     *timeline)
-{
-  GtkStyleContextPrivate *priv;
-  AnimationInfo *info;
-  GSList *l;
-
-  priv = context->priv;
-
-  for (l = priv->animations; l; l = l->next)
-    {
-      info = l->data;
-
-      if (info->timeline == timeline)
-        return info;
-    }
-
-  return NULL;
-}
-
-static void
-timeline_frame_cb (GtkTimeline *timeline,
-                   gdouble      progress,
-                   gpointer     user_data)
-{
-  GtkStyleContextPrivate *priv;
-  GtkStyleContext *context;
-  AnimationInfo *info;
-
-  context = user_data;
-  priv = context->priv;
-  info = animation_info_lookup_by_timeline (context, timeline);
-
-  g_assert (info != NULL);
-
-  /* Cancel transition if window is gone */
-  if (gdk_window_is_destroyed (info->window) ||
-      !gdk_window_is_visible (info->window))
-    {
-      priv->animations = g_slist_remove (priv->animations, info);
-      animation_info_free (info);
-      return;
-    }
-
-  if (info->invalidation_region &&
-      !cairo_region_is_empty (info->invalidation_region))
-    gdk_window_invalidate_region (info->window, info->invalidation_region, TRUE);
-  else
-    gdk_window_invalidate_rect (info->window, NULL, TRUE);
-}
-
-static void
-timeline_finished_cb (GtkTimeline *timeline,
-                      gpointer     user_data)
-{
-  GtkStyleContextPrivate *priv;
-  GtkStyleContext *context;
-  AnimationInfo *info;
-
-  context = user_data;
-  priv = context->priv;
-  info = animation_info_lookup_by_timeline (context, timeline);
-
-  g_assert (info != NULL);
-
-  priv->animations = g_slist_remove (priv->animations, info);
-
-  /* Invalidate one last time the area, so the final content is painted */
-  if (info->invalidation_region &&
-      !cairo_region_is_empty (info->invalidation_region))
-    gdk_window_invalidate_region (info->window, info->invalidation_region, TRUE);
-  else
-    gdk_window_invalidate_rect (info->window, NULL, TRUE);
-
-  animation_info_free (info);
-}
-
-static AnimationInfo *
-animation_info_new (GtkStyleContext         *context,
-                    gpointer                 region_id,
-                    guint                    duration,
-                    GtkTimelineProgressType  progress_type,
-                    gboolean                 loop,
-                    GtkStateType             state,
-                    gboolean                 target_value,
-                    GdkWindow               *window)
-{
-  AnimationInfo *info;
-
-  info = g_slice_new0 (AnimationInfo);
-
-  info->rectangles = g_array_new (FALSE, FALSE, sizeof (cairo_rectangle_int_t));
-  info->timeline = _gtk_timeline_new (duration);
-  info->window = g_object_ref (window);
-  info->state = state;
-  info->target_value = target_value;
-  info->region_id = region_id;
-
-  _gtk_timeline_set_progress_type (info->timeline, progress_type);
-  _gtk_timeline_set_loop (info->timeline, loop);
-
-  if (!loop && !target_value)
-    {
-      _gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_BACKWARD);
-      _gtk_timeline_rewind (info->timeline);
-    }
-
-  g_signal_connect (info->timeline, "frame",
-                    G_CALLBACK (timeline_frame_cb), context);
-  g_signal_connect (info->timeline, "finished",
-                    G_CALLBACK (timeline_finished_cb), context);
-
-  _gtk_timeline_start (info->timeline);
-
-  return info;
-}
-
-static AnimationInfo *
-animation_info_lookup (GtkStyleContext *context,
-                       gpointer         region_id,
-                       GtkStateType     state)
-{
-  GtkStyleContextPrivate *priv;
-  GSList *l;
-
-  priv = context->priv;
-
-  for (l = priv->animations; l; l = l->next)
-    {
-      AnimationInfo *info;
-
-      info = l->data;
-
-      if (info->state == state &&
-          info->region_id == region_id)
-        return info;
-    }
-
-  return NULL;
-}
-
 static void
 gtk_style_context_finalize (GObject *object)
 {
   GtkStyleContextPrivate *priv;
   GtkStyleContext *style_context;
-  GSList *l;
 
   style_context = GTK_STYLE_CONTEXT (object);
   priv = style_context->priv;
 
+  /* children hold a reference to us */
+  g_assert (priv->children == NULL);
+
+  gtk_style_context_set_parent (style_context, NULL);
+
   if (priv->widget_path)
     gtk_widget_path_free (priv->widget_path);
 
   g_hash_table_destroy (priv->style_data);
 
-  g_list_free_full (priv->providers, (GDestroyNotify) style_provider_data_free);
+  g_object_unref (priv->cascade);
 
   g_slist_free_full (priv->info_stack, (GDestroyNotify) style_info_free);
 
-  g_slist_free (priv->animation_regions);
-
-  for (l = priv->animations; l; l = l->next)
-    animation_info_free ((AnimationInfo *) l->data);
-
-  g_slist_free (priv->animations);
-
   if (priv->theming_engine)
     g_object_unref (priv->theming_engine);
 
@@ -842,6 +679,10 @@ gtk_style_context_impl_set_property (GObject      *object,
       gtk_style_context_set_direction (style_context,
                                        g_value_get_enum (value));
       break;
+    case PROP_PARENT:
+      gtk_style_context_set_parent (style_context,
+                                    g_value_get_object (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -868,107 +709,37 @@ gtk_style_context_impl_get_property (GObject    *object,
     case PROP_DIRECTION:
       g_value_set_enum (value, priv->direction);
       break;
+    case PROP_PARENT:
+      g_value_set_object (value, priv->parent);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
     }
 }
 
-static GList *
-find_next_candidate (GList    *local,
-                     GList    *global,
-                     gboolean  ascending)
-{
-  if (local && global)
-    {
-      GtkStyleProviderData *local_data, *global_data;
-
-      local_data = local->data;
-      global_data = global->data;
-
-      if (local_data->priority < global_data->priority)
-        return (ascending) ? local : global;
-      else
-        return (ascending) ? global : local;
-    }
-  else if (local)
-    return local;
-  else if (global)
-    return global;
-
-  return NULL;
-}
-
 static void
 build_properties (GtkStyleContext *context,
                   StyleData       *style_data,
-                  GtkWidgetPath   *path)
-{
-  GtkStyleContextPrivate *priv;
-  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);
-
-  while ((elem = find_next_candidate (list, global_list, TRUE)) != NULL)
-    {
-      GtkStyleProviderData *data;
-      GtkStyleProperties *provider_style;
-
-      data = elem->data;
-
-      if (elem == list)
-        list = list->next;
-      else
-        global_list = global_list->next;
-
-      provider_style = gtk_style_provider_get_style (data->provider, path);
-
-      if (provider_style)
-        {
-          gtk_style_properties_merge (style_data->store, provider_style, TRUE);
-          g_object_unref (provider_style);
-        }
-    }
-}
-
-static void
-build_icon_factories (GtkStyleContext *context,
-                      StyleData       *style_data,
-                      GtkWidgetPath   *path)
+                  GtkWidgetPath   *path,
+                  GtkStateFlags    state)
 {
   GtkStyleContextPrivate *priv;
-  GList *elem, *list, *global_list = NULL;
+  GtkCssMatcher matcher;
+  GtkCssLookup *lookup;
 
   priv = context->priv;
-  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, FALSE)) != NULL)
-    {
-      GtkIconFactory *factory;
-      GtkStyleProviderData *data;
+  _gtk_css_matcher_init (&matcher, path, state);
+  lookup = _gtk_css_lookup_new ();
 
-      data = elem->data;
+  _gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
+                                      &matcher,
+                                      lookup);
 
-      if (elem == list)
-        list = list->prev;
-      else
-        global_list = global_list->prev;
-
-      factory = gtk_style_provider_get_icon_factory (data->provider, path);
-
-      if (factory)
-        style_data->icon_factories = g_slist_prepend (style_data->icon_factories, factory);
-    }
+  style_data->store = _gtk_css_computed_values_new ();
+  _gtk_css_lookup_resolve (lookup, context, style_data->store);
+  _gtk_css_lookup_free (lookup);
 }
 
 static GtkWidgetPath *
@@ -980,7 +751,7 @@ create_query_path (GtkStyleContext *context)
   guint i, pos;
 
   priv = context->priv;
-  path = gtk_widget_path_copy (priv->widget_path);
+  path = gtk_widget_path_copy (priv->widget ? gtk_widget_get_path (priv->widget) : priv->widget_path);
   pos = gtk_widget_path_length (path) - 1;
 
   info = priv->info_stack->data;
@@ -1010,128 +781,97 @@ create_query_path (GtkStyleContext *context)
 }
 
 static StyleData *
-style_data_lookup (GtkStyleContext *context,
-                   GtkStateFlags    state)
+style_data_lookup (GtkStyleContext *context)
 {
   GtkStyleContextPrivate *priv;
-  StyleData *data;
+  GtkStyleInfo *info;
 
   priv = context->priv;
+  info = priv->info_stack->data;
 
   /* Current data in use is cached, just return it */
-  if (priv->current_data)
-    return priv->current_data;
+  if (info->data)
+    return info->data;
 
-  g_assert (priv->widget_path != NULL);
+  g_assert (priv->widget != NULL || priv->widget_path != NULL);
 
-  data = g_hash_table_lookup (priv->style_data, priv->info_stack->data);
+  info->data = g_hash_table_lookup (priv->style_data, info);
 
-  if (!data)
+  if (!info->data)
     {
       GtkWidgetPath *path;
 
-      data = style_data_new ();
       path = create_query_path (context);
 
-      build_properties (context, data, path);
-      build_icon_factories (context, data, path);
-
+      info->data = style_data_new ();
       g_hash_table_insert (priv->style_data,
-                           style_info_copy (priv->info_stack->data),
-                           data);
+                           style_info_copy (info),
+                           info->data);
+
+      build_properties (context, info->data, path, info->state_flags);
 
       gtk_widget_path_free (path);
     }
 
-  priv->current_data = data;
-
   if (priv->theming_engine)
     g_object_unref (priv->theming_engine);
 
-  gtk_style_properties_get (data->store, 0,
-                            "engine", &priv->theming_engine,
-                            NULL);
+  priv->theming_engine = g_object_ref (
+                           _gtk_css_engine_value_get_engine (
+                             _gtk_css_computed_values_get_value (info->data->store, GTK_CSS_PROPERTY_ENGINE)));
 
-  if (!priv->theming_engine)
-    priv->theming_engine = g_object_ref (gtk_theming_engine_load (NULL));
-
-  return data;
+  return info->data;
 }
 
 static void
-style_provider_add (GList            **list,
-                    GtkStyleProvider  *provider,
-                    guint              priority)
+gtk_style_context_set_invalid (GtkStyleContext *context,
+                               gboolean         invalid)
 {
-  GtkStyleProviderData *new_data;
-  gboolean added = FALSE;
-  GList *l = *list;
-
-  new_data = style_provider_data_new (provider, priority);
-
-  while (l)
-    {
-      GtkStyleProviderData *data;
-
-      data = l->data;
-
-      /* Provider was already attached to the style
-       * context, remove in order to add the new data
-       */
-      if (data->provider == provider)
-        {
-          GList *link;
-
-          link = l;
-          l = l->next;
-
-          /* Remove and free link */
-          *list = g_list_remove_link (*list, link);
-          style_provider_data_free (link->data);
-          g_list_free_1 (link);
+  GtkStyleContextPrivate *priv;
+  
+  priv = context->priv;
 
-          continue;
-        }
+  if (priv->invalid == invalid)
+    return;
 
-      if (!added &&
-          data->priority > priority)
-        {
-          *list = g_list_insert_before (*list, l, new_data);
-          added = TRUE;
-        }
+  priv->invalid = invalid;
 
-      l = l->next;
+  if (invalid)
+    {
+      if (priv->parent)
+        gtk_style_context_set_invalid (priv->parent, TRUE);
+      else if (priv->widget)
+        gtk_widget_queue_resize (priv->widget);
     }
-
-  if (!added)
-    *list = g_list_append (*list, new_data);
 }
 
+/* returns TRUE if someone called gtk_style_context_save() but hasn't
+ * called gtk_style_context_restore() yet.
+ * In those situations we don't invalidate the context when somebody
+ * changes state/regions/classes.
+ */
 static gboolean
-style_provider_remove (GList            **list,
-                       GtkStyleProvider  *provider)
+gtk_style_context_is_saved (GtkStyleContext *context)
 {
-  GList *l = *list;
-
-  while (l)
-    {
-      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 context->priv->info_stack->next != NULL;
+}
 
-          return TRUE;
-        }
+static void
+gtk_style_context_queue_invalidate_internal (GtkStyleContext *context,
+                                             GtkCssChange     change)
+{
+  GtkStyleContextPrivate *priv = context->priv;
+  GtkStyleInfo *info = priv->info_stack->data;
 
-      l = l->next;
+  if (gtk_style_context_is_saved (context))
+    {
+      info->data = NULL;
+    }
+  else
+    {
+      _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_STATE);
+      /* XXX: We need to invalidate siblings here somehow */
     }
-
-  return FALSE;
 }
 
 /**
@@ -1156,6 +896,18 @@ gtk_style_context_new (void)
   return g_object_new (GTK_TYPE_STYLE_CONTEXT, NULL);
 }
 
+void
+_gtk_style_context_set_widget (GtkStyleContext *context,
+                               GtkWidget       *widget)
+{
+  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+  g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
+
+  context->priv->widget = widget;
+
+  _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANY_SELF);
+}
+
 /**
  * gtk_style_context_add_provider:
  * @context: a #GtkStyleContext
@@ -1185,8 +937,18 @@ gtk_style_context_add_provider (GtkStyleContext  *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);
+
+  if (priv->cascade == _gtk_style_cascade_get_for_screen (priv->screen))
+    {
+      GtkStyleCascade *new_cascade;
+      
+      new_cascade = _gtk_style_cascade_new ();
+      _gtk_style_cascade_set_parent (new_cascade, priv->cascade);
+      g_object_unref (priv->cascade);
+      priv->cascade = new_cascade;
+    }
+
+  _gtk_style_cascade_add_provider (priv->cascade, provider, priority);
 
   gtk_style_context_invalidate (context);
 }
@@ -1211,12 +973,10 @@ gtk_style_context_remove_provider (GtkStyleContext  *context,
 
   priv = context->priv;
 
-  if (style_provider_remove (&priv->providers, provider))
-    {
-      priv->providers_last = g_list_last (priv->providers);
+  if (priv->cascade == _gtk_style_cascade_get_for_screen (priv->screen))
+    return;
 
-      gtk_style_context_invalidate (context);
-    }
+  _gtk_style_cascade_remove_provider (priv->cascade, provider);
 }
 
 /**
@@ -1281,21 +1041,13 @@ gtk_style_context_add_provider_for_screen (GdkScreen        *screen,
                                            GtkStyleProvider *provider,
                                            guint             priority)
 {
-  GList *providers, *list;
+  GtkStyleCascade *cascade;
 
   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);
-
-  gtk_style_context_reset_widgets (screen);
+  cascade = _gtk_style_cascade_get_for_screen (screen);
+  _gtk_style_cascade_add_provider (cascade, provider, priority);
 }
 
 /**
@@ -1311,23 +1063,62 @@ void
 gtk_style_context_remove_provider_for_screen (GdkScreen        *screen,
                                               GtkStyleProvider *provider)
 {
-  GList *providers, *list;
+  GtkStyleCascade *cascade;
 
   g_return_if_fail (GDK_IS_SCREEN (screen));
   g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
 
-  if (G_UNLIKELY (!provider_list_quark))
-    return;
+  cascade = _gtk_style_cascade_get_for_screen (screen);
+  _gtk_style_cascade_remove_provider (cascade, provider);
+}
 
-  list = providers = g_object_get_qdata (G_OBJECT (screen), provider_list_quark);
+/**
+ * gtk_style_context_get_section:
+ * @context: a #GtkStyleContext
+ * @property: style property name
+ *
+ * Queries the location in the CSS where @property was defined for the
+ * current @context. Note that the state to be queried is taken from
+ * gtk_style_context_get_state().
+ *
+ * If the location is not available, %NULL will be returned. The
+ * location might not be available for various reasons, such as the
+ * property being overridden, @property not naming a supported CSS
+ * property or tracking of definitions being disabled for performance
+ * reasons.
+ *
+ * Shorthand CSS properties cannot be queried for a location and will
+ * always return %NULL.
+ *
+ * Returns: %NULL or the section where value was defined
+ **/
+GtkCssSection *
+gtk_style_context_get_section (GtkStyleContext *context,
+                               const gchar     *property)
+{
+  GtkStyleContextPrivate *priv;
+  GtkStyleProperty *prop;
+  StyleData *data;
 
-  if (style_provider_remove (&list, provider))
-    {
-      if (list != providers)
-        g_object_set_qdata (G_OBJECT (screen), provider_list_quark, list);
+  g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
+  g_return_val_if_fail (property != NULL, NULL);
 
-      gtk_style_context_reset_widgets (screen);
-    }
+  priv = context->priv;
+  g_return_val_if_fail (priv->widget != NULL || priv->widget_path != NULL, NULL);
+
+  prop = _gtk_style_property_lookup (property);
+  if (!GTK_IS_CSS_STYLE_PROPERTY (prop))
+    return NULL;
+
+  data = style_data_lookup (context);
+  return _gtk_css_computed_values_get_section (data->store, _gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (prop)));
+}
+
+static GtkCssValue *
+gtk_style_context_query_func (guint    id,
+                              gpointer values)
+{
+  return _gtk_css_computed_values_get_value (values, id);
 }
 
 /**
@@ -1351,6 +1142,7 @@ gtk_style_context_get_property (GtkStyleContext *context,
                                 GValue          *value)
 {
   GtkStyleContextPrivate *priv;
+  GtkStyleProperty *prop;
   StyleData *data;
 
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
@@ -1358,29 +1150,25 @@ gtk_style_context_get_property (GtkStyleContext *context,
   g_return_if_fail (value != NULL);
 
   priv = context->priv;
+  g_return_if_fail (priv->widget != NULL || priv->widget_path != NULL);
 
-  g_return_if_fail (priv->widget_path != NULL);
-
-  data = style_data_lookup (context, state);
-  gtk_style_properties_get_property (data->store, property, state, value);
-}
-
-void
-_gtk_style_context_get_valist (GtkStyleContext *context,
-                              GtkStateFlags    state,
-                              GtkStylePropertyContext *property_context,
-                              va_list          args)
-{
-  GtkStyleContextPrivate *priv;
-  StyleData *data;
-
-  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
-
-  priv = context->priv;
-  g_return_if_fail (priv->widget_path != NULL);
+  prop = _gtk_style_property_lookup (property);
+  if (prop == NULL)
+    {
+      g_warning ("Style property \"%s\" is not registered", property);
+      return;
+    }
+  if (_gtk_style_property_get_value_type (prop) == G_TYPE_NONE)
+    {
+      g_warning ("Style property \"%s\" is not gettable", property);
+      return;
+    }
 
-  data = style_data_lookup (context, state);
-  _gtk_style_properties_get_valist (data->store, state, property_context, args);
+  gtk_style_context_save (context);
+  gtk_style_context_set_state (context, state);
+  data = style_data_lookup (context);
+  _gtk_style_property_query (prop, value, gtk_style_context_query_func, data->store);
+  gtk_style_context_restore (context);
 }
 
 /**
@@ -1398,16 +1186,34 @@ gtk_style_context_get_valist (GtkStyleContext *context,
                               GtkStateFlags    state,
                               va_list          args)
 {
-  GtkStyleContextPrivate *priv;
-  StyleData *data;
+  const gchar *property_name;
 
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
 
-  priv = context->priv;
-  g_return_if_fail (priv->widget_path != NULL);
+  property_name = va_arg (args, const gchar *);
+
+  while (property_name)
+    {
+      gchar *error = NULL;
+      GValue value = G_VALUE_INIT;
+
+      gtk_style_context_get_property (context,
+                                      property_name,
+                                      state,
+                                      &value);
+
+      G_VALUE_LCOPY (&value, args, 0, &error);
+      g_value_unset (&value);
+
+      if (error)
+        {
+          g_warning ("Could not get style property \"%s\": %s", property_name, error);
+          g_free (error);
+          break;
+        }
 
-  data = style_data_lookup (context, state);
-  gtk_style_properties_get_valist (data->store, state, args);
+      property_name = va_arg (args, const gchar *);
+    }
 }
 
 /**
@@ -1426,19 +1232,12 @@ gtk_style_context_get (GtkStyleContext *context,
                        GtkStateFlags    state,
                        ...)
 {
-  GtkStyleContextPrivate *priv;
-  StyleData *data;
   va_list args;
 
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
 
-  priv = context->priv;
-  g_return_if_fail (priv->widget_path != NULL);
-
-  data = style_data_lookup (context, state);
-
   va_start (args, state);
-  gtk_style_properties_get_valist (data->store, state, args);
+  gtk_style_context_get_valist (context, state, args);
   va_end (args);
 }
 
@@ -1464,6 +1263,8 @@ gtk_style_context_set_state (GtkStyleContext *context,
   priv = context->priv;
   info = priv->info_stack->data;
   info->state_flags = flags;
+  
+  gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_STATE);
 }
 
 /**
@@ -1490,22 +1291,6 @@ gtk_style_context_get_state (GtkStyleContext *context)
   return info->state_flags;
 }
 
-static gboolean
-context_has_animatable_region (GtkStyleContext *context,
-                               gpointer         region_id)
-{
-  GtkStyleContextPrivate *priv;
-
-  /* NULL region_id means everything
-   * rendered through the style context
-   */
-  if (!region_id)
-    return TRUE;
-
-  priv = context->priv;
-  return g_slist_find (priv->animation_regions, region_id) != NULL;
-}
-
 /**
  * gtk_style_context_state_is_running:
  * @context: a #GtkStyleContext
@@ -1524,34 +1309,16 @@ context_has_animatable_region (GtkStyleContext *context,
  * Returns: %TRUE if there is a running transition animation for @state.
  *
  * Since: 3.0
+ *
+ * Deprecated: 3.6: This function always returns %FALSE
  **/
 gboolean
 gtk_style_context_state_is_running (GtkStyleContext *context,
                                     GtkStateType     state,
                                     gdouble         *progress)
 {
-  GtkStyleContextPrivate *priv;
-  AnimationInfo *info;
-  GSList *l;
-
   g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
 
-  priv = context->priv;
-
-  for (l = priv->animations; l; l = l->next)
-    {
-      info = l->data;
-
-      if (info->state == state &&
-          context_has_animatable_region (context, info->region_id))
-        {
-          if (progress)
-            *progress = _gtk_timeline_get_progress (info->timeline);
-
-          return TRUE;
-        }
-    }
-
   return FALSE;
 }
 
@@ -1580,6 +1347,7 @@ gtk_style_context_set_path (GtkStyleContext *context,
   g_return_if_fail (path != NULL);
 
   priv = context->priv;
+  g_return_if_fail (priv->widget == NULL);
 
   if (priv->widget_path)
     {
@@ -1590,7 +1358,7 @@ gtk_style_context_set_path (GtkStyleContext *context,
   if (path)
     priv->widget_path = gtk_widget_path_copy (path);
 
-  gtk_style_context_invalidate (context);
+  _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANY);
 }
 
 /**
@@ -1609,7 +1377,78 @@ gtk_style_context_get_path (GtkStyleContext *context)
   GtkStyleContextPrivate *priv;
 
   priv = context->priv;
-  return priv->widget_path;
+  if (priv->widget)
+    return gtk_widget_get_path (priv->widget);
+  else
+    return priv->widget_path;
+}
+
+/**
+ * gtk_style_context_set_parent:
+ * @context: a #GtkStyleContext
+ * @parent: (allow-none): the new parent or %NULL
+ *
+ * Sets the parent style context for @context. The parent style
+ * context is used to implement
+ * <ulink url="http://www.w3.org/TR/css3-cascade/#inheritance">inheritance</ulink>
+ * of properties.
+ *
+ * If you are using a #GtkStyleContext returned from
+ * gtk_widget_get_style_context(), the parent will be set for you.
+ *
+ * Since: 3.4
+ **/
+void
+gtk_style_context_set_parent (GtkStyleContext *context,
+                              GtkStyleContext *parent)
+{
+  GtkStyleContextPrivate *priv;
+
+  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+  g_return_if_fail (parent == NULL || GTK_IS_STYLE_CONTEXT (parent));
+
+  priv = context->priv;
+
+  if (priv->parent == parent)
+    return;
+
+  if (parent)
+    {
+      parent->priv->children = g_slist_prepend (parent->priv->children, context);
+      g_object_ref (parent);
+      if (priv->invalid)
+        gtk_style_context_set_invalid (parent, TRUE);
+    }
+
+  if (priv->parent)
+    {
+      priv->parent->priv->children = g_slist_remove (priv->parent->priv->children, context);
+      g_object_unref (priv->parent);
+    }
+
+  priv->parent = parent;
+
+  g_object_notify (G_OBJECT (context), "parent");
+  _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANY_PARENT | GTK_CSS_CHANGE_ANY_SIBLING);
+}
+
+/**
+ * gtk_style_context_get_parent:
+ * @context: a #GtkStyleContext
+ *
+ * Gets the parent context set via gtk_style_context_set_parent().
+ * See that function for details.
+ *
+ * Returns: (transfer none): the parent context or %NULL
+ *
+ * Since: 3.4
+ **/
+GtkStyleContext *
+gtk_style_context_get_parent (GtkStyleContext *context)
+{
+  g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
+
+  return context->priv->parent;
 }
 
 /**
@@ -1674,8 +1513,6 @@ gtk_style_context_restore (GtkStyleContext *context)
       info = style_info_new ();
       priv->info_stack = g_slist_prepend (priv->info_stack, info);
     }
-
-  priv->current_data = NULL;
 }
 
 static gboolean
@@ -1816,8 +1653,7 @@ gtk_style_context_add_class (GtkStyleContext *context,
     {
       g_array_insert_val (info->style_classes, position, class_quark);
 
-      /* Unset current data, as it likely changed due to the class change */
-      priv->current_data = NULL;
+      gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_CLASS);
     }
 }
 
@@ -1856,8 +1692,7 @@ gtk_style_context_remove_class (GtkStyleContext *context,
     {
       g_array_remove_index (info->style_classes, position);
 
-      /* Unset current data, as it likely changed due to the class change */
-      priv->current_data = NULL;
+      gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_CLASS);
     }
 }
 
@@ -2061,8 +1896,7 @@ gtk_style_context_add_region (GtkStyleContext *context,
 
       g_array_insert_val (info->regions, position, region);
 
-      /* Unset current data, as it likely changed due to the region change */
-      priv->current_data = NULL;
+      gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_REGION);
     }
 }
 
@@ -2101,8 +1935,7 @@ gtk_style_context_remove_region (GtkStyleContext *context,
     {
       g_array_remove_index (info->regions, position);
 
-      /* Unset current data, as it likely changed due to the region change */
-      priv->current_data = NULL;
+      gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_REGION);
     }
 }
 
@@ -2180,6 +2013,26 @@ style_property_values_cmp (gconstpointer bsearch_node1,
   return 0;
 }
 
+GtkCssValue *
+_gtk_style_context_peek_property (GtkStyleContext *context,
+                                  guint            property_id)
+{
+  StyleData *data = style_data_lookup (context);
+
+  return _gtk_css_computed_values_get_value (data->store, property_id);
+}
+
+double
+_gtk_style_context_get_number (GtkStyleContext *context,
+                               guint            property_id,
+                               double           one_hundred_percent)
+{
+  GtkCssValue *value;
+  
+  value = _gtk_style_context_peek_property (context, property_id);
+  return _gtk_css_number_value_get (value, one_hundred_percent);
+}
+
 const GValue *
 _gtk_style_context_peek_style_property (GtkStyleContext *context,
                                         GType            widget_type,
@@ -2188,12 +2041,15 @@ _gtk_style_context_peek_style_property (GtkStyleContext *context,
 {
   GtkStyleContextPrivate *priv;
   PropertyValue *pcache, key = { 0 };
-  GList *global_list = NULL;
   StyleData *data;
   guint i;
 
   priv = context->priv;
-  data = style_data_lookup (context, state);
+
+  gtk_style_context_save (context);
+  gtk_style_context_set_state (context, state);
+  data = style_data_lookup (context);
+  gtk_style_context_restore (context);
 
   key.widget_type = widget_type;
   key.state = state;
@@ -2223,72 +2079,50 @@ _gtk_style_context_peek_style_property (GtkStyleContext *context,
   g_param_spec_ref (pcache->pspec);
   g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
 
-  if (priv->screen)
-    {
-      global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
-      global_list = g_list_last (global_list);
-    }
-
-  if (priv->widget_path)
+  if (priv->widget || priv->widget_path)
     {
-      GList *list, *global, *elem;
-
-      list = priv->providers_last;
-      global = global_list;
-
-      while ((elem = find_next_candidate (list, global, FALSE)) != NULL)
+      if (gtk_style_provider_get_style_property (GTK_STYLE_PROVIDER (priv->cascade),
+                                                 priv->widget ? gtk_widget_get_path (priv->widget)
+                                                              : priv->widget_path,
+                                                 state, pspec, &pcache->value))
         {
-          GtkStyleProviderData *provider_data;
-
-          provider_data = elem->data;
-
-          if (elem == list)
-            list = list->prev;
-          else
-            global = global->prev;
-
-          if (gtk_style_provider_get_style_property (provider_data->provider,
-                                                     priv->widget_path, state,
-                                                     pspec, &pcache->value))
+          /* Resolve symbolic colors to GdkColor/GdkRGBA */
+          if (G_VALUE_TYPE (&pcache->value) == GTK_TYPE_SYMBOLIC_COLOR)
             {
-              /* Resolve symbolic colors to GdkColor/GdkRGBA */
-              if (G_VALUE_TYPE (&pcache->value) == GTK_TYPE_SYMBOLIC_COLOR)
-                {
-                  GtkSymbolicColor *color;
-                  GdkRGBA rgba;
+              GtkSymbolicColor *color;
+              GdkRGBA rgba;
+
+              color = g_value_dup_boxed (&pcache->value);
 
-                  color = g_value_dup_boxed (&pcache->value);
+              g_value_unset (&pcache->value);
 
-                  g_value_unset (&pcache->value);
+              if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
+                g_value_init (&pcache->value, GDK_TYPE_RGBA);
+              else
+                g_value_init (&pcache->value, GDK_TYPE_COLOR);
 
+              if (_gtk_style_context_resolve_color (context, color, &rgba))
+                {
                   if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
-                    g_value_init (&pcache->value, GDK_TYPE_RGBA);
+                    g_value_set_boxed (&pcache->value, &rgba);
                   else
-                    g_value_init (&pcache->value, GDK_TYPE_COLOR);
-
-                  if (gtk_symbolic_color_resolve (color, data->store, &rgba))
                     {
-                      if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
-                        g_value_set_boxed (&pcache->value, &rgba);
-                      else
-                        {
-                          GdkColor rgb;
-
-                          rgb.red = rgba.red * 65535. + 0.5;
-                          rgb.green = rgba.green * 65535. + 0.5;
-                          rgb.blue = rgba.blue * 65535. + 0.5;
-
-                          g_value_set_boxed (&pcache->value, &rgb);
-                        }
-                    }
-                  else
-                    g_param_value_set_default (pspec, &pcache->value);
+                      GdkColor rgb;
 
-                  gtk_symbolic_color_unref (color);
+                      rgb.red = rgba.red * 65535. + 0.5;
+                      rgb.green = rgba.green * 65535. + 0.5;
+                      rgb.blue = rgba.blue * 65535. + 0.5;
+
+                      g_value_set_boxed (&pcache->value, &rgb);
+                    }
                 }
+              else
+                g_param_value_set_default (pspec, &pcache->value);
 
-              return &pcache->value;
+              gtk_symbolic_color_unref (color);
             }
+
+          return &pcache->value;
         }
     }
 
@@ -2327,17 +2161,24 @@ gtk_style_context_get_style_property (GtkStyleContext *context,
 
   priv = context->priv;
 
-  if (!priv->widget_path)
-    return;
+  if (priv->widget)
+    {
+      widget_type = G_OBJECT_TYPE (priv->widget);
+    }
+  else
+    {
+      if (!priv->widget_path)
+        return;
 
-  widget_type = gtk_widget_path_get_object_type (priv->widget_path);
+      widget_type = gtk_widget_path_get_object_type (priv->widget_path);
 
-  if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
-    {
-      g_warning ("%s: can't get style properties for non-widget class `%s'",
-                 G_STRLOC,
-                 g_type_name (widget_type));
-      return;
+      if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
+        {
+          g_warning ("%s: can't get style properties for non-widget class `%s'",
+                     G_STRLOC,
+                     g_type_name (widget_type));
+          return;
+        }
     }
 
   widget_class = g_type_class_ref (widget_type);
@@ -2392,17 +2233,24 @@ gtk_style_context_get_style_valist (GtkStyleContext *context,
   prop_name = va_arg (args, const gchar *);
   priv = context->priv;
 
-  if (!priv->widget_path)
-    return;
+  if (priv->widget)
+    {
+      widget_type = G_OBJECT_TYPE (priv->widget);
+    }
+  else
+    {
+      if (!priv->widget_path)
+        return;
 
-  widget_type = gtk_widget_path_get_object_type (priv->widget_path);
+      widget_type = gtk_widget_path_get_object_type (priv->widget_path);
 
-  if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
-    {
-      g_warning ("%s: can't get style properties for non-widget class `%s'",
-                 G_STRLOC,
-                 g_type_name (widget_type));
-      return;
+      if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
+        {
+          g_warning ("%s: can't get style properties for non-widget class `%s'",
+                     G_STRLOC,
+                     g_type_name (widget_type));
+          return;
+        }
     }
 
   state = gtk_style_context_get_state (context);
@@ -2424,7 +2272,7 @@ gtk_style_context_get_style_valist (GtkStyleContext *context,
                      G_STRLOC,
                      g_type_name (widget_type),
                      prop_name);
-          continue;
+          break;
         }
 
       peek_value = _gtk_style_context_peek_style_property (context, widget_type,
@@ -2439,6 +2287,7 @@ gtk_style_context_get_style_valist (GtkStyleContext *context,
                      G_VALUE_TYPE_NAME (peek_value),
                      error);
           g_free (error);
+          break;
         }
 
       prop_name = va_arg (args, const gchar *);
@@ -2485,28 +2334,12 @@ gtk_style_context_lookup_icon_set (GtkStyleContext *context,
                                    const gchar     *stock_id)
 {
   GtkStyleContextPrivate *priv;
-  StyleData *data;
-  GSList *list;
 
   g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
   g_return_val_if_fail (stock_id != NULL, NULL);
 
   priv = context->priv;
-  g_return_val_if_fail (priv->widget_path != NULL, NULL);
-
-  data = style_data_lookup (context, 0);
-
-  for (list = data->icon_factories; list; list = list->next)
-    {
-      GtkIconFactory *factory;
-      GtkIconSet *icon_set;
-
-      factory = list->data;
-      icon_set = gtk_icon_factory_lookup (factory, stock_id);
-
-      if (icon_set)
-        return icon_set;
-    }
+  g_return_val_if_fail (priv->widget != NULL || priv->widget_path != NULL, NULL);
 
   return gtk_icon_factory_lookup_default (stock_id);
 }
@@ -2540,6 +2373,17 @@ gtk_style_context_set_screen (GtkStyleContext *context,
   if (priv->screen == screen)
     return;
 
+  if (priv->cascade == _gtk_style_cascade_get_for_screen (priv->screen))
+    {
+      g_object_unref (priv->cascade);
+      priv->cascade = _gtk_style_cascade_get_for_screen (screen);
+      g_object_ref (priv->cascade);
+    }
+  else
+    {
+      _gtk_style_cascade_set_parent (priv->cascade, _gtk_style_cascade_get_for_screen (screen));
+    }
+
   priv->screen = screen;
 
   g_object_notify (G_OBJECT (context), "screen");
@@ -2669,6 +2513,50 @@ gtk_style_context_get_junction_sides (GtkStyleContext *context)
   return info->junction_sides;
 }
 
+static GtkSymbolicColor *
+gtk_style_context_color_lookup_func (gpointer    contextp,
+                                     const char *name)
+{
+  GtkStyleContext *context = contextp;
+
+  return _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (context->priv->cascade), name);
+}
+
+GtkCssValue *
+_gtk_style_context_resolve_color_value (GtkStyleContext  *context,
+                                       GtkSymbolicColor *color)
+{
+  g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
+  g_return_val_if_fail (color != NULL, FALSE);
+
+  return _gtk_symbolic_color_resolve_full (color,
+                                           gtk_style_context_color_lookup_func,
+                                           context);
+}
+
+
+gboolean
+_gtk_style_context_resolve_color (GtkStyleContext  *context,
+                                  GtkSymbolicColor *color,
+                                  GdkRGBA          *result)
+{
+  GtkCssValue *val;
+
+  g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
+  g_return_val_if_fail (color != NULL, FALSE);
+  g_return_val_if_fail (result != NULL, FALSE);
+
+  val = _gtk_symbolic_color_resolve_full (color,
+                                         gtk_style_context_color_lookup_func,
+                                         context);
+  if (val == NULL)
+    return FALSE;
+
+  *result = *_gtk_css_rgba_value_get_rgba (val);
+  _gtk_css_value_unref (val);
+  return TRUE;
+}
+
 /**
  * gtk_style_context_lookup_color:
  * @context: a #GtkStyleContext
@@ -2684,24 +2572,17 @@ gtk_style_context_lookup_color (GtkStyleContext *context,
                                 const gchar     *color_name,
                                 GdkRGBA         *color)
 {
-  GtkStyleContextPrivate *priv;
   GtkSymbolicColor *sym_color;
-  StyleData *data;
 
   g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
   g_return_val_if_fail (color_name != NULL, FALSE);
   g_return_val_if_fail (color != NULL, FALSE);
 
-  priv = context->priv;
-  g_return_val_if_fail (priv->widget_path != NULL, FALSE);
-
-  data = style_data_lookup (context, 0);
-  sym_color = gtk_style_properties_lookup_color (data->store, color_name);
-
-  if (!sym_color)
+  sym_color = gtk_style_context_color_lookup_func (context, color_name);
+  if (sym_color == NULL)
     return FALSE;
 
-  return gtk_symbolic_color_resolve (sym_color, data->store, color);
+  return _gtk_style_context_resolve_color (context, sym_color, color);
 }
 
 /**
@@ -2756,6 +2637,8 @@ gtk_style_context_lookup_color (GtkStyleContext *context,
  * is why the style places the transition under the :hover pseudo-class.
  *
  * Since: 3.0
+ *
+ * Deprecated: 3.6: This function does nothing.
  **/
 void
 gtk_style_context_notify_state_change (GtkStyleContext *context,
@@ -2764,101 +2647,10 @@ gtk_style_context_notify_state_change (GtkStyleContext *context,
                                        GtkStateType     state,
                                        gboolean         state_value)
 {
-  GtkStyleContextPrivate *priv;
-  GtkAnimationDescription *desc;
-  AnimationInfo *info;
-  GtkStateFlags flags;
-  StyleData *data;
-
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (state > GTK_STATE_NORMAL && state <= GTK_STATE_FOCUSED);
-
-  priv = context->priv;
-  g_return_if_fail (priv->widget_path != NULL);
-
-  state_value = (state_value == TRUE);
-
-  switch (state)
-    {
-    case GTK_STATE_ACTIVE:
-      flags = GTK_STATE_FLAG_ACTIVE;
-      break;
-    case GTK_STATE_PRELIGHT:
-      flags = GTK_STATE_FLAG_PRELIGHT;
-      break;
-    case GTK_STATE_SELECTED:
-      flags = GTK_STATE_FLAG_SELECTED;
-      break;
-    case GTK_STATE_INSENSITIVE:
-      flags = GTK_STATE_FLAG_INSENSITIVE;
-      break;
-    case GTK_STATE_INCONSISTENT:
-      flags = GTK_STATE_FLAG_INCONSISTENT;
-      break;
-    case GTK_STATE_FOCUSED:
-      flags = GTK_STATE_FLAG_FOCUSED;
-      break;
-    case GTK_STATE_NORMAL:
-    default:
-      flags = 0;
-      break;
-    }
-
-  /* Find out if there is any animation description for the given
-   * state, it will fallback to the normal state as well if necessary.
-   */
-  data = style_data_lookup (context, state);
-  gtk_style_properties_get (data->store, flags,
-                            "transition", &desc,
-                            NULL);
-
-  if (!desc)
-    return;
-
-  if (_gtk_animation_description_get_duration (desc) == 0)
-    {
-      _gtk_animation_description_unref (desc);
-      return;
-    }
-
-  info = animation_info_lookup (context, region_id, state);
-
-  if (info &&
-      info->target_value != state_value)
-    {
-      /* Target values are the opposite */
-      if (!_gtk_timeline_get_loop (info->timeline))
-        {
-          /* Reverse the animation */
-          if (_gtk_timeline_get_direction (info->timeline) == GTK_TIMELINE_DIRECTION_FORWARD)
-            _gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_BACKWARD);
-          else
-            _gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_FORWARD);
-
-          info->target_value = state_value;
-        }
-      else
-        {
-          /* Take it out of its looping state */
-          _gtk_timeline_set_loop (info->timeline, FALSE);
-        }
-    }
-  else if (!info &&
-           (!_gtk_animation_description_get_loop (desc) ||
-            state_value))
-    {
-      info = animation_info_new (context, region_id,
-                                 _gtk_animation_description_get_duration (desc),
-                                 _gtk_animation_description_get_progress_type (desc),
-                                 _gtk_animation_description_get_loop (desc),
-                                 state, state_value, window);
-
-      priv->animations = g_slist_prepend (priv->animations, info);
-      priv->animations_invalidated = TRUE;
-    }
-
-  _gtk_animation_description_unref (desc);
+  g_return_if_fail (context->priv->widget != NULL || context->priv->widget_path != NULL);
 }
 
 /**
@@ -2878,60 +2670,14 @@ gtk_style_context_notify_state_change (GtkStyleContext *context,
  * animatable regions.
  *
  * Since: 3.0
+ *
+ * Deprecated: 3.6: This function does nothing.
  **/
 void
 gtk_style_context_cancel_animations (GtkStyleContext *context,
                                      gpointer         region_id)
 {
-  GtkStyleContextPrivate *priv;
-  AnimationInfo *info;
-  GSList *l;
-
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
-
-  priv = context->priv;
-  l = priv->animations;
-
-  while (l)
-    {
-      info = l->data;
-      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);
-        }
-    }
-}
-
-static gboolean
-is_parent_of (GdkWindow *parent,
-              GdkWindow *child)
-{
-  GtkWidget *child_widget, *parent_widget;
-  GdkWindow *window;
-
-  gdk_window_get_user_data (child, (gpointer *) &child_widget);
-  gdk_window_get_user_data (parent, (gpointer *) &parent_widget);
-
-  if (child_widget != parent_widget &&
-      !gtk_widget_is_ancestor (child_widget, parent_widget))
-    return FALSE;
-
-  window = child;
-
-  while (window)
-    {
-      if (window == parent)
-        return TRUE;
-
-      window = gdk_window_get_parent (window);
-    }
-
-  return FALSE;
 }
 
 /**
@@ -2948,6 +2694,8 @@ is_parent_of (GdkWindow *parent,
  * with it.
  *
  * Since: 3.0
+ *
+ * Deprecated: 3.6: This function does nothing.
  **/
 void
 gtk_style_context_scroll_animations (GtkStyleContext *context,
@@ -2955,26 +2703,8 @@ gtk_style_context_scroll_animations (GtkStyleContext *context,
                                      gint             dx,
                                      gint             dy)
 {
-  GtkStyleContextPrivate *priv;
-  AnimationInfo *info;
-  GSList *l;
-
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
   g_return_if_fail (GDK_IS_WINDOW (window));
-
-  priv = context->priv;
-  l = priv->animations;
-
-  while (l)
-    {
-      info = l->data;
-      l = l->next;
-
-      if (info->invalidation_region &&
-          (window == info->window ||
-           is_parent_of (window, info->window)))
-        cairo_region_translate (info->invalidation_region, dx, dy);
-    }
 }
 
 /**
@@ -2993,18 +2723,15 @@ gtk_style_context_scroll_animations (GtkStyleContext *context,
  * can uniquely identify rendered elements subject to a state transition.
  *
  * Since: 3.0
+ *
+ * Deprecated: 3.6: This function does nothing.
  **/
 void
 gtk_style_context_push_animatable_region (GtkStyleContext *context,
                                           gpointer         region_id)
 {
-  GtkStyleContextPrivate *priv;
-
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
   g_return_if_fail (region_id != NULL);
-
-  priv = context->priv;
-  priv->animation_regions = g_slist_prepend (priv->animation_regions, region_id);
 }
 
 /**
@@ -3015,150 +2742,122 @@ gtk_style_context_push_animatable_region (GtkStyleContext *context,
  * See gtk_style_context_push_animatable_region().
  *
  * Since: 3.0
+ *
+ * Deprecated: 3.6: This function does nothing.
  **/
 void
 gtk_style_context_pop_animatable_region (GtkStyleContext *context)
 {
-  GtkStyleContextPrivate *priv;
-
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
-
-  priv = context->priv;
-  priv->animation_regions = g_slist_delete_link (priv->animation_regions,
-                                                 priv->animation_regions);
 }
 
-void
-_gtk_style_context_invalidate_animation_areas (GtkStyleContext *context)
+static void
+gtk_style_context_do_invalidate (GtkStyleContext *context,
+                                 gboolean         clear_caches)
 {
   GtkStyleContextPrivate *priv;
-  GSList *l;
+
+  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
 
   priv = context->priv;
 
-  for (l = priv->animations; l; l = l->next)
-    {
-      AnimationInfo *info;
+  /* Avoid reentrancy */
+  if (priv->invalidating_context)
+    return;
 
-      info = l->data;
+  priv->invalidating_context = TRUE;
+
+  if (clear_caches)
+    {
+      GSList *list;
 
-      /* A NULL invalidation region means it has to be recreated on
-       * the next expose event, this happens usually after a widget
-       * allocation change, so the next expose after it will update
-       * the invalidation region.
-       */
-      if (info->invalidation_region)
+      for (list = priv->info_stack; list; list = list->next)
         {
-          cairo_region_destroy (info->invalidation_region);
-          info->invalidation_region = NULL;
+          GtkStyleInfo *info = list->data;
+          info->data = NULL;
         }
+      g_hash_table_remove_all (priv->style_data);
     }
 
-  priv->animations_invalidated = TRUE;
+  g_signal_emit (context, signals[CHANGED], 0);
+
+  priv->invalidating_context = FALSE;
 }
 
 void
-_gtk_style_context_coalesce_animation_areas (GtkStyleContext *context,
-                                             GtkWidget       *widget)
+_gtk_style_context_validate (GtkStyleContext *context,
+                             GtkCssChange     change)
 {
   GtkStyleContextPrivate *priv;
-  GSList *l;
+  GSList *list;
+
+  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
 
   priv = context->priv;
 
-  if (!priv->animations_invalidated)
+  change |= priv->pending_changes;
+
+  if (!priv->invalid && change == 0)
     return;
 
-  l = priv->animations;
+  priv->pending_changes = 0;
+  gtk_style_context_set_invalid (context, FALSE);
 
-  while (l)
+  /* Try to avoid invalidating if we can */
+  if (change & GTK_STYLE_CONTEXT_RADICAL_CHANGE)
     {
-      AnimationInfo *info;
-      gint rel_x, rel_y;
-      GSList *cur;
-      guint i;
-
-      cur = l;
-      info = cur->data;
-      l = l->next;
-
-      if (info->invalidation_region)
-        continue;
-
-      if (info->rectangles->len == 0)
-        continue;
-
-      info->invalidation_region = cairo_region_create ();
-      _gtk_widget_get_translation_to_window (widget, info->window, &rel_x, &rel_y);
-
-      for (i = 0; i < info->rectangles->len; i++)
+      priv->relevant_changes = GTK_CSS_CHANGE_ANY;
+    }
+  else
+    {
+      if (priv->relevant_changes == GTK_CSS_CHANGE_ANY)
         {
-          cairo_rectangle_int_t *rect;
+          GtkWidgetPath *path;
+          GtkCssMatcher matcher;
 
-          rect = &g_array_index (info->rectangles, cairo_rectangle_int_t, i);
+          path = create_query_path (context);
+          _gtk_css_matcher_init (&matcher, path, ((GtkStyleInfo *) priv->info_stack->data)->state_flags);
 
-          /* These are widget relative coordinates,
-           * so have them inverted to be window relative
-           */
-          rect->x -= rel_x;
-          rect->y -= rel_y;
+          priv->relevant_changes = _gtk_style_provider_private_get_change (GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
+                                                                           &matcher);
+          priv->relevant_changes &= ~GTK_STYLE_CONTEXT_RADICAL_CHANGE;
 
-          cairo_region_union_rectangle (info->invalidation_region, rect);
+          gtk_widget_path_unref (path);
         }
+    }
+
+  if (priv->relevant_changes & change)
+    {
+      GtkStyleInfo *info = priv->info_stack->data;
+      gboolean clear_cache = ((priv->relevant_changes & change) & ~GTK_STYLE_CONTEXT_CACHED_CHANGE) != 0;
 
-      g_array_remove_range (info->rectangles, 0, info->rectangles->len);
+      info->data = NULL;
+      gtk_style_context_do_invalidate (context, clear_cache);
     }
 
-  priv->animations_invalidated = FALSE;
+  change = _gtk_css_change_for_child (change);
+  for (list = priv->children; list; list = list->next)
+    {
+      _gtk_style_context_validate (list->data, change);
+    }
 }
 
-static void
-store_animation_region (GtkStyleContext *context,
-                        gdouble          x,
-                        gdouble          y,
-                        gdouble          width,
-                        gdouble          height)
+void
+_gtk_style_context_queue_invalidate (GtkStyleContext *context,
+                                     GtkCssChange     change)
 {
   GtkStyleContextPrivate *priv;
-  GSList *l;
+
+  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+  g_return_if_fail (change != 0);
 
   priv = context->priv;
 
-  if (!priv->animations_invalidated)
+  if (priv->widget == NULL && priv->widget_path == NULL)
     return;
 
-  for (l = priv->animations; l; l = l->next)
-    {
-      AnimationInfo *info;
-
-      info = l->data;
-
-      /* The animation doesn't need updating
-       * the invalidation area, bail out.
-       */
-      if (info->invalidation_region)
-        continue;
-
-      if (context_has_animatable_region (context, info->region_id))
-        {
-          cairo_rectangle_int_t rect;
-
-          rect.x = (gint) x;
-          rect.y = (gint) y;
-          rect.width = (gint) width;
-          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);
-            }
-        }
-    }
+  priv->pending_changes |= change;
+  gtk_style_context_set_invalid (context, TRUE);
 }
 
 /**
@@ -3177,24 +2876,9 @@ store_animation_region (GtkStyleContext *context,
 void
 gtk_style_context_invalidate (GtkStyleContext *context)
 {
-  GtkStyleContextPrivate *priv;
-
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
 
-  priv = context->priv;
-
-  /* Avoid reentrancy */
-  if (priv->invalidating_context)
-    return;
-
-  priv->invalidating_context = TRUE;
-
-  g_hash_table_remove_all (priv->style_data);
-  priv->current_data = NULL;
-
-  g_signal_emit (context, signals[CHANGED], 0);
-
-  priv->invalidating_context = FALSE;
+  gtk_style_context_do_invalidate (context, TRUE);
 }
 
 /**
@@ -3342,41 +3026,23 @@ gtk_style_context_get_border (GtkStyleContext *context,
                               GtkStateFlags    state,
                               GtkBorder       *border)
 {
-  GtkStyleContextPrivate *priv;
-  StyleData *data;
   int top, left, bottom, right;
-  GtkBorderStyle border_style;
 
   g_return_if_fail (border != NULL);
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
 
-  priv = context->priv;
-  g_return_if_fail (priv->widget_path != NULL);
-
-  data = style_data_lookup (context, state);
-  gtk_style_properties_get (data->store,
-                            state,
-                           "border-style", &border_style,
-                            "border-top-width", &top,
-                            "border-top-width", &top,
-                            "border-left-width", &left,
-                            "border-bottom-width", &bottom,
-                            "border-right-width", &right,
-                            NULL);
-  if (border_style == GTK_BORDER_STYLE_NONE)
-    {
-      border->top = 0;
-      border->left = 0;
-      border->bottom = 0;
-      border->right = 0;
-    }
-  else
-    {
-      border->top = top;
-      border->left = left;
-      border->bottom = bottom;
-      border->right = right;
-    }
+  gtk_style_context_get (context,
+                         state,
+                         "border-top-width", &top,
+                         "border-left-width", &left,
+                         "border-bottom-width", &bottom,
+                         "border-right-width", &right,
+                         NULL);
+
+  border->top = top;
+  border->left = left;
+  border->bottom = bottom;
+  border->right = right;
 }
 
 /**
@@ -3395,24 +3061,18 @@ gtk_style_context_get_padding (GtkStyleContext *context,
                                GtkStateFlags    state,
                                GtkBorder       *padding)
 {
-  GtkStyleContextPrivate *priv;
-  StyleData *data;
   int top, left, bottom, right;
 
   g_return_if_fail (padding != NULL);
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
 
-  priv = context->priv;
-  g_return_if_fail (priv->widget_path != NULL);
-
-  data = style_data_lookup (context, state);
-  gtk_style_properties_get (data->store,
-                            state,
-                            "padding-top", &top,
-                            "padding-left", &left,
-                            "padding-bottom", &bottom,
-                            "padding-right", &right,
-                            NULL);
+  gtk_style_context_get (context,
+                         state,
+                         "padding-top", &top,
+                         "padding-left", &left,
+                         "padding-bottom", &bottom,
+                         "padding-right", &right,
+                         NULL);
 
   padding->top = top;
   padding->left = left;
@@ -3436,24 +3096,18 @@ gtk_style_context_get_margin (GtkStyleContext *context,
                               GtkStateFlags    state,
                               GtkBorder       *margin)
 {
-  GtkStyleContextPrivate *priv;
-  StyleData *data;
   int top, left, bottom, right;
 
   g_return_if_fail (margin != NULL);
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
 
-  priv = context->priv;
-  g_return_if_fail (priv->widget_path != NULL);
-
-  data = style_data_lookup (context, state);
-  gtk_style_properties_get (data->store,
-                            state,
-                            "margin-top", &top,
-                            "margin-left", &left,
-                            "margin-bottom", &bottom,
-                            "margin-right", &right,
-                            NULL);
+  gtk_style_context_get (context,
+                         state,
+                         "margin-top", &top,
+                         "margin-left", &left,
+                         "margin-bottom", &bottom,
+                         "margin-right", &right,
+                         NULL);
 
   margin->top = top;
   margin->left = left;
@@ -3482,39 +3136,29 @@ gtk_style_context_get_font (GtkStyleContext *context,
 {
   GtkStyleContextPrivate *priv;
   StyleData *data;
-  GHashTable *font_cache;
   PangoFontDescription *description;
 
   g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
 
   priv = context->priv;
-  g_return_val_if_fail (priv->widget_path != NULL, NULL);
+  g_return_val_if_fail (priv->widget != NULL || priv->widget_path != NULL, NULL);
 
-  data = style_data_lookup (context, state);
+  gtk_style_context_save (context);
+  gtk_style_context_set_state (context, state);
+  data = style_data_lookup (context);
+  gtk_style_context_restore (context);
 
   /* Yuck, fonts are created on-demand but we don't return a ref.
    * Do bad things to achieve this requirement */
-  font_cache = g_object_get_data (G_OBJECT (data->store), "font-cache-for-get_font");
-  if (font_cache)
-    {
-      description = g_hash_table_lookup (font_cache, GUINT_TO_POINTER (state));
-    }
-  else
+  description = g_object_get_data (G_OBJECT (data->store), "font-cache-for-get_font");
+  if (description == NULL)
     {
-      font_cache = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) pango_font_description_free);
+      gtk_style_context_get (context, state, "font", &description, NULL);
       g_object_set_data_full (G_OBJECT (data->store),
                               "font-cache-for-get_font",
-                              font_cache,
-                              (GDestroyNotify) g_hash_table_unref);
-      description = NULL;
-    }
-
-  if (description == NULL)
-    {
-      gtk_style_properties_get (data->store, state, "font", &description, NULL);
-      g_hash_table_insert (font_cache, GUINT_TO_POINTER (state), description);
+                              description,
+                              (GDestroyNotify) pango_font_description_free);
     }
-
   return description;
 }
 
@@ -3614,7 +3258,6 @@ gtk_render_check (GtkStyleContext *context,
 
   cairo_save (cr);
 
-  store_animation_region (context, x, y, width, height);
 
   _gtk_theming_engine_set_context (priv->theming_engine, context);
   engine_class->render_check (priv->theming_engine, cr,
@@ -3665,8 +3308,6 @@ gtk_render_option (GtkStyleContext *context,
 
   cairo_save (cr);
 
-  store_animation_region (context, x, y, width, height);
-
   _gtk_theming_engine_set_context (priv->theming_engine, context);
   engine_class->render_option (priv->theming_engine, cr,
                                x, y, width, height);
@@ -3717,8 +3358,6 @@ gtk_render_arrow (GtkStyleContext *context,
   gtk_style_context_save (context);
   gtk_style_context_add_class (context, GTK_STYLE_CLASS_ARROW);
 
-  store_animation_region (context, x, y, size, size);
-
   _gtk_theming_engine_set_context (priv->theming_engine, context);
   engine_class->render_arrow (priv->theming_engine, cr,
                               angle, x, y, size);
@@ -3770,8 +3409,6 @@ gtk_render_background (GtkStyleContext *context,
 
   cairo_save (cr);
 
-  store_animation_region (context, x, y, width, height);
-
   _gtk_theming_engine_set_context (priv->theming_engine, context);
   engine_class->render_background (priv->theming_engine, cr, x, y, width, height);
 
@@ -3823,8 +3460,6 @@ gtk_render_frame (GtkStyleContext *context,
 
   cairo_save (cr);
 
-  store_animation_region (context, x, y, width, height);
-
   _gtk_theming_engine_set_context (priv->theming_engine, context);
   engine_class->render_frame (priv->theming_engine, cr, x, y, width, height);
 
@@ -3873,8 +3508,6 @@ gtk_render_expander (GtkStyleContext *context,
 
   cairo_save (cr);
 
-  store_animation_region (context, x, y, width, height);
-
   _gtk_theming_engine_set_context (priv->theming_engine, context);
   engine_class->render_expander (priv->theming_engine, cr, x, y, width, height);
 
@@ -3920,8 +3553,6 @@ gtk_render_focus (GtkStyleContext *context,
 
   cairo_save (cr);
 
-  store_animation_region (context, x, y, width, height);
-
   _gtk_theming_engine_set_context (priv->theming_engine, context);
   engine_class->render_focus (priv->theming_engine, cr, x, y, width, height);
 
@@ -3962,12 +3593,6 @@ gtk_render_layout (GtkStyleContext *context,
 
   pango_layout_get_extents (layout, &extents, NULL);
 
-  store_animation_region (context,
-                          x + extents.x,
-                          y + extents.y,
-                          extents.width,
-                          extents.height);
-
   _gtk_theming_engine_set_context (priv->theming_engine, context);
   engine_class->render_layout (priv->theming_engine, cr, x, y, layout);
 
@@ -4056,8 +3681,6 @@ gtk_render_slider (GtkStyleContext *context,
 
   cairo_save (cr);
 
-  store_animation_region (context, x, y, width, height);
-
   _gtk_theming_engine_set_context (priv->theming_engine, context);
   engine_class->render_slider (priv->theming_engine, cr, x, y, width, height, orientation);
 
@@ -4121,8 +3744,6 @@ gtk_render_frame_gap (GtkStyleContext *context,
 
   cairo_save (cr);
 
-  store_animation_region (context, x, y, width, height);
-
   _gtk_theming_engine_set_context (priv->theming_engine, context);
   engine_class->render_frame_gap (priv->theming_engine, cr,
                                   x, y, width, height, gap_side,
@@ -4175,8 +3796,6 @@ gtk_render_extension (GtkStyleContext *context,
 
   cairo_save (cr);
 
-  store_animation_region (context, x, y, width, height);
-
   _gtk_theming_engine_set_context (priv->theming_engine, context);
   engine_class->render_extension (priv->theming_engine, cr, x, y, width, height, gap_side);
 
@@ -4225,8 +3844,6 @@ gtk_render_handle (GtkStyleContext *context,
 
   cairo_save (cr);
 
-  store_animation_region (context, x, y, width, height);
-
   _gtk_theming_engine_set_context (priv->theming_engine, context);
   engine_class->render_handle (priv->theming_engine, cr, x, y, width, height);
 
@@ -4270,8 +3887,6 @@ gtk_render_activity (GtkStyleContext *context,
 
   cairo_save (cr);
 
-  store_animation_region (context, x, y, width, height);
-
   _gtk_theming_engine_set_context (priv->theming_engine, context);
   engine_class->render_activity (priv->theming_engine, cr, x, y, width, height);
 
@@ -4341,11 +3956,6 @@ gtk_render_icon (GtkStyleContext *context,
 
   cairo_save (cr);
 
-  store_animation_region (context,
-                          x, y,
-                          gdk_pixbuf_get_width (pixbuf),
-                          gdk_pixbuf_get_height (pixbuf));
-
   _gtk_theming_engine_set_context (priv->theming_engine, context);
   engine_class->render_icon (priv->theming_engine, cr, pixbuf, x, y);
 
@@ -4529,6 +4139,7 @@ gtk_render_insertion_cursor (GtkStyleContext *context,
  * but merely a convenience function for drawing the standard cursor shape.
  *
  * Since: 3.0
+ * Deprecated: 3.4: Use gtk_render_insertion_cursor() instead.
  */
 void
 gtk_draw_insertion_cursor (GtkWidget          *widget,