[gtk+/toplevel-embedding: 1/12] Allow GtkWindow to be parented if gtk_widget_set_parent_window() is called on one
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/toplevel-embedding: 1/12] Allow GtkWindow to be parented if gtk_widget_set_parent_window() is called on one
- Date: Wed, 29 Dec 2010 08:15:36 +0000 (UTC)
commit 0cc3789194aab88ada4a50541f66b598dfe2163e
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date: Thu Dec 23 21:51:25 2010 +0900
Allow GtkWindow to be parented if gtk_widget_set_parent_window() is called on one
This patch makes gtk_widget_set_parent_window() undo the toplevelness
of a GtkWindow, GtkWindow then realizes itself as a normal child widget
and behaves like a normal GtkBin by checking gtk_widget_is_toplevel() in
several places (show/hide/map/unmap/draw/size_allocate/check_resize/configure_event).
gtk/gtkwidget.c | 11 ++++
gtk/gtkwindow.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 147 insertions(+), 19 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 1876597..9d7f253 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -8633,6 +8633,7 @@ gtk_widget_get_default_style (void)
}
#ifdef G_ENABLE_DEBUG
+
/* Verify invariants, see docs/widget_system.txt for notes on much of
* this. Invariants may be temporarily broken while we're in the
* process of updating state, of course, so you can only
@@ -9083,6 +9084,16 @@ gtk_widget_set_parent_window (GtkWidget *widget,
g_object_unref (old_parent_window);
if (parent_window)
g_object_ref (parent_window);
+
+ /* Unset toplevel flag when adding a parent window to a widget,
+ * this is the primary entry point to allow toplevels to be
+ * embeddable.
+ */
+ if (GTK_IS_WINDOW (widget))
+ {
+ _gtk_window_set_is_toplevel (GTK_WINDOW (widget), FALSE);
+ gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
+ }
}
}
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 78a2a62..1474940 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -4584,6 +4584,12 @@ gtk_window_show (GtkWidget *widget)
GtkContainer *container = GTK_CONTAINER (window);
gboolean need_resize;
+ if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
+ {
+ GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
+ return;
+ }
+
_gtk_widget_set_visible_flag (widget, TRUE);
need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
@@ -4661,6 +4667,12 @@ gtk_window_hide (GtkWidget *widget)
GtkWindow *window = GTK_WINDOW (widget);
GtkWindowPrivate *priv = window->priv;
+ if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
+ {
+ GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
+ return;
+ }
+
_gtk_widget_set_visible_flag (widget, FALSE);
gtk_widget_unmap (widget);
@@ -4680,6 +4692,12 @@ gtk_window_map (GtkWidget *widget)
gdk_window = gtk_widget_get_window (widget);
+ if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
+ {
+ GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
+ return;
+ }
+
gtk_widget_set_mapped (widget, TRUE);
child = gtk_bin_get_child (&(window->bin));
@@ -4790,6 +4808,12 @@ gtk_window_unmap (GtkWidget *widget)
GdkWindow *gdk_window;
GdkWindowState state;
+ if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
+ {
+ GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
+ return;
+ }
+
gdk_window = gtk_widget_get_window (widget);
gtk_widget_set_mapped (widget, FALSE);
@@ -4840,6 +4864,35 @@ gtk_window_realize (GtkWidget *widget)
gtk_widget_get_allocation (widget, &allocation);
+ if (gtk_widget_get_parent_window (widget))
+ {
+ gtk_widget_set_realized (widget, TRUE);
+
+ attributes.x = allocation.x;
+ attributes.y = allocation.y;
+ attributes.width = allocation.width;
+ attributes.height = allocation.height;
+ attributes.window_type = GDK_WINDOW_CHILD;
+
+ attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
+
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.wclass = GDK_INPUT_OUTPUT;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
+
+ gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
+ gtk_widget_set_window (widget, gdk_window);
+ gdk_window_set_user_data (gdk_window, widget);
+
+ gtk_widget_style_attach (widget);
+ gtk_style_set_background (gtk_widget_get_style (widget), gdk_window, GTK_STATE_NORMAL);
+
+ gdk_window_enable_synchronized_configure (gdk_window);
+ return;
+ }
+
/* ensure widget tree is properly size allocated */
if (allocation.x == -1 &&
allocation.y == -1 &&
@@ -4923,6 +4976,7 @@ gtk_window_realize (GtkWidget *widget)
gtk_style_context_set_background (context, gdk_window);
+
if (priv->transient_parent &&
gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
gdk_window_set_transient_for (gdk_window,
@@ -4930,48 +4984,48 @@ gtk_window_realize (GtkWidget *widget)
if (priv->wm_role)
gdk_window_set_role (gdk_window, priv->wm_role);
-
+
if (!priv->decorated)
gdk_window_set_decorations (gdk_window, 0);
-
+
if (!priv->deletable)
gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
-
+
if (gtk_window_get_skip_pager_hint (window))
gdk_window_set_skip_pager_hint (gdk_window, TRUE);
-
+
if (gtk_window_get_skip_taskbar_hint (window))
gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
-
+
if (gtk_window_get_accept_focus (window))
gdk_window_set_accept_focus (gdk_window, TRUE);
else
gdk_window_set_accept_focus (gdk_window, FALSE);
-
+
if (gtk_window_get_focus_on_map (window))
gdk_window_set_focus_on_map (gdk_window, TRUE);
else
gdk_window_set_focus_on_map (gdk_window, FALSE);
-
+
if (priv->modal)
gdk_window_set_modal_hint (gdk_window, TRUE);
else
gdk_window_set_modal_hint (gdk_window, FALSE);
-
+
if (priv->startup_id)
{
#ifdef GDK_WINDOWING_X11
guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
if (timestamp != GDK_CURRENT_TIME)
- gdk_x11_window_set_user_time (gdk_window, timestamp);
+ gdk_x11_window_set_user_time (gdk_window, timestamp);
#endif
if (!startup_id_is_fake (priv->startup_id))
- gdk_window_set_startup_id (gdk_window, priv->startup_id);
+ gdk_window_set_startup_id (gdk_window, priv->startup_id);
}
-
+
/* Icons */
gtk_window_realize_icon (window);
-
+
if (priv->has_resize_grip)
resize_grip_create_window (window);
}
@@ -5180,6 +5234,29 @@ gtk_window_size_allocate (GtkWidget *widget,
gtk_widget_set_allocation (widget, allocation);
+ if (gtk_widget_get_realized (widget))
+ {
+ /* If it's not a toplevel we're embedded, we need to resize the window's
+ * window and skip the grip.
+ */
+ if (!gtk_widget_is_toplevel (widget))
+ {
+ gdk_window_move_resize (gtk_widget_get_window (widget),
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+ }
+ else
+ {
+ if (priv->frame)
+ gdk_window_resize (priv->frame,
+ allocation->width + priv->frame_left + priv->frame_right,
+ allocation->height + priv->frame_top + priv->frame_bottom);
+
+ update_grip_visibility (window);
+ set_grip_position (window);
+ }
+ }
+
child = gtk_bin_get_child (&(window->bin));
if (child && gtk_widget_get_visible (child))
{
@@ -5210,6 +5287,15 @@ gtk_window_configure_event (GtkWidget *widget,
GtkWindowPrivate *priv = window->priv;
gboolean expected_reply = priv->configure_request_count > 0;
+ if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
+ {
+ if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
+ return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
+
+ gdk_window_configure_finished (gtk_widget_get_window (widget));
+ return FALSE;
+ }
+
/* priv->configure_request_count incremented for each
* configure request, and decremented to a min of 0 for
* each configure notify.
@@ -5271,7 +5357,8 @@ static gboolean
gtk_window_state_event (GtkWidget *widget,
GdkEventWindowState *event)
{
- update_grip_visibility (GTK_WINDOW (widget));
+ if (gtk_widget_is_toplevel (GTK_WIDGET (widget)))
+ update_grip_visibility (GTK_WINDOW (widget));
return FALSE;
}
@@ -5282,9 +5369,12 @@ gtk_window_direction_changed (GtkWidget *widget,
{
GtkWindow *window = GTK_WINDOW (widget);
- set_grip_cursor (window);
- set_grip_position (window);
- set_grip_shape (window);
+ if (gtk_widget_is_toplevel (GTK_WIDGET (widget)))
+ {
+ set_grip_cursor (window);
+ set_grip_position (window);
+ set_grip_shape (window);
+ }
}
static void
@@ -5293,7 +5383,8 @@ gtk_window_state_changed (GtkWidget *widget,
{
GtkWindow *window = GTK_WINDOW (widget);
- update_grip_visibility (window);
+ if (gtk_widget_is_toplevel (GTK_WIDGET (widget)))
+ update_grip_visibility (window);
}
static void
@@ -5394,7 +5485,8 @@ gtk_window_set_has_resize_grip (GtkWindow *window,
priv->has_resize_grip = value;
gtk_widget_queue_draw (widget);
- if (gtk_widget_get_realized (widget))
+ if (gtk_widget_get_realized (widget) &&
+ gtk_widget_is_toplevel (GTK_WIDGET (widget)))
{
if (priv->has_resize_grip && priv->grip_window == NULL)
resize_grip_create_window (window);
@@ -5463,6 +5555,9 @@ gtk_window_resize_grip_is_visible (GtkWindow *window)
if (!priv->resizable)
return FALSE;
+ if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
+ return FALSE;
+
if (gtk_widget_get_realized (widget))
{
GdkWindowState state;
@@ -5883,7 +5978,11 @@ gtk_window_client_event (GtkWidget *widget,
static void
gtk_window_check_resize (GtkContainer *container)
{
- if (gtk_widget_get_visible (GTK_WIDGET (container)))
+ /* If the window is not toplevel anymore than it's embedded somewhere,
+ * so handle it like a normal window */
+ if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
+ GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
+ else if (gtk_widget_get_visible (GTK_WIDGET (container)))
gtk_window_move_resize (GTK_WINDOW (container));
}
@@ -6641,6 +6740,7 @@ gtk_window_move_resize (GtkWindow *window)
GtkWindowLastGeometryInfo saved_last_info;
widget = GTK_WIDGET (window);
+
gdk_window = gtk_widget_get_window (widget);
container = GTK_CONTAINER (widget);
info = gtk_window_get_geometry_info (window, TRUE);
@@ -7246,6 +7346,23 @@ gtk_window_draw (GtkWidget *widget,
GtkStyleContext *context;
gboolean ret = FALSE;
+ /* If the window is not toplevel anymore than it's embedded somewhere,
+ * so just chain up and paint the children */
+ if (!gtk_widget_is_toplevel (widget))
+ {
+ if (!gtk_widget_get_app_paintable (widget))
+ gtk_paint_flat_box (gtk_widget_get_style (widget),
+ cr,
+ gtk_widget_get_state (widget),
+ GTK_SHADOW_NONE,
+ widget, "window",
+ 0, 0,
+ gtk_widget_get_allocated_width (widget),
+ gtk_widget_get_allocated_height (widget));
+
+ return GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
+ }
+
context = gtk_widget_get_style_context (widget);
gtk_style_context_save (context);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]