]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkwidget.c
Make sure the paper dialog is destroyed with the parent
[~andy/gtk] / gtk / gtkwidget.c
index c15da47d9f2db4100c33adef24b5de57f52cf2e2..9ee2218e9c66612a8d7561bdeb7179849cf7beab 100644 (file)
@@ -154,7 +154,8 @@ enum {
   PROP_HAS_TOOLTIP,
   PROP_TOOLTIP_MARKUP,
   PROP_TOOLTIP_TEXT,
-  PROP_WINDOW
+  PROP_WINDOW,
+  PROP_DOUBLE_BUFFERED
 };
 
 typedef        struct  _GtkStateData    GtkStateData;
@@ -274,6 +275,7 @@ static void             gtk_widget_buildable_custom_finished    (GtkBuildable
 static void             gtk_widget_buildable_parser_finished    (GtkBuildable     *buildable,
                                                                  GtkBuilder       *builder);
 
+static void             gtk_widget_queue_tooltip_query          (GtkWidget *widget);
      
 static void gtk_widget_set_usize_internal (GtkWidget *widget,
                                           gint       width,
@@ -691,6 +693,21 @@ gtk_widget_class_init (GtkWidgetClass *klass)
                                                        GDK_TYPE_WINDOW,
                                                        GTK_PARAM_READABLE));
 
+  /**
+   * GtkWidget:double-buffered
+   *
+   * Whether or not the widget is double buffered.
+   *
+   * Since: 2.18
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_DOUBLE_BUFFERED,
+                                   g_param_spec_boolean ("double-buffered",
+                                                         P_("Double Buffered"),
+                                                         P_("Whether or not the widget is double buffered"),
+                                                         TRUE,
+                                                         GTK_PARAM_READWRITE));
+
   widget_signals[SHOW] =
     g_signal_new (I_("show"),
                  G_TYPE_FROM_CLASS (gobject_class),
@@ -2488,17 +2505,18 @@ gtk_widget_set_property (GObject         *object,
        * because an empty string would be useless for a tooltip:
        */
       if (tooltip_markup && (strlen (tooltip_markup) == 0))
-      {
-       g_free (tooltip_markup);
-        tooltip_markup = NULL;
-      }
+        {
+         g_free (tooltip_markup);
+          tooltip_markup = NULL;
+        }
 
       g_object_set_qdata_full (object, quark_tooltip_markup,
                               tooltip_markup, g_free);
 
       tmp = (tooltip_window != NULL || tooltip_markup != NULL);
       gtk_widget_real_set_has_tooltip (widget, tmp, FALSE);
-      gtk_widget_trigger_tooltip_query (widget);
+      if (GTK_WIDGET_VISIBLE (widget))
+        gtk_widget_queue_tooltip_query (widget);
       break;
     case PROP_TOOLTIP_TEXT:
       tooltip_window = g_object_get_qdata (object, quark_tooltip_window);
