=== modified file 'demos/gtk-demo/main.c'
--- demos/gtk-demo/main.c	2008-12-26 21:57:55 +0000
+++ demos/gtk-demo/main.c	2009-01-28 20:24:24 +0000
@@ -929,6 +929,8 @@
 main (int argc, char **argv)
 {
   GtkWidget *window;
+  GdkScreen *screen;
+  GdkColormap *cmap;
   GtkWidget *notebook;
   GtkWidget *hbox;
   GtkWidget *tree;
@@ -951,6 +953,12 @@
   setup_default_icon ();
   
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  screen = gtk_widget_get_screen (window);
+  cmap = gdk_screen_get_rgba_colormap (screen);
+
+  if (cmap && gdk_screen_is_composited (screen))
+    gtk_widget_set_default_colormap (cmap);
+
   gtk_window_set_title (GTK_WINDOW (window), "GTK+ Code Demos");
   g_signal_connect_after (window, "destroy",
 		    G_CALLBACK (gtk_main_quit), NULL);
@@ -1004,7 +1012,6 @@
   gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
   gtk_widget_show_all (window);
   
-
   load_file (testgtk_demos[0].filename);
   
   gtk_main ();

=== modified file 'gdk/gdk.symbols'
--- gdk/gdk.symbols	2008-12-09 15:37:59 +0000
+++ gdk/gdk.symbols	2009-01-28 20:36:01 +0000
@@ -677,12 +677,14 @@
 gdk_window_at_pointer
 gdk_window_begin_paint_rect
 gdk_window_begin_paint_region
+gdk_window_begin_paint_region_full
 gdk_window_clear
 gdk_window_clear_area
 gdk_window_clear_area_e
 gdk_window_constrain_size
 gdk_window_destroy
 gdk_window_end_paint
+gdk_window_end_paint_full
 gdk_window_foreign_new
 gdk_window_freeze_toplevel_updates_libgtk_only
 gdk_window_freeze_updates

=== modified file 'gdk/gdkwindow.c'
--- gdk/gdkwindow.c	2009-01-23 05:34:14 +0000
+++ gdk/gdkwindow.c	2009-01-28 20:36:01 +0000
@@ -212,6 +212,12 @@
 					   gint       y,
 					   gint       width,
 					   gint       height);
+static void gdk_window_clear_backing_rect_full (GdkWindow *window,
+					        gint       x,
+					        gint       y,
+					        gint       width,
+					        gint       height,
+                                                gboolean   transparent);
 static void setup_redirect_clip           (GdkWindow         *window,
 					   GdkGC             *gc,
 					   GdkWindowClipData *data);
@@ -1104,6 +1110,14 @@
 gdk_window_begin_paint_region (GdkWindow       *window,
                                const GdkRegion *region)
 {
+  gdk_window_begin_paint_region_full (window, region, FALSE);
+}
+
+void	      
+gdk_window_begin_paint_region_full (GdkWindow       *window,
+                                    const GdkRegion *region,
+                                    gboolean         subwindow)
+{
 #ifdef USE_BACKING_STORE
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkRectangle clip_box;
@@ -1150,9 +1164,10 @@
 
   if (!gdk_region_empty (region))
     {
-      gdk_window_clear_backing_rect (window,
-				     clip_box.x, clip_box.y,
-				     clip_box.width, clip_box.height);
+      gdk_window_clear_backing_rect_full (window,
+                                          clip_box.x, clip_box.y,
+                                          clip_box.width, clip_box.height,
+                                          subwindow);
     }
 #endif /* USE_BACKING_STORE */
 }
@@ -1174,19 +1189,29 @@
 gdk_window_end_paint (GdkWindow *window)
 {
 #ifdef USE_BACKING_STORE
+  gdk_window_end_paint_full (window, FALSE);
+#endif /* USE_BACKING_STORE */
+}
+
+void
+gdk_window_end_paint_full (GdkWindow *window,
+                           gboolean   only_redirect)
+{
+#ifdef USE_BACKING_STORE
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowObject *composited;
   GdkWindowPaint *paint;
   GdkGC *tmp_gc;
   GdkRectangle clip_box;
   gint x_offset, y_offset;
+  GdkGCValues values;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  if (GDK_IS_PAINTABLE (private->impl))
+  if (GDK_IS_PAINTABLE (private->impl) && !only_redirect)
     {
       GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
 
@@ -1214,11 +1239,17 @@
   gdk_gc_set_clip_region (tmp_gc, paint->region);
   gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
 
-  gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
-                     clip_box.x - paint->x_offset,
-                     clip_box.y - paint->y_offset,
-                     clip_box.x - x_offset, clip_box.y - y_offset,
-                     clip_box.width, clip_box.height);
+  if (!only_redirect)
+    {
+      cairo_t *cr;
+
+      cr = gdk_cairo_create (private->impl);
+
+      gdk_cairo_set_source_pixmap (cr, paint->pixmap, 0, 0);
+      cairo_paint (cr);
+
+      cairo_destroy (cr);
+    }
 
   if (private->redirect)
     {
@@ -1249,7 +1280,7 @@
    * to draw (ie: 'composited' will always be non-NULL here).
    */
   for (composited = private;
-       composited->parent;
+       composited->parent && !only_redirect;
        composited = composited->parent)
     {
       int width, height;
@@ -2037,6 +2068,17 @@
 			       gint       width,
 			       gint       height)
 {
+  gdk_window_clear_backing_rect_full (window, x, y, width, height, FALSE);
+}
+
+static void
+gdk_window_clear_backing_rect_full (GdkWindow *window,
+			            gint       x,
+			            gint       y,
+			            gint       width,
+			            gint       height,
+                                    gboolean   transparent)
+{
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowPaint *paint = private->paint_stack->data;
   BackingRectMethod method;
@@ -2064,7 +2106,14 @@
       cairo_clip (method.cr);
 
       gdk_cairo_region (method.cr, paint->region);
-      cairo_fill (method.cr);
+
+      if (transparent)
+        {
+          cairo_set_operator (method.cr, CAIRO_OPERATOR_CLEAR);
+          cairo_paint (method.cr);
+        }
+      else
+        cairo_fill (method.cr);
 
       cairo_destroy (method.cr);
 #if 0
@@ -2144,7 +2193,7 @@
       g_object_unref (method.gc);
 
     }
-
+  
   gdk_region_destroy (clip_region);
   cairo_surface_destroy (paint.surface);
 }

=== modified file 'gdk/gdkwindow.h'
--- gdk/gdkwindow.h	2008-11-30 05:04:29 +0000
+++ gdk/gdkwindow.h	2009-01-28 20:36:01 +0000
@@ -487,11 +487,16 @@
 					     GdkWindowHints      geom_mask);
 void          gdk_set_sm_client_id          (const gchar        *sm_client_id);
 
-void	      gdk_window_begin_paint_rect   (GdkWindow          *window,
-					     const GdkRectangle *rectangle);
-void	      gdk_window_begin_paint_region (GdkWindow          *window,
-					     const GdkRegion    *region);
-void	      gdk_window_end_paint          (GdkWindow          *window);
+void	      gdk_window_begin_paint_rect             (GdkWindow          *window,
+					               const GdkRectangle *rectangle);
+void	      gdk_window_begin_paint_region           (GdkWindow          *window,
+					               const GdkRegion    *region);
+void	      gdk_window_begin_paint_region_full      (GdkWindow          *window,
+					               const GdkRegion    *region,
+                                                       gboolean            subwindow);
+void	      gdk_window_end_paint                    (GdkWindow          *window);
+void	      gdk_window_end_paint_full               (GdkWindow          *window,
+                                                       gboolean            only_redirect);
 
 void	      gdk_window_set_title	   (GdkWindow	  *window,
 					    const gchar	  *title);

=== modified file 'gtk/Makefile.am'
--- gtk/Makefile.am	2009-01-23 15:15:28 +0000
+++ gtk/Makefile.am	2009-01-29 11:13:22 +0000
@@ -151,6 +151,8 @@
 	gtkactivatable.h	\
 	gtkadjustment.h		\
 	gtkalignment.h		\
