[gtk+/toplevel-embedding: 9/12] Fixed GtkWindow/GtkWidget to properly emit hierarchy changed for embedded toplevels
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/toplevel-embedding: 9/12] Fixed GtkWindow/GtkWidget to properly emit hierarchy changed for embedded toplevels
- Date: Wed, 29 Dec 2010 09:17:15 +0000 (UTC)
commit 460be460ec99823fc2e76fd9bd769b5cbdea103f
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date: Sun Dec 26 19:08:33 2010 +0900
Fixed GtkWindow/GtkWidget to properly emit hierarchy changed for embedded toplevels
Now GtkWindow takes some measures when setting toplevelness:
- When a window becomes toplevel after being embedded it saves
the visibility state and reshow's itself so that the window
re-realizes and presents itself again automatically
- When emitting hierarchy-changed, synthetically mark the toplevel
as not anchored, this allows the hierarchy changed propagation to
recurse properly.
GtkWidget also takes care to unset the parent window *after* unparenting
the widget and after emitting the heirarhcy changed that leaves a NULL
toplevel.
That means there are now 2 cycles of "hierarchy-changed" when removing
an embedded toplevel from a parent, first one that makes the new toplevel
a NULL one (since the toplevel flag is not yet restored), the second cycle
makes the removed window toplevel again when setting the parent window
to NULL.
gtk/gtkwidget.c | 27 ++++++++++++++-------------
gtk/gtkwindow.c | 36 ++++++++++++++++++++++++++++++++++--
2 files changed, 48 insertions(+), 15 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 3a2c0b8..d90f987 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -3719,14 +3719,6 @@ gtk_widget_unparent (GtkWidget *widget)
if (gtk_container_get_focus_child (GTK_CONTAINER (priv->parent)) == widget)
gtk_container_set_focus_child (GTK_CONTAINER (priv->parent), NULL);
- /* If we are unanchoring the child, we save around the toplevel
- * to emit hierarchy changed
- */
- if (priv->parent->priv->anchored)
- g_object_ref (toplevel);
- else
- toplevel = NULL;
-
gtk_widget_queue_draw_child (widget);
/* Reset the width and height here, to force reallocation if we
@@ -3745,11 +3737,13 @@ gtk_widget_unparent (GtkWidget *widget)
gtk_widget_unrealize (widget);
}
- /* Need to unset the parent window early, this can result in
- * an additional "hierarchy-changed" propagation if we are removing
- * a parented GtkWindow from the hierarchy.
+ /* If we are unanchoring the child, we save around the toplevel
+ * to emit hierarchy changed
*/
- gtk_widget_set_parent_window (widget, NULL);
+ if (priv->parent->priv->anchored)
+ g_object_ref (toplevel);
+ else
+ toplevel = NULL;
/* Removing a widget from a container restores the child visible
* flag to the default state, so it doesn't affect the child
@@ -3773,12 +3767,19 @@ gtk_widget_unparent (GtkWidget *widget)
}
g_signal_emit (widget, widget_signals[PARENT_SET], 0, old_parent);
- if (toplevel && gtk_widget_is_toplevel (toplevel))
+ if (toplevel)
{
_gtk_widget_propagate_hierarchy_changed (widget, toplevel);
g_object_unref (toplevel);
}
+ /* Now that the parent pointer is nullified and the hierarchy-changed
+ * already passed, go ahead and unset the parent window, if we are unparenting
+ * an embeded GtkWindow the window will become toplevel again and hierarchy-changed
+ * will fire again for the new subhierarchy.
+ */
+ gtk_widget_set_parent_window (widget, NULL);
+
g_object_notify (G_OBJECT (widget), "parent");
g_object_thaw_notify (G_OBJECT (widget));
if (!priv->parent)
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index f52da2d..0068ea9 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -9232,6 +9232,7 @@ _gtk_window_set_is_toplevel (GtkWindow *window,
{
GtkWidget *widget;
GtkWidget *toplevel;
+ gboolean was_anchored;
widget = GTK_WIDGET (window);
@@ -9243,16 +9244,47 @@ _gtk_window_set_is_toplevel (GtkWindow *window,
if (is_toplevel == gtk_widget_is_toplevel (widget))
return;
+ was_anchored = _gtk_widget_get_anchored (widget);
+
if (is_toplevel)
{
+ gboolean was_visible = gtk_widget_get_visible (widget);
+
+ /* Pass through regular pathways of an embedded toplevel
+ * to go through unmapping and hiding the widget before
+ * becomming a toplevel again.
+ */
+ if (was_visible)
+ gtk_widget_hide (widget);
+
+ /* Save the toplevel this widget was previously anchored into before
+ * propagating a hierarchy-changed.
+ *
+ * Usually this happens by way of gtk_widget_unparent() and we are
+ * already unanchored at this point, just adding this clause incase
+ * things happen differently.
+ */
toplevel = gtk_widget_get_toplevel (widget);
- if (!gtk_widget_is_toplevel (toplevel))
+ if (!gtk_widget_is_toplevel (widget))
toplevel = NULL;
+ _gtk_widget_set_is_toplevel (widget, TRUE);
+
+ /* When a window becomes toplevel after being embedded and anchored
+ * into another window we need to unset it's anchored flag so that
+ * the hierarchy changed signal kicks in properly.
+ */
+ _gtk_widget_set_anchored (widget, FALSE);
_gtk_widget_propagate_hierarchy_changed (widget, toplevel);
- _gtk_widget_set_is_toplevel (widget, TRUE);
toplevel_list = g_slist_prepend (toplevel_list, window);
+
+ /* If an embedded toplevel gets removed from the hierarchy
+ * and is still in a visible state, we need to show it again
+ * so it will be realized as a real toplevel again.
+ */
+ if (was_visible)
+ gtk_widget_show (widget);
}
else
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]