@@ -2518,7 +2536,11 @@ gtk_widget_set_property (GObject         *object,
 
       tmp = (tooltip_window != NULL || tooltip_markup != NULL);
       gtk_widget_real_set_has_tooltip (widget, tmp, FALSE);
-      gtk_widget_trigger_tooltip_query (widget);
+      if (GTK_WIDGET_VISIBLE (widget))
+        gtk_widget_queue_tooltip_query (widget);
+      break;
+    case PROP_DOUBLE_BUFFERED:
+      gtk_widget_set_double_buffered (widget, g_value_get_boolean (value));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -2627,6 +2649,9 @@ gtk_widget_get_property (GObject         *object,
     case PROP_WINDOW:
       g_value_set_object (value, gtk_widget_get_window (widget));
       break;
+    case PROP_DOUBLE_BUFFERED:
+      g_value_set_boolean (value, gtk_widget_get_double_buffered (widget));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -5063,8 +5088,10 @@ _gtk_widget_grab_notify (GtkWidget *widget,
  * 
  * Causes @widget to have the keyboard focus for the #GtkWindow it's
  * inside. @widget must be a focusable widget, such as a #GtkEntry;
- * something like #GtkFrame won't work. (More precisely, it must have the
- * %GTK_CAN_FOCUS flag set.)
+ * something like #GtkFrame won't work.
+ *
+ * More precisely, it must have the %GTK_CAN_FOCUS flag set. Use
+ * gtk_widget_set_can_focus() to modify that flag.
  **/
 void
 gtk_widget_grab_focus (GtkWidget *widget)
@@ -5255,6 +5282,74 @@ gtk_widget_real_keynav_failed (GtkWidget        *widget,
   return TRUE;
 }
 
+/**
+ * gtk_widget_set_can_focus:
+ * @widget: a #GtkWidget
+ * @can_focus: whether or not @widget can own the input focus.
+ *
+ * Specifies whether @widget can own the input focus. See
+ * gtk_widget_grab_focus() for actually setting the input focus on a
+ * widget.
+ *
+ * Since: 2.18
+ **/
+void
+gtk_widget_set_can_focus (GtkWidget *widget,
+                          gboolean   can_focus)
+{
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  if (can_focus != GTK_WIDGET_CAN_FOCUS (widget))
+    {
+      if (can_focus)
+        GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
+      else
+        GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS);
+
+      gtk_widget_queue_resize (widget);
+      g_object_notify (G_OBJECT (widget), "can-focus");
+    }
+}
+
+/**
+ * gtk_widget_get_can_focus:
+ * @widget: a #GtkWidget
+ *
+ * Determines whether @widget can own the input focus. See
+ * gtk_widget_set_can_focus().
+ *
+ * Return value: %TRUE if @widget can own the input focus, %FALSE otherwise
+ *
+ * Since: 2.18
+ **/
+gboolean
+gtk_widget_get_can_focus (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return GTK_WIDGET_CAN_FOCUS (widget);
+}
+
+/**
+ * gtk_widget_has_focus:
+ * @widget: a #GtkWidget
+ *
+ * Determines if the widget has the global input focus. See
+ * gtk_widget_is_focus() for the difference between having the global
+ * input focus, and only having the focus within a toplevel.
+ *
+ * Return value: %TRUE if the widget has the global input focus.
+ *
+ * Since: 2.18
+ **/
+gboolean
+gtk_widget_has_focus (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return GTK_WIDGET_HAS_FOCUS (widget);
+}
+
 /**
  * gtk_widget_is_focus:
  * @widget: a #GtkWidget
@@ -5281,14 +5376,82 @@ gtk_widget_is_focus (GtkWidget *widget)
     return FALSE;
 }
 
+/**
+ * gtk_widget_set_can_default:
+ * @widget: a #GtkWidget
+ * @can_default: whether or not @widget can be a default widget.
+ *
+ * Specifies whether @widget can be a default widget. See
+ * gtk_widget_grab_default() for details about the meaning of
+ * "default".
+ *
+ * Since: 2.18
+ **/
+void
+gtk_widget_set_can_default (GtkWidget *widget,
+                            gboolean   can_default)
+{
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  if (can_default != GTK_WIDGET_CAN_DEFAULT (widget))
+    {
+      if (can_default)
+        GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_DEFAULT);
+      else
+        GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_DEFAULT);
+
+      gtk_widget_queue_resize (widget);
+      g_object_notify (G_OBJECT (widget), "can-default");
+    }
+}
+
+/**
+ * gtk_widget_get_can_default:
+ * @widget: a #GtkWidget
+ *
+ * Determines whether @widget can be a default widget. See
+ * gtk_widget_set_can_default().
+ *
+ * Return value: %TRUE if @widget can be a default widget, %FALSE otherwise
+ *
+ * Since: 2.18
+ **/
+gboolean
+gtk_widget_get_can_default (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return GTK_WIDGET_CAN_DEFAULT (widget);
+}
+
+/**
+ * gtk_widget_has_default:
+ * @widget: a #GtkWidget
+ *
+ * Determines whether @widget is the current default widget within its
+ * toplevel. See gtk_widget_set_can_default().
+ *
+ * Return value: %TRUE if @widget is the current default widget within
+ *     its toplevel, %FALSE otherwise
+ *
+ * Since: 2.18
+ */
+gboolean
+gtk_widget_has_default (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return GTK_WIDGET_HAS_DEFAULT (widget);
+}
+
 /**
  * gtk_widget_grab_default:
  * @widget: a #GtkWidget
  *
  * Causes @widget to become the default widget. @widget must have the
  * %GTK_CAN_DEFAULT flag set; typically you have to set this flag
- * yourself by calling <literal>GTK_WIDGET_SET_FLAGS (@widget,
- * GTK_CAN_DEFAULT)</literal>. The default widget is activated when 
+ * yourself by calling <literal>gtk_widget_set_can_default (@widget,
+ * %TRUE)</literal>. The default widget is activated when 
  * the user presses Enter in a window. Default widgets must be 
  * activatable, that is, gtk_widget_activate() should affect them.
  **/