+	gtkanimatable.h		\
+	gtkanimbox.h		\
 	gtkarrow.h		\
 	gtkaspectframe.h	\
 	gtkassistant.h		\
@@ -348,6 +350,7 @@
 	gtkdndcursors.h		\
 	gtkentryprivate.h	\
 	gtkbuilderprivate.h 	\
+	gtkanimatableprivate.h	\
 	gtkfilechooserdefault.h	\
 	gtkfilechooserembed.h	\
 	gtkfilechooserentry.h	\
@@ -401,6 +404,8 @@
 	gtkactivatable.c	\
 	gtkadjustment.c		\
 	gtkalignment.c		\
+	gtkanimatable.c		\
+	gtkanimbox.c		\
 	gtkarrow.c		\
 	gtkaspectframe.c	\
 	gtkassistant.c		\

=== modified file 'gtk/gtk.h'
--- gtk/gtk.h	2009-01-23 15:15:28 +0000
+++ gtk/gtk.h	2009-01-29 11:09:01 +0000
@@ -40,6 +40,8 @@
 #include <gtk/gtkactivatable.h>
 #include <gtk/gtkadjustment.h>
 #include <gtk/gtkalignment.h>
+#include <gtk/gtkanimatable.h>
+#include <gtk/gtkanimbox.h>
 #include <gtk/gtkarrow.h>
 #include <gtk/gtkaspectframe.h>
 #include <gtk/gtkassistant.h>

=== modified file 'gtk/gtk.symbols'
--- gtk/gtk.symbols	2009-01-27 03:56:03 +0000
+++ gtk/gtk.symbols	2009-02-03 13:47:15 +0000
@@ -273,6 +273,25 @@
 #endif
 #endif
 
+#if IN_HEADER(__GTK_ANIMATABLE_H__)
+#if IN_FILE(__GTK_ANIMATABLE_C__)
+gtk_animatable_get_type G_GNUC_CONST
+gtk_animatable_triggered
+gtk_animatable_running
+gtk_animatable_get_duration
+gtk_animatable_set_duration
+gtk_animatable_get_fps
+gtk_animatable_set_fps
+#endif
+#endif
+
+#if IN_HEADER(__GTK_ANIM_BOX_H__)
+#if IN_FILE(__GTK_ANIM_BOX_C__)
+gtk_anim_box_get_type
+gtk_anim_box_new
+gtk_anim_box_set_orientation
+#endif
+#endif
 
 #if IN_HEADER(__GTK_ASSISTANT_H__)
 #if IN_FILE(__GTK_ASSISTANT_C__)
@@ -2369,6 +2388,7 @@
 gtk_parse_args
 gtk_main
 gtk_main_do_event
+gtk_main_queue_expose_event
 gtk_main_iteration
 gtk_main_iteration_do
 gtk_main_level

