]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkcontainer.c
gtkenums: correct various documentation typos
[~andy/gtk] / gtk / gtkcontainer.c
index fc27dd11ee1523db2e64963a55c98f06d12ab2dd..ce16fe4df42e224471754b0886415b08b200e474 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/>.
  */
 
 /*
@@ -36,6 +34,7 @@
 #include <gobject/gobjectnotifyqueue.c>
 #include <gobject/gvaluecollector.h>
 
+#include "gtkadjustment.h"
 #include "gtkbuildable.h"
 #include "gtkbuilderprivate.h"
 #include "gtktypebuiltins.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
 #include "gtksizerequest.h"
+#include "gtksizerequestcacheprivate.h"
 #include "gtkwidgetprivate.h"
 #include "gtkwindow.h"
+#include "gtkassistant.h"
 #include "gtkintl.h"
-#include "gtktoolbar.h"
-
+#include "gtkstylecontextprivate.h"
+#include "gtkwidgetpath.h"
+#include "a11y/gtkcontaineraccessible.h"
 
 /**
  * SECTION:gtkcontainer
@@ -73,7 +75,7 @@
  * The second type of container can have more than one child; its purpose is to
  * manage <emphasis>layout</emphasis>. This means that these containers assign
  * sizes and positions to their children. For example, a #GtkHBox arranges its
- * children in a horizontal row, and a #GtkTable arranges the widgets it contains
+ * children in a horizontal row, and a #GtkGrid arranges the widgets it contains
  * in a two-dimensional grid.
  *
  * <refsect2 id="container-geometry-management">
@@ -234,11 +236,15 @@ struct _GtkContainerPrivate
 {
   GtkWidget *focus_child;
 
+  guint resize_handler;
+  GdkFrameClock *resize_clock;
+
   guint border_width : 16;
 
   guint has_focus_chain    : 1;
-  guint need_resize        : 1;
   guint reallocate_redraws : 1;
+  guint resize_pending     : 1;
+  guint restyle_pending    : 1;
   guint resize_mode        : 2;
   guint request_mode       : 2;
 };
@@ -341,7 +347,6 @@ static const gchar           vadjustment_key[] = "gtk-vadjustment";
 static guint                 vadjustment_key_id = 0;
 static const gchar           hadjustment_key[] = "gtk-hadjustment";
 static guint                 hadjustment_key_id = 0;
-static GSList               *container_resize_queue = NULL;
 static guint                 container_signals[LAST_SIGNAL] = { 0 };
 static GtkWidgetClass       *parent_class = NULL;
 extern GParamSpecPool       *_gtk_widget_child_property_pool;
@@ -512,6 +517,8 @@ gtk_container_class_init (GtkContainerClass *class)
                   GTK_TYPE_WIDGET);
 
   g_type_class_add_private (class, sizeof (GtkContainerPrivate));
+
+  gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_CONTAINER_ACCESSIBLE);
 }
 
 static void
@@ -551,7 +558,7 @@ gtk_container_buildable_set_child_property (GtkContainer *container,
                                             const gchar  *value)
 {
   GParamSpec *pspec;
-  GValue gvalue = { 0, };
+  GValue gvalue = G_VALUE_INIT;
   GError *error = NULL;
 
   pspec = gtk_container_class_find_child_property
@@ -769,8 +776,8 @@ gtk_container_child_type (GtkContainer *container)
 /**
  * gtk_container_child_notify:
  * @container: the #GtkContainer
- * @widget: the child widget
- * @child_property: the name of a chld property installed on
+ * @child: the child widget
+ * @child_property: the name of a child property installed on
  *     the class of @container
  *
  * Emits a #GtkWidget::child-notify signal for the
@@ -785,17 +792,17 @@ gtk_container_child_type (GtkContainer *container)
  */
 void
 gtk_container_child_notify (GtkContainer *container,
-                            GtkWidget    *widget,
+                            GtkWidget    *child,
                             const gchar  *child_property)
 {
   GObject *obj;
   GParamSpec *pspec;
 
   g_return_if_fail (GTK_IS_CONTAINER (container));
-  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (GTK_IS_WIDGET (child));
   g_return_if_fail (child_property != NULL);
 
-  obj = G_OBJECT (widget);
+  obj = G_OBJECT (child);
 
   if (obj->ref_count == 0)
     return;
@@ -845,7 +852,7 @@ container_set_child_property (GtkContainer       *container,
                               const GValue       *value,
                               GObjectNotifyQueue *nqueue)
 {
-  GValue tmp_value = { 0, };
+  GValue tmp_value = G_VALUE_INIT;
   GtkContainerClass *class = g_type_class_peek (pspec->owner_type);
 
   /* provide a copy to work from, convert (if necessary) and validate */
@@ -901,7 +908,7 @@ gtk_container_child_get_valist (GtkContainer *container,
   name = first_property_name;
   while (name)
     {
-      GValue value = { 0, };
+      GValue value = G_VALUE_INIT;
       GParamSpec *pspec;
       gchar *error;
 
@@ -981,7 +988,7 @@ gtk_container_child_get_property (GtkContainer *container,
                G_OBJECT_TYPE_NAME (container));
   else
     {
-      GValue *prop_value, tmp_value = { 0, };
+      GValue *prop_value, tmp_value = G_VALUE_INIT;
 
       /* auto-conversion of the callers value type
        */
@@ -1045,7 +1052,7 @@ gtk_container_child_set_valist (GtkContainer *container,
   name = first_property_name;
   while (name)
     {
-      GValue value = { 0, };
+      GValue value = G_VALUE_INIT;
       gchar *error = NULL;
       GParamSpec *pspec = g_param_spec_pool_lookup (_gtk_widget_child_property_pool,
                                                     name,
@@ -1143,8 +1150,8 @@ gtk_container_child_set_property (GtkContainer *container,
  * @container: a #GtkContainer
  * @widget: a widget to be placed inside @container
  * @first_prop_name: the name of the first child property to set
- * @Varargs: a %NULL-terminated list of property names and values, starting
- *           with @first_prop_name
+ * @...: a %NULL-terminated list of property names and values, starting
+ *     with @first_prop_name
  *
  * Adds @widget to @container, setting child properties at the same time.
  * See gtk_container_add() and gtk_container_child_set() for more details.
@@ -1183,8 +1190,8 @@ gtk_container_add_with_properties (GtkContainer *container,
  * @container: a #GtkContainer
  * @child: a widget which is a child of @container
  * @first_prop_name: the name of the first property to set
- * @Varargs: a %NULL-terminated list of property names and values, starting
- *           with @first_prop_name
+ * @...: a %NULL-terminated list of property names and values, starting
+ *     with @first_prop_name
  *
  * Sets one or more child properties for @child and @container.
  */
@@ -1206,11 +1213,11 @@ gtk_container_child_set (GtkContainer      *container,
  * @container: a #GtkContainer
  * @child: a widget which is a child of @container
  * @first_prop_name: the name of the first property to get
- * @Varargs: return location for the first property, followed
+ * @...: return location for the first property, followed
  *     optionally by more name/return location pairs, followed by %NULL
  *
  * Gets the values of one or more child properties for @child and @container.
- **/
+ */
 void
 gtk_container_child_get (GtkContainer      *container,
                          GtkWidget         *child,
@@ -1265,10 +1272,11 @@ gtk_container_class_install_child_property (GtkContainerClass *cclass,
  * gtk_container_class_find_child_property:
  * @cclass: (type GtkContainerClass): a #GtkContainerClass
  * @property_name: the name of the child property to find
- * @returns: (transfer none): the #GParamSpec of the child property or
- *           %NULL if @class has no child property with that name.
  *
  * Finds a child property of a container class by name.
+ *
+ * Returns: (transfer none): the #GParamSpec of the child property
+ *     or %NULL if @class has no child property with that name.
  */
 GParamSpec*
 gtk_container_class_find_child_property (GObjectClass *cclass,
@@ -1287,11 +1295,12 @@ gtk_container_class_find_child_property (GObjectClass *cclass,
  * gtk_container_class_list_child_properties:
  * @cclass: (type GtkContainerClass): a #GtkContainerClass
  * @n_properties: location to return the number of child properties found
- * @returns: (array length=n_properties) (transfer container): a newly
- *           allocated %NULL-terminated array of #GParamSpec*.  The
- *           array must be freed with g_free().
  *
  * Returns all child properties of a container class.
+ *
+ * Returns: (array length=n_properties) (transfer container):
+ *     a newly allocated %NULL-terminated array of #GParamSpec*.
+ *     The array must be freed with g_free().
  */
 GParamSpec**
 gtk_container_class_list_child_properties (GObjectClass *cclass,
@@ -1337,7 +1346,6 @@ gtk_container_init (GtkContainer *container)
 
   priv->focus_child = NULL;
   priv->border_width = 0;
-  priv->need_resize = FALSE;
   priv->resize_mode = GTK_RESIZE_PARENT;
   priv->reallocate_redraws = FALSE;
 }
@@ -1348,9 +1356,12 @@ gtk_container_destroy (GtkWidget *widget)
   GtkContainer *container = GTK_CONTAINER (widget);
   GtkContainerPrivate *priv = container->priv;
 
-  if (_gtk_widget_get_resize_pending (GTK_WIDGET (container)))
+  if (priv->resize_pending)
     _gtk_container_dequeue_resize_handler (container);
 
+  if (priv->restyle_pending)
+    priv->restyle_pending = FALSE;
+
   if (priv->focus_child)
     {
       g_object_unref (priv->focus_child);
@@ -1477,10 +1488,10 @@ gtk_container_get_border_width (GtkContainer *container)
  *
  * Adds @widget to @container. Typically used for simple containers
  * such as #GtkWindow, #GtkFrame, or #GtkButton; for more complicated
- * layout containers such as #GtkBox or #GtkTable, this function will
+ * layout containers such as #GtkBox or #GtkGrid, this function will
  * pick default packing parameters that may not be correct.  So
  * consider functions such as gtk_box_pack_start() and
- * gtk_table_attach() as an alternative to gtk_container_add() in
+ * gtk_grid_attach() as an alternative to gtk_container_add() in
  * those cases. A widget may be added to only one container at a time;
  * you can't place the same widget inside two different containers.
  **/
@@ -1530,7 +1541,7 @@ gtk_container_remove (GtkContainer *container,
 {
   g_return_if_fail (GTK_IS_CONTAINER (container));
   g_return_if_fail (GTK_IS_WIDGET (widget));
-  g_return_if_fail (gtk_widget_get_parent (widget) == GTK_WIDGET (container));
+  g_return_if_fail (gtk_widget_get_parent (widget) == GTK_WIDGET (container) || GTK_IS_ASSISTANT (container));
 
   g_signal_emit (container, container_signals[REMOVE], 0, widget);
 }
@@ -1539,10 +1550,9 @@ void
 _gtk_container_dequeue_resize_handler (GtkContainer *container)
 {
   g_return_if_fail (GTK_IS_CONTAINER (container));
-  g_return_if_fail (_gtk_widget_get_resize_pending (GTK_WIDGET (container)));
+  g_return_if_fail (container->priv->resize_pending);
 
-  container_resize_queue = g_slist_remove (container_resize_queue, container);
-  _gtk_widget_set_resize_pending (GTK_WIDGET (container), FALSE);
+  container->priv->resize_pending = FALSE;
 }
 
 /**
@@ -1618,115 +1628,166 @@ gtk_container_set_reallocate_redraws (GtkContainer *container,
   container->priv->reallocate_redraws = needs_redraws ? TRUE : FALSE;
 }
 
-static GtkContainer*
-gtk_container_get_resize_container (GtkContainer *container)
-{
-  GtkWidget *parent;
-  GtkWidget *widget = GTK_WIDGET (container);
-
-  while ((parent = gtk_widget_get_parent (widget)))
+static void
+gtk_container_idle_sizer (GdkFrameClock *clock,
+                         GtkContainer  *container)
+{
+  /* We validate the style contexts in a single loop before even trying
+   * to handle resizes instead of doing validations inline.
+   * This is mostly necessary for compatibility reasons with old code,
+   * because both style_updated and size_allocate functions often change
+   * styles and so could cause infinite loops in this function.
+   *
+   * It's important to note that even an invalid style context returns
+   * sane values. So the result of an invalid style context will never be
+   * a program crash, but only a wrong layout or rendering.
+   */
+  if (container->priv->restyle_pending)
     {
-      widget = parent;
-      if (GTK_IS_RESIZE_CONTAINER (widget))
-        break;
-    }
+      GtkBitmask *empty;
+      gint64 current_time;
 
-  return GTK_IS_RESIZE_CONTAINER (widget) ? (GtkContainer*) widget : NULL;
-}
+      empty = _gtk_bitmask_new ();
+      current_time = g_get_monotonic_time ();
+
+      container->priv->restyle_pending = FALSE;
+      _gtk_style_context_validate (gtk_widget_get_style_context (GTK_WIDGET (container)),
+                                   current_time,
+                                   0,
+                                   empty);
+
+      _gtk_bitmask_free (empty);
+    }
 
-static gboolean
-gtk_container_idle_sizer (gpointer data)
-{
   /* we may be invoked with a container_resize_queue of NULL, because
    * queue_resize could have been adding an extra idle function while
    * the queue still got processed. we better just ignore such case
    * than trying to explicitely work around them with some extra flags,
    * since it doesn't cause any actual harm.
    */
-  while (container_resize_queue)
+  if (container->priv->resize_pending)
     {
-      GSList *slist;
-      GtkWidget *widget;
-
-      slist = container_resize_queue;
-      container_resize_queue = slist->next;
-      widget = slist->data;
-      g_slist_free_1 (slist);
+      container->priv->resize_pending = FALSE;
+      gtk_container_check_resize (container);
+    }
 
-      _gtk_widget_set_resize_pending (widget, FALSE);
-      gtk_container_check_resize (GTK_CONTAINER (widget));
+  if (!container->priv->restyle_pending && !container->priv->resize_pending)
+    {
+      _gtk_container_stop_idle_sizer (container);
+    }
+  else
+    {
+      gdk_frame_clock_request_phase (clock,
+                                     GDK_FRAME_CLOCK_PHASE_LAYOUT);
     }
+}
 
-  gdk_window_process_all_updates ();
+static void
+gtk_container_start_idle_sizer (GtkContainer *container)
+{
+  GdkFrameClock *clock;
 
-  return FALSE;
+  if (container->priv->resize_handler != 0)
+    return;
+
+  clock = gtk_widget_get_frame_clock (GTK_WIDGET (container));
+  if (clock == NULL)
+    return;
+
+  container->priv->resize_clock = clock;
+  container->priv->resize_handler = g_signal_connect (clock, "layout",
+                                                     G_CALLBACK (gtk_container_idle_sizer), container);
+  gdk_frame_clock_request_phase (clock,
+                                 GDK_FRAME_CLOCK_PHASE_LAYOUT);
+}
+
+void
+_gtk_container_stop_idle_sizer (GtkContainer *container)
+{
+  if (container->priv->resize_handler == 0)
+    return;
+
+  g_signal_handler_disconnect (container->priv->resize_clock,
+                               container->priv->resize_handler);
+  container->priv->resize_handler = 0;
+  container->priv->resize_clock = NULL;
+}
+
+static void
+gtk_container_queue_resize_handler (GtkContainer *container)
+{
+  GtkWidget *widget;
+
+  g_return_if_fail (GTK_IS_RESIZE_CONTAINER (container));
+
+  widget = GTK_WIDGET (container);
+
+  if (gtk_widget_get_visible (widget) &&
+      (gtk_widget_is_toplevel (widget) ||
+       gtk_widget_get_realized (widget)))
+    {
+      switch (container->priv->resize_mode)
+        {
+        case GTK_RESIZE_QUEUE:
+          if (!container->priv->resize_pending)
+            {
+              container->priv->resize_pending = TRUE;
+              gtk_container_start_idle_sizer (container);
+            }
+          break;
+
+        case GTK_RESIZE_IMMEDIATE:
+          gtk_container_check_resize (container);
+          break;
+
+        case GTK_RESIZE_PARENT:
+        default:
+          g_assert_not_reached ();
+          break;
+        }
+    }
 }
 
 static void
 _gtk_container_queue_resize_internal (GtkContainer *container,
                                       gboolean      invalidate_only)
 {
-  GtkContainer *resize_container;
-  GtkWidget *parent;
   GtkWidget *widget;
 
   g_return_if_fail (GTK_IS_CONTAINER (container));
 
   widget = GTK_WIDGET (container);
 
-  resize_container = gtk_container_get_resize_container (container);
-
-  while (TRUE)
+  do
     {
       _gtk_widget_set_alloc_needed (widget, TRUE);
-      _gtk_widget_set_width_request_needed (widget, TRUE);
-      _gtk_widget_set_height_request_needed (widget, TRUE);
+      _gtk_size_request_cache_clear (_gtk_widget_peek_request_cache (widget));
 
-      if ((resize_container && widget == GTK_WIDGET (resize_container)) ||
-          !(parent = gtk_widget_get_parent (widget)))
+      if (GTK_IS_RESIZE_CONTAINER (widget))
         break;
 
-      widget = parent;
+      widget = gtk_widget_get_parent (widget);
     }
+  while (widget);
 
-  if (resize_container && !invalidate_only)
-    {
-      if (gtk_widget_get_visible (GTK_WIDGET (resize_container)) &&
-          (gtk_widget_is_toplevel (GTK_WIDGET (resize_container)) ||
-           gtk_widget_get_realized (GTK_WIDGET (resize_container))))
-        {
-          switch (resize_container->priv->resize_mode)
-            {
-            case GTK_RESIZE_QUEUE:
-              if (!_gtk_widget_get_resize_pending (GTK_WIDGET (resize_container)))
-                {
-                  _gtk_widget_set_resize_pending (GTK_WIDGET (resize_container), TRUE);
-                  if (container_resize_queue == NULL)
-                    gdk_threads_add_idle_full (GTK_PRIORITY_RESIZE,
-                                     gtk_container_idle_sizer,
-                                     NULL, NULL);
-                  container_resize_queue = g_slist_prepend (container_resize_queue, resize_container);
-                }
-              break;
+  if (widget && !invalidate_only)
+    gtk_container_queue_resize_handler (GTK_CONTAINER (widget));
+}
 
-            case GTK_RESIZE_IMMEDIATE:
-              gtk_container_check_resize (resize_container);
-              break;
+void
+_gtk_container_queue_restyle (GtkContainer *container)
+{
+  GtkContainerPrivate *priv;
 
-            case GTK_RESIZE_PARENT:
-              g_assert_not_reached ();
-              break;
-            }
-        }
-      else
-        {
-          /* we need to let hidden resize containers know that something
-           * changed while they where hidden (currently only evaluated by
-           * toplevels).
-           */
-          resize_container->priv->need_resize = TRUE;
-        }
-    }
+  g_return_if_fail (GTK_CONTAINER (container));
+
+  priv = container->priv;
+
+  if (priv->restyle_pending)
+    return;
+
+  gtk_container_start_idle_sizer (container);
+  priv->restyle_pending = TRUE;
 }
 
 /**
@@ -1759,6 +1820,13 @@ _gtk_container_resize_invalidate (GtkContainer *container)
   _gtk_container_queue_resize_internal (container, TRUE);
 }
 
+void
+_gtk_container_maybe_start_idle_sizer (GtkContainer *container)
+{
+  if (container->priv->restyle_pending || container->priv->resize_pending)
+    gtk_container_start_idle_sizer (container);
+}
+
 void
 gtk_container_check_resize (GtkContainer *container)
 {
@@ -1862,32 +1930,11 @@ gtk_container_adjust_size_allocation (GtkWidget         *widget,
 
   container = GTK_CONTAINER (widget);
 
-  if (!GTK_CONTAINER_GET_CLASS (widget)->_handle_border_width)
+  if (GTK_CONTAINER_GET_CLASS (widget)->_handle_border_width)
     {
-      parent_class->adjust_size_allocation (widget, orientation,
-                                            minimum_size, natural_size, allocated_pos,
-                                            allocated_size);
-      return;
-    }
-
-  border_width = container->priv->border_width;
-
-  *allocated_size -= border_width * 2;
-
-  /* If we get a pathological too-small allocation to hold
-   * even the border width, leave all allocation to the actual
-   * widget, and leave x,y unchanged. (GtkWidget's min size is
-   * 1x1 if you're wondering why <1 and not <0)
-   *
-   * As long as we have space, set x,y properly.
-   */
+      border_width = container->priv->border_width;
 
-  if (*allocated_size < 1)
-    {
-      *allocated_size += border_width * 2;
-    }
-  else
-    {
+      *allocated_size -= border_width * 2;
       *allocated_pos += border_width;
       *minimum_size -= border_width * 2;
       *natural_size -= border_width * 2;
@@ -1933,27 +1980,17 @@ count_request_modes (GtkWidget        *widget,
 static GtkSizeRequestMode 
 gtk_container_get_request_mode (GtkWidget *widget)
 {
-  GtkContainer        *container = GTK_CONTAINER (widget);
-  GtkContainerPrivate *priv      = container->priv;
-
-  /* Recalculate the request mode of the children by majority
-   * vote whenever the internal content changes */
-  if (_gtk_widget_get_width_request_needed (widget) ||
-      _gtk_widget_get_height_request_needed (widget))
-    {
-      RequestModeCount count = { 0, 0 };
-
-      gtk_container_forall (container, (GtkCallback)count_request_modes, &count);
+  GtkContainer *container = GTK_CONTAINER (widget);
+  RequestModeCount count = { 0, 0 };
 
-      if (!count.hfw && !count.wfh)
-       priv->request_mode = GTK_SIZE_REQUEST_CONSTANT_SIZE;
-      else
-       priv->request_mode = count.wfh > count.hfw ? 
-         GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT :
-         GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
-    }
+  gtk_container_forall (container, (GtkCallback)count_request_modes, &count);
 
-  return priv->request_mode;
+  if (!count.hfw && !count.wfh)
+    return GTK_SIZE_REQUEST_CONSTANT_SIZE;
+  else
+    return count.wfh > count.hfw ? 
+        GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT :
+       GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
 }
 
 /**
@@ -2298,8 +2335,8 @@ get_focus_chain (GtkContainer *container)
 
 /* same as gtk_container_get_children, except it includes internals
  */
-static GList *
-gtk_container_get_all_children (GtkContainer *container)
+GList *
+_gtk_container_get_all_children (GtkContainer *container)
 {
   GList *children = NULL;
 
@@ -2319,7 +2356,7 @@ gtk_container_real_get_path_for_child (GtkContainer *container,
   GList *classes;
 
   context = gtk_widget_get_style_context (GTK_WIDGET (container));
-  path = gtk_widget_path_copy (gtk_widget_get_path (GTK_WIDGET (container)));
+  path = _gtk_widget_create_path (GTK_WIDGET (container));
 
   /* Copy any permanent classes to the path */
   classes = gtk_style_context_list_classes (context);
@@ -2373,7 +2410,7 @@ gtk_container_focus (GtkWidget        *widget,
       if (priv->has_focus_chain)
         children = g_list_copy (get_focus_chain (container));
       else
-        children = gtk_container_get_all_children (container);
+        children = _gtk_container_get_all_children (container);
 
       if (priv->has_focus_chain &&
           (direction == GTK_DIR_TAB_FORWARD ||
@@ -3340,19 +3377,6 @@ gtk_container_propagate_draw (GtkContainer   *container,
   cairo_restore (cr);
 }
 
-gboolean
-_gtk_container_get_need_resize (GtkContainer *container)
-{
-  return container->priv->need_resize;
-}
-
-void
-_gtk_container_set_need_resize (GtkContainer *container,
-                                gboolean      need_resize)
-{
-  container->priv->need_resize = need_resize;
-}
-
 gboolean
 _gtk_container_get_reallocate_redraws (GtkContainer *container)
 {
@@ -3373,9 +3397,21 @@ GtkWidgetPath *
 gtk_container_get_path_for_child (GtkContainer *container,
                                   GtkWidget    *child)
 {
+  GtkWidgetPath *path;
+
   g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL);
   g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
   g_return_val_if_fail (container == (GtkContainer *) gtk_widget_get_parent (child), NULL);
 
-  return GTK_CONTAINER_GET_CLASS (container)->get_path_for_child (container, child);
+  path = GTK_CONTAINER_GET_CLASS (container)->get_path_for_child (container, child);
+  if (gtk_widget_path_get_object_type (path) != G_OBJECT_TYPE (child))
+    {
+      g_critical ("%s %p returned a widget path for type %s, but child is %s",
+                  G_OBJECT_TYPE_NAME (container),
+                  container,
+                  g_type_name (gtk_widget_path_get_object_type (path)),
+                  G_OBJECT_TYPE_NAME (child));
+    }
+
+  return path;
 }