@@ -5308,6 +5471,27 @@ gtk_widget_grab_default (GtkWidget *widget)
     g_warning (G_STRLOC ": widget not within a GtkWindow");
 }
 
+/**
+ * gtk_widget_has_grab:
+ * @widget: a #GtkWidget
+ *
+ * Determines whether the widget is currently grabbing events, so it
+ * is the only widget receiving input events (keyboard and mouse).
+ *
+ * See also gtk_grab_add().
+ *
+ * Return value: %TRUE if the widget is in the grab_widgets stack
+ *
+ * Since: 2.18
+ **/
+gboolean
+gtk_widget_has_grab (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return (GTK_WIDGET_FLAGS (widget) & GTK_HAS_GRAB) != 0;
+}
+
 /**
  * gtk_widget_set_name:
  * @widget: a #GtkWidget
@@ -5398,6 +5582,164 @@ gtk_widget_set_state (GtkWidget           *widget,
     }
 }
 
+/**
+ * gtk_widget_get_state:
+ * @widget: a #GtkWidget
+ *
+ * Returns the widget's state. See gtk_widget_set_state().
+ *
+ * Returns: the state of @widget.
+ *
+ * Since: 2.18
+ */
+GtkStateType
+gtk_widget_get_state (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), GTK_STATE_NORMAL);
+
+  return widget->state;
+}
+
+/**
+ * gtk_widget_set_visible:
+ * @widget: a #GtkWidget
+ * @visible: whether the widget should be shown or not
+ *
+ * Sets the visibility state of @widget. Note that setting this to
+ * %TRUE doesn't mean the widget is actually viewable, see
+ * gtk_widget_get_visible().
+ *
+ * This function simply calls gtk_widget_show() or gtk_widget_hide()
+ * but is nicer to use when the visibility of the widget depends on
+ * some condition.
+ *
+ * Since: 2.18
+ **/
+void
+gtk_widget_set_visible (GtkWidget *widget,
+                        gboolean   visible)
+{
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  if (visible != GTK_WIDGET_VISIBLE (widget))
+    {
+      if (visible)
+        gtk_widget_show (widget);
+      else
+        gtk_widget_hide (widget);
+    }
+}
+
+/**
+ * gtk_widget_get_visible:
+ * @widget: a #GtkWidget
+ *
+ * Determines whether the widget is visible. Note that this doesn't
+ * take into account whether the widget's parent is also visible
+ * or the widget is obscured in any way.
+ *
+ * See gtk_widget_set_visible().
+ *
+ * Return value: %TRUE if the widget is visible
+ *
+ * Since: 2.18
+ **/
+gboolean
+gtk_widget_get_visible (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return (GTK_WIDGET_FLAGS (widget) & GTK_VISIBLE) != 0;
+}
+
+/**
+ * gtk_widget_set_has_window:
+ * @widget: a #GtkWidget
+ * @has_window: whether or not @widget has a window.
+ *
+ * Specifies whether @widget has a #GdkWindow of its own. Note that
+ * all realized widgets have a non-%NULL "window" pointer
+ * (gtk_widget_get_window() never returns a %NULL window when a widget
+ * is realized), but for many of them it's actually the #GdkWindow of
+ * one of its parent widgets. Widgets that create a %window for
+ * themselves in GtkWidget::realize() however must announce this by
+ * calling this function with @has_window = %TRUE.
+ *
+ * This function should only be called by widget implementations,
+ * and they should call it in their init() function.
+ *
+ * Since: 2.18
+ **/
+void
+gtk_widget_set_has_window (GtkWidget *widget,
+                           gboolean   has_window)
+{
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  if (has_window)
+    GTK_WIDGET_UNSET_FLAGS (widget, GTK_NO_WINDOW);
+  else
+    GTK_WIDGET_SET_FLAGS (widget, GTK_NO_WINDOW);
+}
+
+/**
+ * gtk_widget_get_has_window:
+ * @widget: a #GtkWidget
+ *
+ * Determines whether @widget has a #GdkWindow of its own. See
+ * gtk_widget_set_has_window().
+ *
+ * Return value: %TRUE if @widget has a window, %FALSE otherwise
+ *
+ * Since: 2.18
+ **/
+gboolean
+gtk_widget_get_has_window (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return !GTK_WIDGET_NO_WINDOW (widget);
+}
+
+/**
+ * gtk_widget_is_toplevel:
+ * @widget: a #GtkWidget
+ *
+ * Determines whether @widget is a toplevel widget. Currently only
+ * #GtkWindow and #GtkInvisible are toplevel widgets. Toplevel
+ * widgets have no parent widget.
+ *
+ * Return value: %TRUE if @widget is a toplevel, %FALSE otherwise
+ *
+ * Since: 2.18
+ **/
+gboolean
+gtk_widget_is_toplevel (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return (GTK_WIDGET_FLAGS (widget) & GTK_TOPLEVEL) != 0;
+}
+
+/**
+ * gtk_widget_is_drawable:
+ * @widget: a #GtkWidget
+ *
+ * Determines whether @widget can be drawn to. A widget can be drawn
+ * to if it is mapped and visible.
+ *
+ * Return value: %TRUE if @widget is drawable, %FALSE otherwise
+ *
+ * Since: 2.18
+ **/
+gboolean
+gtk_widget_is_drawable (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return ((GTK_WIDGET_FLAGS (widget) & GTK_VISIBLE) != 0 &&
+          (GTK_WIDGET_FLAGS (widget) & GTK_MAPPED) != 0);
+}
 
 /**
  * gtk_widget_set_app_paintable:
@@ -5445,6 +5787,27 @@ gtk_widget_set_app_paintable (GtkWidget *widget,
     }
 }
 
+/**
+ * gtk_widget_get_app_paintable:
+ * @widget: a #GtkWidget
+ *
+ * Determines whether the application intends to draw on the widget in
+ * an #GtkWidget::expose-event handler.
+ *
+ * See gtk_widget_set_app_paintable()
+ *
+ * Return value: %TRUE if the widget is app paintable
+ *
+ * Since: 2.18
+ **/
+gboolean
+gtk_widget_get_app_paintable (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return (GTK_WIDGET_FLAGS (widget) & GTK_APP_PAINTABLE) != 0;
+}
+
 /**
  * gtk_widget_set_double_buffered:
  * @widget: a #GtkWidget
@@ -5475,10 +5838,35 @@ gtk_widget_set_double_buffered (GtkWidget *widget,
 {
   g_return_if_fail (GTK_IS_WIDGET (widget));
 
-  if (double_buffered)
-    GTK_WIDGET_SET_FLAGS (widget, GTK_DOUBLE_BUFFERED);
-  else
-    GTK_WIDGET_UNSET_FLAGS (widget, GTK_DOUBLE_BUFFERED);
+  if (double_buffered != GTK_WIDGET_DOUBLE_BUFFERED (widget))
+    {
+      if (double_buffered)
+        GTK_WIDGET_SET_FLAGS (widget, GTK_DOUBLE_BUFFERED);
+      else
+        GTK_WIDGET_UNSET_FLAGS (widget, GTK_DOUBLE_BUFFERED);
+
+      g_object_notify (G_OBJECT (widget), "double-buffered");
+    }
+}
+
+/**
+ * gtk_widget_get_double_buffered:
+ * @widget: a #GtkWidget
+ *
+ * Determines whether the widget is double buffered.
+ *
+ * See gtk_widget_set_double_buffered()
+ *
+ * Return value: %TRUE if the widget is double buffered
+ *
+ * Since: 2.18
+ **/
+gboolean
+gtk_widget_get_double_buffered (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return (GTK_WIDGET_FLAGS (widget) & GTK_DOUBLE_BUFFERED) != 0;
 }
 
 /**
@@ -5563,6 +5951,47 @@ gtk_widget_set_sensitive (GtkWidget *widget,
   g_object_notify (G_OBJECT (widget), "sensitive");
 }
 
+/**
+ * gtk_widget_get_sensitive:
+ * @widget: a #GtkWidget
+ *
+ * Returns the widget's sensitivity (in the sense of returning
+ * the value that has been set using gtk_widget_set_sensitive()).
+ *
+ * The effective sensitivity of a widget is however determined by both its
+ * own and its parent widget's sensitivity. See gtk_widget_is_sensitive().
+ *
+ * Returns: %TRUE if the widget is sensitive
+ *
+ * Since: 2.18
+ */
+gboolean
+gtk_widget_get_sensitive (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return GTK_WIDGET_SENSITIVE (widget);
+}
+
+/**
+ * gtk_widget_is_sensitive:
+ * @widget: a #GtkWidget
+ *
+ * Returns the widget's effective sensitivity, which means
+ * it is sensitive itself and also its parent widget is sensntive
+ *
+ * Returns: %TRUE if the widget is effectively sensitive
+ *
+ * Since: 2.18
+ */
+gboolean
+gtk_widget_is_sensitive (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return GTK_WIDGET_IS_SENSITIVE (widget);
+}
+
 /**
  * gtk_widget_set_parent:
  * @widget: a #GtkWidget
@@ -8181,7 +8610,7 @@ _gtk_widget_is_pointer_widget (GtkWidget *widget)
       win = _gtk_widget_get_pointer_window (widget);
       if (win)
         {
-          gdk_window_get_user_data (win, &wid);
+          gdk_window_get_user_data (win, (gpointer *)&wid);
           if (wid == widget)
             return TRUE;
         }
@@ -9627,9 +10056,9 @@ accessibility_start_element (GMarkupParseContext  *context,
     }
   else if (strcmp (element_name, "action") == 0)
     {
-      gchar *action_name = NULL;
-      gchar *description = NULL;
-      gchar *context = NULL;
+      const gchar *action_name = NULL;
+      const gchar *description = NULL;
+      const gchar *msg_context = NULL;
       gboolean translatable = FALSE;
       AtkActionData *action;
 
@@ -9649,7 +10078,7 @@ accessibility_start_element (GMarkupParseContext  *context,
               /* do nothing, comments are for translators */
             }
           else if (strcmp (names[i], "context") == 0)