=== added file 'gtk/gtkanimatable.c'
--- gtk/gtkanimatable.c	1970-01-01 00:00:00 +0000
+++ gtk/gtkanimatable.c	2009-02-04 08:33:29 +0000
@@ -0,0 +1,403 @@
+/*
+ * gtkanimatable.c
+ * Copyright (C) 2008 Imendio AB
+ * Contact: Hagen Schink <hagen@imendio.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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.
+ */
+
+#include "config.h"
+
+#include "gtkprivate.h"
+#include "gtkintl.h"
+#include "gtkanimatable.h"
+#include "gtkanimatableprivate.h"
+#include "gtkcontainer.h"
+#include "gtkalias.h"
+
+
+static gboolean gtk_animatable_callback    (GtkAnimatable *animatable);
+static void     gtk_animatable_animate     (GtkAnimatable *animatable,
+                                            gdouble        progress);
+
+
+static void     gtk_animatable_base_init   (GtkAnimatableIface *iface);
+
+GType
+gtk_animatable_get_type (void)
+{
+  static GType animatable_type = 0;
+
+  if (!animatable_type)
+    {
+      const GTypeInfo animatable_info =
+      {
+        sizeof (GtkAnimatableIface),
+        (GBaseInitFunc)     gtk_animatable_base_init,
+        (GBaseFinalizeFunc) NULL,
+      };
+
+      animatable_type = g_type_register_static (G_TYPE_INTERFACE,
+                                                I_("GtkAnimatable"),
+                                                &animatable_info, 0);
+    }
+
+  return animatable_type;
+}
+
+static void
+gtk_animatable_base_init (GtkAnimatableIface *iface)
+{
+  static gboolean initialized = FALSE;
+
+  if (initialized)
+    return;
+
+  g_object_interface_install_property (iface,
+                                       g_param_spec_uint ("duration",
+                                                          P_("Duration"),
+                                                          P_("The duration of the animation of the animatable in ms"),
+                                                          0,
+                                                          G_MAXUINT,
+							  500,
+                                                          GTK_PARAM_READWRITE));
+
+  g_object_interface_install_property (iface,
+                                       g_param_spec_uint ("fps",
+                                                          P_("FPS"),
+                                                          P_("The number of frames shown per second"),
+                                                          0,
+                                                          G_MAXUINT,
+                                                          24,
+                                                          GTK_PARAM_READWRITE));
+
+  g_object_interface_install_property (iface,
+                                       g_param_spec_double ("progress",
+                                                            P_("Progress"),
+                                                            P_("When running this shows the progress of an animation"),
+                                                            0,
+                                                            1,
+							    0,
+                                                            GTK_PARAM_READWRITE));
+
+  initialized = TRUE;
+}
+
+void
+gtk_animatable_started (GtkAnimatable *animatable)
+{
+  g_return_if_fail (GTK_IS_ANIMATABLE (animatable));
+  
+  return GTK_ANIMATABLE_GET_IFACE (animatable)->started (animatable);
+}
+
+void
+gtk_animatable_finished (GtkAnimatable *animatable)
+{
+  g_return_if_fail (GTK_IS_ANIMATABLE (animatable));
+  
+  return GTK_ANIMATABLE_GET_IFACE (animatable)->finished (animatable);
+}
+
+gboolean
+gtk_animatable_triggered (GtkAnimatable *animatable)
+{
+  g_return_val_if_fail (GTK_IS_ANIMATABLE (animatable), FALSE);
+  
+  return GTK_ANIMATABLE_GET_IFACE (animatable)->triggered (animatable);
+}
+
+gboolean
+gtk_animatable_running (GtkAnimatable *animatable)
+{
+  g_return_val_if_fail (GTK_IS_ANIMATABLE (animatable), FALSE);
+  
+  return GTK_ANIMATABLE_GET_IFACE (animatable)->running (animatable);
+}
+
+void
+gtk_animatable_set_duration (GtkAnimatable  *animatable,
+                             guint           duration)
+{
+  g_return_if_fail (GTK_IS_ANIMATABLE (animatable));
+
+  g_object_set (animatable,
+                "duration", duration,
+                NULL);
+}
+
+guint
+gtk_animatable_get_duration (GtkAnimatable *animatable)
+{
+  guint duration = 0;
+
+  g_return_val_if_fail (GTK_IS_ANIMATABLE (animatable), 0);
+
+  g_object_get (animatable,
+                "duration", &duration,
+                NULL);
+
+  return duration;
+}
+
+void
+gtk_animatable_set_fps (GtkAnimatable  *animatable,
+                        guint           fps)
+{
+  g_return_if_fail (GTK_IS_ANIMATABLE (animatable));
+
+  g_object_set (animatable,
+                "fps", fps,
+                NULL);
+}
+
+guint
+gtk_animatable_get_fps (GtkAnimatable *animatable)
+{
+  guint fps = 0;
+
+  g_return_val_if_fail (GTK_IS_ANIMATABLE (animatable), 0);
+
+  g_object_get (animatable,
+                "fps", &fps,
+                NULL);
+
+  return fps;
+}
+
+void
+_gtk_animatable_start_animation (GtkAnimatable *animatable)
+{
+  guint callback_interval = 1000;
+  guint idle_handler = 0;
+  GTimer *timer;
+
+  g_return_if_fail (GTK_ANIMATABLE (animatable));
+
+  callback_interval /= gtk_animatable_get_fps (animatable);
+
+  timer = g_timer_new ();
+
+  g_object_set_data (G_OBJECT (animatable),
+                     GTK_ANIMATABLE_TIMER,
+                     timer);
+
+  idle_handler = gdk_threads_add_timeout_full (G_PRIORITY_HIGH,
+                                               callback_interval,
+                                               (GSourceFunc)gtk_animatable_callback,
+                                               animatable,
+                                               _gtk_animatable_cleanup_animation);
+
+  g_object_set_data (G_OBJECT (animatable),
+                     GTK_ANIMATABLE_IDLE,
+                     GINT_TO_POINTER (idle_handler));
+
+  gtk_animatable_started (animatable);
+}
+
+void
+_gtk_animatable_cleanup_animation (gpointer data)
+{
+  GtkAnimatable *animatable = GTK_ANIMATABLE (data);
+  guint idle_handler;
+  GTimer *timer;
+
+  idle_handler = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (animatable),
+                                                     GTK_ANIMATABLE_IDLE));
+
+  if (idle_handler)
+    {
+      g_object_set_data (G_OBJECT (animatable),
+                         GTK_ANIMATABLE_IDLE,
+                         GINT_TO_POINTER (0));
+
+      timer = g_object_get_data (G_OBJECT (animatable),
+                                 GTK_ANIMATABLE_TIMER);
+
+      g_timer_destroy (timer);
+
+      gtk_animatable_finished (animatable);
+    }
+}
+
+static gboolean
+gtk_animatable_callback (GtkAnimatable *animatable)
+{
+  gdouble progress;
+  GTimer *timer;
+
+  progress = gtk_animatable_get_duration (animatable);
+
+  timer = (GTimer*) g_object_get_data (G_OBJECT (animatable),
+                                       GTK_ANIMATABLE_TIMER);
+
+  progress = g_timer_elapsed (timer, NULL) * 1000 / progress;
+
+  progress = (progress >= 1) ? 1 : progress;
+
+  g_object_set (G_OBJECT (animatable),
+                "progress", progress,
+                NULL);
+
+  gtk_animatable_animate (animatable, progress);
+
+  return progress < 1;
+}
+
+static void
+gtk_animatable_animate (GtkAnimatable *animatable,
+                        gdouble        progress)
+{
+  GtkWidget *widget;
+  GdkWindowObject *private;
+  GtkWidget *child_widget;
+  GdkPixmap *pixmap, *buffer;
+  GQueue *queue;
+  GList *child;
+  GtkAllocation *new_alloc, *old_alloc;
+  gint width, height;
+  gdouble pos_x, pos_y, w, h;
+  cairo_t *cr;
+
+  widget = GTK_WIDGET (animatable);
+
+  private = (GdkWindowObject *)gtk_widget_get_window (widget);
+
+  g_assert (GTK_IS_WIDGET (widget) && GTK_IS_ANIMATABLE (widget));
+
+  queue = NULL;
+  child = NULL;
+
+  /* create a buffer */
+  gdk_drawable_get_size (gtk_widget_get_window (widget),
+                         &width, &height);
+  buffer = gdk_pixmap_new (gtk_widget_get_window (widget),
+                           width, height, -1);
+
+  cr = gdk_cairo_create (buffer);
+  gdk_cairo_set_source_color (cr, &private->bg_color);
+  cairo_paint (cr);
+  cairo_destroy (cr);
+
+  /* draw parent */
+  pixmap = g_object_get_data (G_OBJECT (widget),
+                              GTK_ANIMATABLE_STATE_NEW);
+
+  if (!pixmap)
+    pixmap = g_object_get_data (G_OBJECT (widget),
+                                GTK_ANIMATABLE_STATE_OLD);
+
+  if (pixmap)
+    {
+      cr = gdk_cairo_create (gtk_widget_get_window (widget));
+      gdk_cairo_set_source_pixmap (cr, pixmap, 0, 0);
+
+      cairo_paint (cr);
+      cairo_destroy (cr);
+    }
+
+  if (GTK_IS_CONTAINER (widget))
+    {
+      GList *children;
+
+      queue = g_queue_new ();
+
+      children = gtk_container_get_children (GTK_CONTAINER (widget));
+
+      while (children)
+        {
+          g_queue_push_tail (queue, children->data);
+
+          children = children->next;
+        }
+    }
+
+  if (queue)
+    child = g_queue_pop_head_link (queue);
+
+  while (child)
+    {
+      child_widget = GTK_WIDGET (child->data);
+
+      pixmap = g_object_get_data (G_OBJECT (child_widget),
+                                  GTK_ANIMATABLE_STATE_NEW);
+
+      if (!pixmap)
+        pixmap = g_object_get_data (G_OBJECT (child_widget),
+                                    GTK_ANIMATABLE_STATE_OLD);
+
+      new_alloc = &(child_widget->allocation);
+      old_alloc = g_object_get_data (G_OBJECT (child_widget),
+                                     GTK_ANIMATABLE_OLD_ALLOCATION);
+
+      if (pixmap)
+        {
+          pos_x = old_alloc->x + (new_alloc->x - old_alloc->x) 
+                   * progress;
+          pos_y = old_alloc->y + (new_alloc->y - old_alloc->y) 
+                   * progress;
+          width = (old_alloc->width + (new_alloc->width - old_alloc->width) 
+                   * progress);
+          height = (old_alloc->height + (new_alloc->height - old_alloc->height) 
+                    * progress);
+
+          w = (gdouble)width / new_alloc->width;
+          h = (gdouble)height / new_alloc->height;
+
+          cr = gdk_cairo_create (buffer);
+          cairo_scale (cr, w, h);
+          gdk_cairo_set_source_pixmap (cr, pixmap, pos_x / w, pos_y / h);
+
+          cairo_paint (cr);
+          cairo_destroy (cr);
+        }
+
+      g_list_free (child);
+      
+      if (GTK_IS_CONTAINER (child_widget))
+        {
+          GList *children;
+
+          children = gtk_container_get_children (GTK_CONTAINER (child_widget));
+
+          while (children)
+            {
+              g_queue_push_head (queue, children->data);
+
+              children = children->next;
+            }
+        }
+
+      child = g_queue_pop_head_link (queue);
+    }
+
+  cr = gdk_cairo_create (gtk_widget_get_window (child_widget));
+  gdk_cairo_set_source_pixmap (cr, buffer, 
+                               widget->allocation.x, 
+                               widget->allocation.y);
+  cairo_rectangle (cr,
+                   widget->allocation.x, 
+                   widget->allocation.y, 
+                   widget->allocation.width, 
+                   widget->allocation.height);
+  cairo_clip (cr);
+
+  cairo_paint (cr);
+  cairo_destroy (cr);
+}
+
+#define __GTK_ANIMATABLE_C__
+#include "gtkaliasdef.c"

=== added file 'gtk/gtkanimatable.h'
--- gtk/gtkanimatable.h	1970-01-01 00:00:00 +0000
+++ gtk/gtkanimatable.h	2009-02-03 14:45:55 +0000
@@ -0,0 +1,76 @@
+/*
+ * gtkanimatable.h
+ * Copyright (C) 2008 Imendio AB
+ * Contact: Hagen Schink <hagen@imendio.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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.
+ */
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#ifndef __GTK_ANIMATABLE_H__
+#define __GTK_ANIMATABLE_H__
+
+#include "gtkwidget.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_ANIMATABLE             (gtk_animatable_get_type ())
+#define GTK_ANIMATABLE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ANIMATABLE, GtkAnimatable))
+#define GTK_ANIMATABLE_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), GTK_TYPE_ANIMATABLE, GtkAnimatableIface))
+#define GTK_IS_ANIMATABLE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ANIMATABLE))
+#define GTK_IS_ANIMATABLE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), GTK_TYPE_ANIMATABLE))
+#define GTK_ANIMATABLE_GET_IFACE(inst)  (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GTK_TYPE_ANIMATABLE, GtkAnimatableIface))
+
+#define GTK_ANIMATABLE_STATE_OLD "gtk_animatable_state_old"
+#define GTK_ANIMATABLE_STATE_NEW "gtk_animatable_state_new"
+
+typedef struct _GtkAnimatable       GtkAnimatable;         /* Dummy typedef */
+typedef struct _GtkAnimatableIface  GtkAnimatableIface;
+
+typedef struct _GtkAnimatablePropertyChange GtkAnimatablePropertyChange;
+
+struct _GtkAnimatableIface
+{
+  GTypeInterface base_iface;
+
+  gboolean (*triggered) (GtkAnimatable *animatable);
+  gboolean (*running)   (GtkAnimatable *animatable);
+  void     (*started)   (GtkAnimatable *animatable);
+  void     (*finished)  (GtkAnimatable *animatable);
+};
+
+GType         gtk_animatable_get_type          (void) G_GNUC_CONST;
+
+gboolean      gtk_animatable_triggered         (GtkAnimatable *animatable);
+gboolean      gtk_animatable_running           (GtkAnimatable *animatable);
+void          gtk_animatable_started           (GtkAnimatable *animatable);
+void          gtk_animatable_finished          (GtkAnimatable *animatable);
+
+guint         gtk_animatable_get_duration      (GtkAnimatable *animatable);
+void          gtk_animatable_set_duration      (GtkAnimatable *animatable,
+		                                guint          duration);
+guint         gtk_animatable_get_fps           (GtkAnimatable *animatable);
+void          gtk_animatable_set_fps           (GtkAnimatable *animatable,
+		                                guint          fps);
+                                                  
+
+
+G_END_DECLS
+
+#endif /* __GTK_ANIMATABLE_H__ */

=== added file 'gtk/gtkanimatableprivate.h'
--- gtk/gtkanimatableprivate.h	1970-01-01 00:00:00 +0000
+++ gtk/gtkanimatableprivate.h	2009-02-03 13:11:44 +0000
@@ -0,0 +1,43 @@
+/*
+ * gtkanimatableprivate.h
+ * Copyright (C) 2008 Imendio AB
+ * Contact: Hagen Schink <hagen@imendio.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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.
+ */
+
+#ifndef __GTK_ANIMATABLE_PRIVATE_H__
+#define __GTK_ANIMATABLE_PRIVATE_H__
+
+#include "gtkanimatable.h"
+
+G_BEGIN_DECLS
+
+#define GTK_ANIMATABLE_OLD_ALLOCATION "gtk_animatable_old_allocation"
+#define GTK_ANIMATABLE_IDLE           "gtk_animatable_idle_handler"
+#define GTK_ANIMATABLE_TIMER          "gtk_animatable_timer"
+
+void          _gtk_animatable_start_animation     (GtkAnimatable *animatable);
+void          _gtk_animatable_cleanup_animation   (gpointer      data);
+
+/*
+void          _gtk_animation_callback             (GtkAnimatable *animatable,
+                                                   gdouble        progress);
+*/
+
+G_END_DECLS
+
+#endif /* __GTK_ANIMATABLE_PRIVATE_H__ */