-            context = values[i];
+            msg_context = values[i];
          else
            {
              g_markup_parse_context_get_position (context,
@@ -9683,7 +10112,7 @@ accessibility_start_element (GMarkupParseContext  *context,
       action = g_slice_new (AtkActionData);
       action->action_name = g_strdup (action_name);
       action->description = g_string_new (description);
-      action->context = g_strdup (context);
+      action->context = g_strdup (msg_context);
       action->translatable = translatable;
 
       data->actions = g_slist_prepend (data->actions, action);
@@ -9803,6 +10232,44 @@ gtk_widget_buildable_custom_tag_start (GtkBuildable     *buildable,
   return FALSE;
 }
 
+void
+_gtk_widget_buildable_finish_accelerator (GtkWidget *widget,
+                                         GtkWidget *toplevel,
+                                         gpointer   user_data)
+{
+  AccelGroupParserData *accel_data;
+  GSList *accel_groups;
+  GtkAccelGroup *accel_group;
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (GTK_IS_WIDGET (toplevel));
+  g_return_if_fail (user_data != NULL);
+
+  accel_data = (AccelGroupParserData*)user_data;
+  accel_groups = gtk_accel_groups_from_object (G_OBJECT (toplevel));
+  if (g_slist_length (accel_groups) == 0)
+    {
+      accel_group = gtk_accel_group_new ();
+      gtk_window_add_accel_group (GTK_WINDOW (toplevel), accel_group);
+    }
+  else
+    {
+      g_assert (g_slist_length (accel_groups) == 1);
+      accel_group = g_slist_nth_data (accel_groups, 0);
+    }
+
+  gtk_widget_add_accelerator (GTK_WIDGET (accel_data->object),
+                             accel_data->signal,
+                             accel_group,
+                             accel_data->key,
+                             accel_data->modifiers,
+                             GTK_ACCEL_VISIBLE);
+
+  g_object_unref (accel_data->object);
+  g_free (accel_data->signal);
+  g_slice_free (AccelGroupParserData, accel_data);
+}
+
 static void
 gtk_widget_buildable_custom_finished (GtkBuildable *buildable,
                                      GtkBuilder   *builder,
@@ -9813,8 +10280,6 @@ gtk_widget_buildable_custom_finished (GtkBuildable *buildable,
   AccelGroupParserData *accel_data;
   AccessibilitySubParserData *a11y_data;
   GtkWidget *toplevel;
-  GSList *accel_groups;
-  GtkAccelGroup *accel_group;
 
   if (strcmp (tagname, "accelerator") == 0)
     {
@@ -9822,26 +10287,8 @@ gtk_widget_buildable_custom_finished (GtkBuildable *buildable,
       g_assert (accel_data->object);
 
       toplevel = gtk_widget_get_toplevel (GTK_WIDGET (accel_data->object));
-      accel_groups = gtk_accel_groups_from_object (G_OBJECT (toplevel));
-      if (g_slist_length (accel_groups) == 0)
-       {
-         accel_group = gtk_accel_group_new ();
-         gtk_window_add_accel_group (GTK_WINDOW (toplevel), accel_group);
-       }
-      else
-       {
-         g_assert (g_slist_length (accel_groups) == 1);
-         accel_group = g_slist_nth_data (accel_groups, 0);
-       }
-      gtk_widget_add_accelerator (GTK_WIDGET (accel_data->object),
-                                 accel_data->signal,
-                                 accel_group,
-                                 accel_data->key,
-                                 accel_data->modifiers,
-                                 GTK_ACCEL_VISIBLE);
-      g_object_unref (accel_data->object);
-      g_free (accel_data->signal);
-      g_slice_free (AccelGroupParserData, accel_data);
+
+      _gtk_widget_buildable_finish_accelerator (GTK_WIDGET (buildable), toplevel, user_data);
     }
   else if (strcmp (tagname, "accessibility") == 0)
     {
@@ -10144,8 +10591,8 @@ gtk_widget_set_tooltip_window (GtkWidget *widget,
   has_tooltip = (custom_window != NULL || tooltip_markup != NULL);
   gtk_widget_real_set_has_tooltip (widget, has_tooltip, FALSE);
 
-  if (has_tooltip)
-    gtk_widget_trigger_tooltip_query (widget);
+  if (has_tooltip && GTK_WIDGET_VISIBLE (widget))
+    gtk_widget_queue_tooltip_query (widget);
 }
 
 /**
@@ -10184,6 +10631,36 @@ gtk_widget_trigger_tooltip_query (GtkWidget *widget)
   gtk_tooltip_trigger_tooltip_query (gtk_widget_get_display (widget));
 }
 
+static guint tooltip_query_id;
+static GSList *tooltip_query_displays;
+
+static gboolean
+tooltip_query_idle (gpointer data)
+{
+  g_slist_foreach (tooltip_query_displays, (GFunc)gtk_tooltip_trigger_tooltip_query, NULL);
+  g_slist_foreach (tooltip_query_displays, (GFunc)g_object_unref, NULL);
+  g_slist_free (tooltip_query_displays);
+
+  tooltip_query_displays = NULL;
+  tooltip_query_id = 0;
+
+  return FALSE;
+}
+
+static void
+gtk_widget_queue_tooltip_query (GtkWidget *widget)
+{
+  GdkDisplay *display;
+
+  display = gtk_widget_get_display (widget);
+
+  if (!g_slist_find (tooltip_query_displays, display))
+    tooltip_query_displays = g_slist_prepend (tooltip_query_displays, g_object_ref (display));
+
+  if (tooltip_query_id == 0)
+    tooltip_query_id = gdk_threads_add_idle (tooltip_query_idle, NULL);
+}
+
 /**
  * gtk_widget_set_tooltip_text:
  * @widget: a #GtkWidget
@@ -10319,6 +10796,76 @@ gtk_widget_get_has_tooltip (GtkWidget *widget)
   return has_tooltip;
 }
 
+/**
+ * gtk_widget_get_allocation:
+ * @widget: a #GtkWidget
+ * @allocation: a pointer to a #GtkAllocation to copy to
+ *
+ * Retrieves the widget's allocation.
+ *
+ * Since: 2.18
+ */
+void
+gtk_widget_get_allocation (GtkWidget     *widget,
+                           GtkAllocation *allocation)
+{
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (allocation != NULL);
+
+  *allocation = widget->allocation;
+}
+
+/**
+ * gtk_widget_set_allocation:
+ * @widget: a #GtkWidget
+ * @allocation: a pointer to a #GtkAllocation to copy from
+ *
+ * Sets the widget's allocation.  This should not be used
+ * directly, but from within a widget's size_allocate method.
+ *
+ * Since: 2.18
+ */
+void
+gtk_widget_set_allocation (GtkWidget           *widget,
+                           const GtkAllocation *allocation)
+{
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (allocation != NULL);
+
+  widget->allocation = *allocation;
+}
+
+/**
+ * gtk_widget_set_window:
+ * @widget: a #GtkWidget
+ * @window: a #GdkWindow
+ *
+ * Sets a widget's window. This function should only be used in a
+ * widget's GtkWidget::realize() implementation. The %window passed is
+ * usually either new window created with gdk_window_new(), or the
+ * window of its parent widget as returned by
+ * gtk_widget_get_parent_window().
+ *
+ * Widgets must indicate whether they will create their own #GdkWindow
+ * by calling gtk_widget_set_has_window(). This is usually done in the
+ * widget's init() function.
+ *
+ * Since: 2.18
+ */
+void
+gtk_widget_set_window (GtkWidget *widget,
+                       GdkWindow *window)
+{
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
+
+  if (widget->window != window)
+    {
+      widget->window = window;
+      g_object_notify (G_OBJECT (widget), "window");
+    }
+}
+
 /**
  * gtk_widget_get_window:
  * @widget: a #GtkWidget