=== added file 'gtk/gtkanimbox.c'
--- gtk/gtkanimbox.c	1970-01-01 00:00:00 +0000
+++ gtk/gtkanimbox.c	2009-02-04 08:38:17 +0000
@@ -0,0 +1,767 @@
+#include "config.h"
+
+#include "gtkanimbox.h"
+#include "gtkanimatable.h"
+#include "gtkanimatableprivate.h"
+#include "gtkorientable.h"
+#include "gtkprivate.h"
+#include "gtkintl.h"
+#include "gtkalias.h"
+
+enum {
+  PROP_0,
+  PROP_DURATION,
+  PROP_FPS,
+  PROP_PROGRESS
+};
+
+typedef enum _GtkAnimBoxAnimation GtkAnimBoxAnimation;
+
+enum _GtkAnimBoxAnimation {
+  NONE,
+  ADD,
+  REMOVE,
+  ORIENTATION
+};
+
+typedef struct _GtkAnimBoxPrivate GtkAnimBoxPrivate;
+
+struct _GtkAnimBoxPrivate
+{
+  guint duration;
+  guint fps;
+
+  GtkAnimBoxAnimation anim;
+  gboolean running;
+  gdouble progress;
+
+  GtkWidget *animation_child;
+};
+
+/* GtkAnimBox methods */
+static void gtk_anim_box_remove_child       (GtkAnimBox     *box,
+                                             GtkWidget      *widget);
+
+/* GObject methods */
+static void gtk_anim_box_set_property       (GObject        *object,
+                                             guint           prop_id,
+                                             const GValue   *value,
+                                             GParamSpec     *pspec);
+static void gtk_anim_box_get_property       (GObject        *object,
+                                             guint           prop_id,
+                                             GValue         *value,
+                                             GParamSpec     *pspec);
+
+/* GtkContainer methods */
+static void gtk_anim_box_add                (GtkContainer   *container,
+	                                     GtkWidget      *widget);
+static void gtk_anim_box_remove             (GtkContainer   *container,
+	                                     GtkWidget      *widget);
+
+
+/* GtkWidget methods */
+static void gtk_anim_box_size_request       (GtkWidget      *widget,
+                                             GtkRequisition *requisition);
+static void gtk_anim_box_size_allocate      (GtkWidget      *widget,
+                                             GtkAllocation  *allocation);
+
+
+/* GtkAnimatable Iface methods */
+static void     gtk_anim_box_animatable_interface_init (GtkAnimatableIface *iface);
+
+static void     gtk_anim_box_started                   (GtkAnimatable      *animatable);
+static void     gtk_anim_box_finished                  (GtkAnimatable      *animatable);
+static gboolean gtk_anim_box_animation_triggered       (GtkAnimatable      *animatable);
+static gboolean gtk_anim_box_animation_running         (GtkAnimatable      *animatable);
+
+/* GtkAnimBox Private methods */
+static void _gtk_anim_box_remove_real                  (GtkContainer       *container,
+                                                        GtkWidget          *widget);
+
+
+#define GTK_ANIM_BOX_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ANIM_BOX, GtkAnimBoxPrivate))
+
+G_DEFINE_TYPE_WITH_CODE (GtkAnimBox, gtk_anim_box, GTK_TYPE_BOX,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ANIMATABLE,
+                                                gtk_anim_box_animatable_interface_init));
+
+/*
+G_DEFINE_TYPE (GtkAnimBox, gtk_anim_box, GTK_TYPE_BOX);
+*/
+
+static void
+gtk_anim_box_animatable_interface_init (GtkAnimatableIface *iface)
+{
+  iface->started = gtk_anim_box_started;
+  iface->finished = gtk_anim_box_finished;
+  iface->triggered = gtk_anim_box_animation_triggered;
+  iface->running = gtk_anim_box_animation_running;
+}
+
+static void
+gtk_anim_box_class_init (GtkAnimBoxClass *class)
+{  
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+
+  object_class->set_property = gtk_anim_box_set_property;
+  object_class->get_property = gtk_anim_box_get_property;
+  
+  container_class->add = gtk_anim_box_add;
+  container_class->remove = gtk_anim_box_remove;
+
+  widget_class->size_request = gtk_anim_box_size_request;
+  widget_class->size_allocate = gtk_anim_box_size_allocate;
+
+  g_object_class_override_property (object_class,
+                                    PROP_DURATION,
+                                    "duration");
+
+  g_object_class_override_property (object_class,
+                                    PROP_FPS,
+                                    "fps");
+
+  g_object_class_override_property (object_class,
+                                    PROP_PROGRESS,
+                                    "progress");
+
+  g_type_class_add_private (object_class, sizeof (GtkAnimBoxPrivate));
+}
+
+static void
+gtk_anim_box_init (GtkAnimBox *box)
+{
+  GtkAnimBoxPrivate *priv = GTK_ANIM_BOX_GET_PRIVATE (box);
+
+  priv->duration = 1500;
+  priv->fps = 24;
+
+  priv->anim = NONE;
+  priv->running = FALSE;
+  priv->progress = 0;
+}
+
+static void
+gtk_anim_box_set_property (GObject      *object,
+                           guint         prop_id,
+                           const GValue *value,
+                           GParamSpec   *pspec)
+{
+  GtkAnimBox *box = GTK_ANIM_BOX (object);
+  GtkAnimBoxPrivate *priv = GTK_ANIM_BOX_GET_PRIVATE (box);
+
+  switch (prop_id)
+    {
+    case PROP_DURATION:
+      priv->duration = g_value_get_uint (value);
+      break;
+    case PROP_FPS:
+      priv->fps = g_value_get_uint (value);
+      break;
+    case PROP_PROGRESS:
+      priv->progress = g_value_get_double (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_anim_box_get_property (GObject    *object,
+                           guint       prop_id,
+                           GValue     *value,
+                           GParamSpec *pspec)
+{
+  GtkAnimBox *box = GTK_ANIM_BOX (object);
+  GtkAnimBoxPrivate *priv = GTK_ANIM_BOX_GET_PRIVATE (box);
+
+  switch (prop_id)
+    {
+    case PROP_DURATION:
+      g_value_set_uint (value, priv->duration);
+      break;
+    case PROP_FPS:
+      g_value_set_uint (value, priv->fps);
+      break;
+    case PROP_PROGRESS:
+      g_value_set_double (value, priv->progress);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+GtkWidget*
+gtk_anim_box_new (GtkOrientation orientation,
+                  gint           spacing,
+                  gboolean       homogeneous)
+{
+  GtkWidget *box;
+
+  box = g_object_new (GTK_TYPE_ANIM_BOX,
+                      "orientation", orientation,
+                      "spacing",     spacing,
+                      "homogeneous", homogeneous ? TRUE : FALSE,
+                      NULL);
+ 
+  /*
+  g_signal_connect_after (G_OBJECT (box), "add",
+                          G_CALLBACK (gtk_anim_box_trigger_animation),
+                          GINT_TO_POINTER (ADD));
+  */
+
+  return box;
+}
+
+void
+gtk_anim_box_set_orientation (GtkAnimBox     *box,
+                              GtkOrientation orientation)
+{
+  GtkAnimBoxPrivate *priv = GTK_ANIM_BOX_GET_PRIVATE (box);
+
+  g_return_if_fail (GTK_IS_ORIENTABLE (box));
+
+  g_object_set (box,
+                "orientation", orientation,
+                NULL);
+
+  priv->anim = ORIENTATION;
+}
+
+static void
+gtk_anim_box_add (GtkContainer *container,
+	          GtkWidget    *widget)
+{
+  GtkAnimBoxPrivate *priv;
+
+  priv = GTK_ANIM_BOX_GET_PRIVATE (GTK_ANIM_BOX (container));
+
+  gtk_box_pack_start (GTK_BOX (container), widget,
+                      TRUE, TRUE, 0);
+
+  if (GTK_WIDGET_VISIBLE (container))
+    {
+      priv->animation_child = widget;
+
+      priv->anim = ADD;
+    }
+}
+
+static void
+gtk_anim_box_remove (GtkContainer *container,
+	             GtkWidget    *widget)
+{
+  GtkAnimBoxPrivate *priv;
+
+  priv = GTK_ANIM_BOX_GET_PRIVATE (GTK_ANIM_BOX (container));
+
+  if (GTK_WIDGET_VISIBLE (container))
+    {
+      priv->animation_child = widget;
+
+      priv->anim = REMOVE;
+    }
+  else
+    _gtk_anim_box_remove_real (container, widget);
+}
+
+static void
+gtk_anim_box_size_request (GtkWidget      *widget,
+                           GtkRequisition *requisition)
+{
+  GtkBox *box = GTK_BOX (widget);
+  GtkAnimBoxPrivate *priv = GTK_ANIM_BOX_GET_PRIVATE (GTK_ANIM_BOX (widget));
+  GtkBoxChild *child;
+  GList *children;
+  gint nvis_children;
+  gint width;
+  gint height;
+  GtkOrientation orientation;
+
+  orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget));
+
+  requisition->width = 0;
+  requisition->height = 0;
+  nvis_children = 0;
+
+  children = box->children;
+  while (children)
+    {
+      child = children->data;
+      children = children->next;
+
+      if (GTK_WIDGET_VISIBLE (child->widget)
+          && (priv->anim != REMOVE || child->widget != priv->animation_child))
+	{
+	  GtkRequisition child_requisition;
+
+	  gtk_widget_size_request (child->widget, &child_requisition);
+
+	  if (box->homogeneous)
+	    {
+	      width = child_requisition.width + child->padding * 2;
+	      height = child_requisition.height + child->padding * 2;
+
+              if (orientation == GTK_ORIENTATION_HORIZONTAL)
+                requisition->width = MAX (requisition->width, width);
+              else
+                requisition->height = MAX (requisition->height, height);
+	    }
+	  else
+	    {
+              if (orientation == GTK_ORIENTATION_HORIZONTAL)
+                requisition->width += child_requisition.width + child->padding * 2;
+              else
+                requisition->height += child_requisition.height + child->padding * 2;
+	    }
+
+          if (orientation == GTK_ORIENTATION_HORIZONTAL)
+            requisition->height = MAX (requisition->height, child_requisition.height);
+          else
+            requisition->width = MAX (requisition->width, child_requisition.width);
+
+	  nvis_children += 1;
+	}
+    }
+
+  if (nvis_children > 0)
+    {
+      if (box->homogeneous)
+        {
+          if (orientation == GTK_ORIENTATION_HORIZONTAL)
+            requisition->width *= nvis_children;
+          else
+            requisition->height *= nvis_children;
+        }
+
+      if (orientation == GTK_ORIENTATION_HORIZONTAL)
+        requisition->width += (nvis_children - 1) * box->spacing;
+      else
+        requisition->height += (nvis_children - 1) * box->spacing;
+    }
+
+  requisition->width += GTK_CONTAINER (box)->border_width * 2;
+  requisition->height += GTK_CONTAINER (box)->border_width * 2;
+}
+
+
+static void
+gtk_anim_box_size_allocate (GtkWidget     *widget,
+                            GtkAllocation *allocation)
+{
+  GtkBox *box = GTK_BOX (widget);
+  GtkAnimBoxPrivate *priv = GTK_ANIM_BOX_GET_PRIVATE (GTK_ANIM_BOX (widget));
+  GtkOrientation orientation;
+  GtkBoxChild *child;
+  GList *children;
+  GtkAllocation child_allocation;
+  gint nvis_children = 0;
+  gint nexpand_children = 0;
+  gint child_width = 0;
+  gint child_height = 0;
+  gint width = 0;
+  gint height = 0;
+  gint extra = 0;
+  gint x = 0;
+  gint y = 0;
+  GtkTextDirection direction;
+
+  widget->allocation = *allocation;
+
+  direction = gtk_widget_get_direction (widget);
+
+  orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget));
+
+  for (children = box->children; children; children = children->next)
+    {
+      child = children->data;
+
+      if (GTK_WIDGET_VISIBLE (child->widget)
+          && (priv->anim != REMOVE || child->widget != priv->animation_child))
+	{
+	  nvis_children += 1;
+	  if (child->expand)
+	    nexpand_children += 1;
+	}
+    }
+
+  if (nvis_children > 0)
+    {
+      if (box->homogeneous)
+	{
+          if (orientation == GTK_ORIENTATION_HORIZONTAL)
+            {
+              width = (allocation->width -
+                       GTK_CONTAINER (box)->border_width * 2 -
+                       (nvis_children - 1) * box->spacing);
+              extra = width / nvis_children;
+            }
+          else
+            {
+              height = (allocation->height -
+                        GTK_CONTAINER (box)->border_width * 2 -
+                        (nvis_children - 1) * box->spacing);
+              extra = height / nvis_children;
+            }
+	}
+      else if (nexpand_children > 0)
+	{
+          if (orientation == GTK_ORIENTATION_HORIZONTAL)
+            {
+              width = (gint) allocation->width - (gint) widget->requisition.width;
+              extra = width / nexpand_children;
+            }
+          else
+            {
+              height = (gint) allocation->height - (gint) widget->requisition.height;
+              extra = height / nexpand_children;
+            }
+	}
+
+      if (orientation == GTK_ORIENTATION_HORIZONTAL)
+        {
+          x = allocation->x + GTK_CONTAINER (box)->border_width;
+          child_allocation.y = allocation->y + GTK_CONTAINER (box)->border_width;
+          child_allocation.height = MAX (1, (gint) allocation->height - (gint) GTK_CONTAINER (box)->border_width * 2);
+        }
+      else
+        {
+          y = allocation->y + GTK_CONTAINER (box)->border_width;
+          child_allocation.x = allocation->x + GTK_CONTAINER (box)->border_width;
+          child_allocation.width = MAX (1, (gint) allocation->width - (gint) GTK_CONTAINER (box)->border_width * 2);
+        }
+
+      children = box->children;
+      while (children)
+	{
+	  child = children->data;
+	  children = children->next;
+
+	  if ((child->pack == GTK_PACK_START) && GTK_WIDGET_VISIBLE (child->widget))
+	    {
+	      if (box->homogeneous)
+		{
+		  if (nvis_children == 1)
+                    {
+                      child_width = width;
+                      child_height = height;
+                    }
+		  else
+                    {
+                      child_width = extra;
+                      child_height = extra;
+                    }
+
+		  nvis_children -= 1;
+		  width -= extra;
+                  height -= extra;
+		}
+	      else
+		{
+		  GtkRequisition child_requisition;
+
+		  gtk_widget_get_child_requisition (child->widget, &child_requisition);
+
+		  child_width = child_requisition.width + child->padding * 2;
+		  child_height = child_requisition.height + child->padding * 2;
+
+		  if (child->expand)
+		    {
+		      if (nexpand_children == 1)
+                        {
+                          child_width += width;
+                          child_height += height;
+                        }
+		      else
+                        {
+                          child_width += extra;
+                          child_height += extra;
+                        }
+
+		      nexpand_children -= 1;
+		      width -= extra;
+                      height -= extra;
+		    }
+		}
+
+	      if (child->fill)
+		{
+                  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+                    {
+                      child_allocation.width = MAX (1, (gint) child_width - (gint) child->padding * 2);
+                      child_allocation.x = x + child->padding;
+                    }
+                  else
+                    {
+                      child_allocation.height = MAX (1, child_height - (gint)child->padding * 2);
+                      child_allocation.y = y + child->padding;
+                    }
+		}
+	      else
+		{
+		  GtkRequisition child_requisition;
+
+		  gtk_widget_get_child_requisition (child->widget, &child_requisition);
+                  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+                    {
+                      child_allocation.width = child_requisition.width;
+                      child_allocation.x = x + (child_width - child_allocation.width) / 2;
+                    }
+                  else
+                    {
+                      child_allocation.height = child_requisition.height;
+                      child_allocation.y = y + (child_height - child_allocation.height) / 2;
+                    }
+		}
+
+	      if (direction == GTK_TEXT_DIR_RTL &&
+                  orientation == GTK_ORIENTATION_HORIZONTAL)
+                {
+                  child_allocation.x = allocation->x + allocation->width - (child_allocation.x - allocation->x) - child_allocation.width;
+                }
+
+              if (priv->animation_child == child->widget)
+                {
+                  GtkAllocation new_allocation;
+
+                  switch (priv->anim)
+                    {
+                      case REMOVE:
+                        new_allocation.x = child_allocation.x;
+                        new_allocation.y = child_allocation.y;
+                        new_allocation.width = child_allocation.width;
+                        new_allocation.height = child_allocation.height;
+
+                        if ((!children || orientation != GTK_ORIENTATION_HORIZONTAL)
+                            && (children || orientation == GTK_ORIENTATION_HORIZONTAL))
+                          new_allocation.x += child_allocation.width;
+                        else
+                          new_allocation.y += child_allocation.height;
+
+                        gtk_widget_size_allocate (child->widget, &new_allocation);
+                        break;
+
+                      case ADD:
+                        priv->animation_child->allocation.x = child_allocation.x;
+                        priv->animation_child->allocation.y = child_allocation.y;
+                        priv->animation_child->allocation.width = child_allocation.width;
+                        priv->animation_child->allocation.height = child_allocation.height;
+
+                        if (orientation == GTK_ORIENTATION_HORIZONTAL)
+                          priv->animation_child->allocation.x += child_allocation.width;
+                        else
+                          priv->animation_child->allocation.y += child_allocation.height;
+
+                        gtk_widget_size_allocate (child->widget, &(priv->animation_child->allocation));
+                        break;
+                      default: break;
+                    }
+                }
+
+              if (priv->anim != REMOVE || child->widget != priv->animation_child)
+                gtk_widget_size_allocate (child->widget, &child_allocation);
+
+	      x += child_width + box->spacing;
+	      y += child_height + box->spacing;
+	    }
+	}
+
+      x = allocation->x + allocation->width - GTK_CONTAINER (box)->border_width;
+      y = allocation->y + allocation->height - GTK_CONTAINER (box)->border_width;
+
+      children = box->children;
+      while (children)
+	{
+	  child = children->data;
+	  children = children->next;
+
+	  if ((child->pack == GTK_PACK_END) && GTK_WIDGET_VISIBLE (child->widget))
+	    {
+	      GtkRequisition child_requisition;
+
+	      gtk_widget_get_child_requisition (child->widget, &child_requisition);
+
+              if (box->homogeneous)
+                {
+                  if (nvis_children == 1)
+                    {
+                      child_width = width;
+                      child_height = height;
+                    }
+                  else
+                    {
+                      child_width = extra;
+                      child_height = extra;
+                   }
+
+                  nvis_children -= 1;
+                  width -= extra;
+                  height -= extra;
+                }
+              else
+                {
+		  child_width = child_requisition.width + child->padding * 2;
+		  child_height = child_requisition.height + child->padding * 2;
+
+                  if (child->expand)
+                    {
+                      if (nexpand_children == 1)
+                        {
+                          child_width += width;
+                          child_height += height;
+                         }
+                      else
+                        {
+                          child_width += extra;
+                          child_height += extra;
+                        }
+
+                      nexpand_children -= 1;
+                      width -= extra;
+                      height -= extra;
+                    }
+                }
+
+              if (child->fill)
+                {
+                  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+                    {
+                      child_allocation.width = MAX (1, (gint)child_width - (gint)child->padding * 2);
+                      child_allocation.x = x + child->padding - child_width;
+                    }
+                  else
+                    {
+                      child_allocation.height = MAX (1, child_height - (gint)child->padding * 2);
+                      child_allocation.y = y + child->padding - child_height;
+                     }
+                }
+              else
+                {
+                  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+                    {
+                      child_allocation.width = child_requisition.width;
+                      child_allocation.x = x + (child_width - child_allocation.width) / 2 - child_width;
+                    }
+                  else
+                    {
+                      child_allocation.height = child_requisition.height;
+                      child_allocation.y = y + (child_height - child_allocation.height) / 2 - child_height;
+                    }
+                }
+
+	      if (direction == GTK_TEXT_DIR_RTL &&
+                  orientation == GTK_ORIENTATION_HORIZONTAL)
+                {
+                  child_allocation.x = allocation->x + allocation->width - (child_allocation.x - allocation->x) - child_allocation.width;
+                }
+
+              if (priv->animation_child == child->widget)
+                {
+                  priv->animation_child->allocation.x = widget->allocation.x;
+                  priv->animation_child->allocation.y = widget->allocation.y;
+                  priv->animation_child->allocation.width = child_allocation.width;
+                  priv->animation_child->allocation.height = child_allocation.height;
+
+                  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+                    priv->animation_child->allocation.x += widget->allocation.width;
+                  else
+                    priv->animation_child->allocation.y += widget->allocation.height;
+
+                  gtk_widget_size_allocate (child->widget, &(priv->animation_child->allocation));
+                }
+
+              gtk_widget_size_allocate (child->widget, &child_allocation);
+
+              x -= (child_width + box->spacing);
+              y -= (child_height + box->spacing);
+	    }
+	}
+    }
+}
+
+static void
+_gtk_anim_box_remove_real (GtkContainer *container,
+                           GtkWidget    *widget)
+{
+  GtkBox *box = GTK_BOX (container);
+  GtkBoxChild *child;
+  GList *children;
+
+  children = box->children;
+  while (children)
+    {
+      child = children->data;
+
+      if (child->widget == widget)
+	{
+	  gboolean was_visible;
+
+	  was_visible = GTK_WIDGET_VISIBLE (widget);
+	  gtk_widget_unparent (widget);
+
+	  box->children = g_list_remove_link (box->children, children);
+	  g_list_free (children);
+	  g_free (child);
+
+	  /* queue resize regardless of GTK_WIDGET_VISIBLE (container),
+	   * since that's what is needed by toplevels.
+	   */
+	  if (was_visible)
+	    gtk_widget_queue_resize (GTK_WIDGET (container));
+
+	  break;
+	}
+
+      children = children->next;
+    }
+}
+
+/* GtkAnimatable Iface methods */
+static void
+gtk_anim_box_started (GtkAnimatable *animatable)
+{
+  GtkWidget *widget = GTK_WIDGET (animatable);
+  GtkAnimBoxPrivate *priv = GTK_ANIM_BOX_GET_PRIVATE (GTK_ANIM_BOX (widget));
+
+  priv->running = TRUE;
+}
+
+static void
+gtk_anim_box_finished (GtkAnimatable *animatable)
+{
+  GtkWidget *widget = GTK_WIDGET (animatable);
+  GtkAnimBoxPrivate *priv = GTK_ANIM_BOX_GET_PRIVATE (GTK_ANIM_BOX (widget));
+
+  if (priv->anim == REMOVE)
+    _gtk_anim_box_remove_real (GTK_CONTAINER (widget),
+                               priv->animation_child);
+
+  priv->progress = 0;
+  priv->running = FALSE;
+  priv->anim = NONE;
+  priv->animation_child = NULL;
+}
+
+static gboolean
+gtk_anim_box_animation_triggered (GtkAnimatable *animatable)
+{
+  GtkAnimBox *box = GTK_ANIM_BOX (animatable);
+  GtkAnimBoxPrivate *priv = GTK_ANIM_BOX_GET_PRIVATE (box);
+
+  return priv->anim != NONE;
+}
+
+static gboolean
+gtk_anim_box_animation_running (GtkAnimatable *animatable)
+{
+  GtkAnimBox *box = GTK_ANIM_BOX (animatable);
+  GtkAnimBoxPrivate *priv = GTK_ANIM_BOX_GET_PRIVATE (box);
+
+  return priv->running;
+}
+
+#define __GTK_ANIM_BOX_C__
+#include "gtkaliasdef.c"

=== added file 'gtk/gtkanimbox.h'
--- gtk/gtkanimbox.h	1970-01-01 00:00:00 +0000
+++ gtk/gtkanimbox.h	2009-01-30 08:37:51 +0000
@@ -0,0 +1,48 @@
+
+#if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#ifndef __GTK_ANIM_BOX_H__
+#define __GTK_ANIM_BOX_H__
+
+
+#include <gtk/gtkbox.h>
+
+
+G_BEGIN_DECLS
+
+
+#define GTK_TYPE_ANIM_BOX            (gtk_anim_box_get_type ())
+#define GTK_ANIM_BOX(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ANIM_BOX, GtkAnimBox))
+#define GTK_ANIM_BOX_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_ANIM_BOX, GtkAnimBoxClass))
+#define GTK_IS_ANIM_BOX(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ANIM_BOX))
+#define GTK_IS_ANIM_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_ANIM_BOX))
+#define GTK_ANIM_BOX_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ANIM_BOX, GtkAnimBoxClass))
+
+
+typedef struct _GtkAnimBox	GtkAnimBox;
+typedef struct _GtkAnimBoxClass GtkAnimBoxClass;
+
+struct _GtkAnimBox
+{
+  GtkBox box;
+};
+
+struct _GtkAnimBoxClass
+{
+  GtkBoxClass parent_class;
+};
+
+
+GType       gtk_anim_box_get_type            (void) G_GNUC_CONST;
+GtkWidget*  gtk_anim_box_new                 (GtkOrientation orientation,
+                                              gint           spacing,
+                                              gboolean       homogeneous);
+void        gtk_anim_box_set_orientation     (GtkAnimBox     *box,
+                                              GtkOrientation orientation);
+
+
+G_END_DECLS
+
+#endif /* __GTK_ANIM_BOX_H__ */

=== modified file 'gtk/gtkcontainer.c'
--- gtk/gtkcontainer.c	2008-12-09 15:13:55 +0000
+++ gtk/gtkcontainer.c	2009-01-28 20:54:14 +0000
@@ -2728,7 +2728,9 @@
       if (!gdk_region_empty (child_event->expose.region))
 	{
 	  gdk_region_get_clipbox (child_event->expose.region, &child_event->expose.area);
-	  gtk_widget_send_expose (child, child_event);
+
+          if (!gtk_main_queue_expose_event (child, child_event))
+	    gtk_widget_send_expose (child, child_event);
 	}
       gdk_event_free (child_event);
     }

=== modified file 'gtk/gtkmain.c'
--- gtk/gtkmain.c	2009-01-13 14:04:27 +0000
+++ gtk/gtkmain.c	2009-02-04 09:02:55 +0000
@@ -48,6 +48,8 @@
 #include "gtkintl.h"
 
 #include "gtkaccelmap.h"
+#include "gtkanimatable.h"
+#include "gtkanimatableprivate.h"
 #include "gtkbox.h"
 #include "gtkclipboard.h"
 #include "gtkdnd.h"
@@ -1434,6 +1436,138 @@
     return NULL;
 }
 
+typedef struct _GtkQueuedExposeEvent GtkQueuedExposeEvent;
+
+struct _GtkQueuedExposeEvent
+{
+  GtkWidget *widget;
+  GdkEvent *event;
+};
+
+static GQueue expose_events = G_QUEUE_INIT;
+
+gboolean
+gtk_main_queue_expose_event (GtkWidget *widget,
+                             GdkEvent  *event)
+{
+  GtkQueuedExposeEvent *queued_event;
+  GdkEvent *event_copy;
+  
+  if (!GTK_IS_ANIMATABLE (widget) && g_queue_is_empty (&expose_events))
+    return FALSE;
+
+  queued_event = g_slice_new (GtkQueuedExposeEvent);
+
+  event_copy = gdk_event_copy (event);
+
+  queued_event->widget = widget;
+  queued_event->event = event_copy;
+
+  g_queue_push_tail (&expose_events, queued_event);
+
+  return TRUE;
+}
+
+/*
+#ifndef DRAW_WIDGET_PIXMAP
+#define DRAW_WIDGET_PIXMAP
+#endif
+*/
+
+static void
+draw_test_pictures (GdkDrawable *pixmap)
+{
+#ifdef DRAW_WIDGET_PIXMAP
+  static gint number = 0;
+
+  cairo_t *cr;
+  cairo_surface_t *src;
+  gchar num_text[12];
+
+  g_printf ("NUMBER: %d\n", number);
+  g_sprintf (num_text, "%04d", number++);
+
+  cr = gdk_cairo_create (pixmap);
+  src = cairo_get_target (cr);
+
+  cairo_surface_write_to_png (src, num_text);
+  cairo_destroy (cr);
+#endif
+}
+
+static GdkPixmap*
+gtk_main_set_redirect (GdkEvent *event)
+{
+  GdkPixmap *pixmap = NULL;
+  gint x, y, width, height;
+
+  x = event->expose.area.x;
+  y = event->expose.area.y;
+  width = event->expose.area.width;
+  height = event->expose.area.height;
+
+  pixmap = gdk_pixmap_new (event->any.window,
+                           width, height, -1);
+
+  gdk_window_redirect_to_drawable (event->any.window,
+                                   pixmap,
+                                   x, y, 0, 0,
+                                   width, height);
+
+  return pixmap;
+}
+
+static void
+gtk_main_unset_redirect (GdkEvent *event,
+                         GtkWidget *widget,
+                         GdkPixmap *pixmap)
+{
+  GdkPixmap *old, *new;
+
+  old = new = NULL;
+
+  gdk_window_remove_redirection (event->any.window);
+
+  #ifdef DRAW_WIDGET_PIXMAP
+  draw_test_pictures (pixmap);
+  #endif
+
+  old = g_object_get_data (G_OBJECT (widget),
+                           GTK_ANIMATABLE_STATE_OLD);
+  new = g_object_get_data (G_OBJECT (widget),
+                           GTK_ANIMATABLE_STATE_NEW);
+
+  if (!old)
+    {
+      g_object_set_data_full (G_OBJECT (widget),
+                              GTK_ANIMATABLE_STATE_OLD,
+                              pixmap,
+                              g_object_unref);
+    }
+  else if (!new)
+    {
+      g_object_set_data_full (G_OBJECT (widget),
+                              GTK_ANIMATABLE_STATE_NEW,
+                              pixmap,
+                              g_object_unref);
+    }
+  else
+    {
+      g_object_ref (new);
+
+      g_object_set_data_full (G_OBJECT (widget),
+                              GTK_ANIMATABLE_STATE_OLD,
+                              new,
+                              g_object_unref);
+
+      g_object_set_data_full (G_OBJECT (widget),
+                              GTK_ANIMATABLE_STATE_NEW,
+                              pixmap,
+                              g_object_unref);
+    }
+}
+
+
 void 
 gtk_main_do_event (GdkEvent *event)
 {
@@ -1554,9 +1688,79 @@
     case GDK_EXPOSE:
       if (event->any.window && GTK_WIDGET_DOUBLE_BUFFERED (event_widget))
 	{
-	  gdk_window_begin_paint_region (event->any.window, event->expose.region);
-	  gtk_widget_send_expose (event_widget, event);
-	  gdk_window_end_paint (event->any.window);
+          GdkPixmap *pixmap;
+          GtkQueuedExposeEvent *queued_event;
+          GList *child_event = NULL;
+          GtkWidget *anim_widget = NULL;
+          GList *old_child_event = NULL;
+          gboolean is_subwindow = FALSE;
+          gboolean is_redirected = TRUE;
+          gboolean is_triggered = FALSE;
+
+          if (GTK_IS_ANIMATABLE (event_widget))
+            {
+              if (!gtk_animatable_running (GTK_ANIMATABLE (event_widget)))
+                gtk_main_queue_expose_event (event_widget, event);
+              else
+                break;
+            }
+          else
+            {
+              gdk_window_begin_paint_region (event->any.window, event->expose.region);
+              gtk_widget_send_expose (event_widget, event);
+              gdk_window_end_paint (event->any.window);
+            }
+
+          child_event = g_queue_peek_head_link (&expose_events);
+
+          if (child_event)
+            {
+              queued_event = (GtkQueuedExposeEvent *) child_event->data;
+              anim_widget = queued_event->widget;
+
+              is_triggered = gtk_animatable_triggered (anim_widget);
+            }
+
+          while (child_event)
+            {
+              if (!GTK_WIDGET_NO_WINDOW (queued_event->widget)
+                  || GTK_WIDGET_REDRAW_ON_ALLOC (queued_event->widget))
+                {
+                  pixmap = gtk_main_set_redirect (queued_event->event);
+                  is_redirected = TRUE;
+                }
+              else
+                is_redirected = FALSE;
+
+              gdk_window_begin_paint_region_full (queued_event->event->any.window, 
+                                                  queued_event->event->expose.region,
+                                                  is_subwindow);
+	      gtk_widget_send_expose (queued_event->widget, queued_event->event);
+	      gdk_window_end_paint_full (queued_event->event->any.window, is_triggered);
+
+              is_subwindow = TRUE;
+
+              if (is_redirected)
+                gtk_main_unset_redirect (queued_event->event,
+                                         queued_event->widget,
+                                         pixmap);
+
+              gdk_event_free (queued_event->event);
+              g_slice_free (GtkQueuedExposeEvent, queued_event);
+          
+              child_event = child_event->next;
+
+              old_child_event = g_queue_pop_head_link (&expose_events);
+              g_list_free (old_child_event);
+
+              if (child_event)
+                queued_event = (GtkQueuedExposeEvent *) child_event->data;
+            }
+
+          if (anim_widget && GTK_IS_ANIMATABLE (anim_widget) 
+              && gtk_animatable_triggered (GTK_ANIMATABLE (anim_widget))
+              && !gtk_animatable_running (GTK_ANIMATABLE (anim_widget)))
+            _gtk_animatable_start_animation (GTK_ANIMATABLE (anim_widget));
 	}
       else
 	gtk_widget_send_expose (event_widget, event);

=== modified file 'gtk/gtkmain.h'
--- gtk/gtkmain.h	2008-07-01 22:57:50 +0000
+++ gtk/gtkmain.h	2009-01-28 21:06:17 +0000
@@ -141,6 +141,8 @@
  * GDK and GTK+.
  */
 void 	   gtk_main_do_event	   (GdkEvent           *event);
+gboolean gtk_main_queue_expose_event (GtkWidget *widget,
+                                      GdkEvent  *event);
 
 void	   gtk_main		   (void);
 guint	   gtk_main_level	   (void);

=== modified file 'gtk/gtkwidget.c'
--- gtk/gtkwidget.c	2009-01-23 05:34:14 +0000
+++ gtk/gtkwidget.c	2009-02-02 14:26:23 +0000
@@ -30,6 +30,7 @@
 #include <locale.h>
 #include "gtkcontainer.h"
 #include "gtkaccelmap.h"
+#include "gtkanimatableprivate.h"
 #include "gtkclipboard.h"
 #include "gtkiconfactory.h"
 #include "gtkintl.h"
@@ -3801,6 +3802,12 @@
   gdk_region_destroy (region);
 }
 
+static void
+gtk_widget_free_old_size_allocate (gpointer data)
+{
+  g_slice_free (GtkAllocation, data);
+}
+
 /**
  * gtk_widget_size_allocate:
  * @widget: a #GtkWidget
@@ -3814,6 +3821,7 @@
 			  GtkAllocation *allocation)
 {
   GtkWidgetAuxInfo *aux_info;
+  GtkAllocation *allocation_old;
   GdkRectangle real_allocation;
   GdkRectangle old_allocation;
   gboolean alloc_needed;
@@ -3848,6 +3856,19 @@
   if (!GTK_WIDGET_REQUEST_NEEDED (widget))      /* Preserve request/allocate ordering */
     GTK_PRIVATE_UNSET_FLAG (widget, GTK_ALLOC_NEEDED);
 
+  /* Save old allocation data */
+  allocation_old = g_slice_new (GtkAllocation);
+
+  allocation_old->x = widget->allocation.x;
+  allocation_old->y = widget->allocation.y;
+  allocation_old->width = widget->allocation.width;
+  allocation_old->height = widget->allocation.height;
+
+  g_object_set_data_full (G_OBJECT (widget),
+                          GTK_ANIMATABLE_OLD_ALLOCATION,
+                          allocation_old,
+                          gtk_widget_free_old_size_allocate);
+
   old_allocation = widget->allocation;
   real_allocation = *allocation;
   aux_info =_gtk_widget_get_aux_info (widget, FALSE);

