From d67a7eda16d64ba44fa759530abd08147347bae6 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 2 Sep 2009 23:38:55 +0200 Subject: [PATCH] Add gdk_window_restack This lets you restack a window above or below a specified sibling. At least eclipse wants this functionallity. --- gdk/gdk.symbols | 1 + gdk/gdkwindow.c | 116 ++++++++++++++++++++++++++++++++++ gdk/gdkwindow.h | 3 + gdk/gdkwindowimpl.h | 3 + gdk/quartz/gdkwindow-quartz.c | 9 +++ gdk/win32/gdkwindow-win32.c | 9 +++ gdk/x11/gdkwindow-x11.c | 16 +++++ 7 files changed, 157 insertions(+) diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols index 7956390d25..e8c51093b2 100644 --- a/gdk/gdk.symbols +++ b/gdk/gdk.symbols @@ -651,6 +651,7 @@ gdk_window_get_events gdk_window_set_events gdk_window_raise gdk_window_lower +gdk_window_restack gdk_window_move gdk_window_resize gdk_window_move_resize diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index f9fb2adccc..bc0a5057d9 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -6448,6 +6448,122 @@ gdk_window_lower (GdkWindow *window) gdk_window_invalidate_in_parent (private); } +/** + * gdk_window_restack: + * @window: a #GdkWindow + * @sibling: a #GdkWindow that is a sibling of @window, or %NULL + * @above: a boolean + * + * Changes the position of @window in the Z-order (stacking order), so that + * it is above @sibling (if @above is %TRUE) or below @sibling (if @above is + * %FALSE). + * + * If @sibling is %NULL, then this either raises (if @above is %TRUE) or + * lowers the window. + * + * If @window is a toplevel, the window manager may choose to deny the + * request to move the window in the Z-order, gdk_window_restack() only + * requests the restack, does not guarantee it. + * + * Since: 2.18 + */ +void +gdk_window_restack (GdkWindow *window, + GdkWindow *sibling, + gboolean above) +{ + GdkWindowObject *private; + GdkWindowImplIface *impl_iface; + GdkWindowObject *parent; + GdkWindowObject *above_native; + GList *sibling_link; + GList *native_children; + GList *l, listhead; + + g_return_if_fail (GDK_IS_WINDOW (window)); + g_return_if_fail (sibling == NULL || GDK_IS_WINDOW (sibling)); + + private = (GdkWindowObject *) window; + if (private->destroyed) + return; + + if (sibling == NULL) + { + if (above) + gdk_window_raise (window); + else + gdk_window_lower (window); + return; + } + + if (gdk_window_is_toplevel (private)) + { + g_return_if_fail (gdk_window_is_toplevel (sibling)); + impl_iface->restack_toplevel (window, sibling, above); + return; + } + + parent = private->parent; + if (parent) + { + sibling_link = g_list_find (parent->children, sibling); + g_return_if_fail (sibling_link != NULL); + if (sibling_link == NULL) + return; + + parent->children = g_list_remove (parent->children, window); + if (above) + parent->children = g_list_insert_before (parent->children, + sibling_link, + window); + else + parent->children = g_list_insert_before (parent->children, + sibling_link->next, + window); + + impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl); + if (gdk_window_has_impl (private)) + { + above_native = find_native_sibling_above (parent, private); + if (above_native) + { + listhead.data = window; + listhead.next = NULL; + listhead.prev = NULL; + impl_iface->restack_under ((GdkWindow *)above_native, &listhead); + } + else + impl_iface->raise (window); + } + else + { + native_children = NULL; + get_all_native_children (private, &native_children); + if (native_children != NULL) + { + above_native = find_native_sibling_above (parent, private); + if (above_native) + impl_iface->restack_under ((GdkWindow *)above_native, + native_children); + else + { + /* Right order, since native_children is bottom-topmost first */ + for (l = native_children; l != NULL; l = l->next) + impl_iface->raise (l->data); + } + + g_list_free (native_children); + } + } + } + + recompute_visible_regions (private, TRUE, FALSE); + + _gdk_synthesize_crossing_events_for_geometry_change (window); + gdk_window_invalidate_in_parent (private); +} + + /** * gdk_window_show: * @window: a #GdkWindow diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h index a3297d24ad..bea3ca9789 100644 --- a/gdk/gdkwindow.h +++ b/gdk/gdkwindow.h @@ -364,6 +364,9 @@ void gdk_window_clear_area_e (GdkWindow *window, gint height); void gdk_window_raise (GdkWindow *window); void gdk_window_lower (GdkWindow *window); +void gdk_window_restack (GdkWindow *window, + GdkWindow *sibling, + gboolean above); void gdk_window_focus (GdkWindow *window, guint32 timestamp); void gdk_window_set_user_data (GdkWindow *window, diff --git a/gdk/gdkwindowimpl.h b/gdk/gdkwindowimpl.h index b8de4744d1..00f2f1b13d 100644 --- a/gdk/gdkwindowimpl.h +++ b/gdk/gdkwindowimpl.h @@ -51,6 +51,9 @@ struct _GdkWindowImplIface void (* lower) (GdkWindow *window); void (* restack_under) (GdkWindow *window, GList *native_siblings); + void (* restack_toplevel) (GdkWindow *window, + GdkWindow *sibling, + gboolean above); void (* move_resize) (GdkWindow *window, gboolean with_move, diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c index 43f93f9b5c..6b8373b2b9 100644 --- a/gdk/quartz/gdkwindow-quartz.c +++ b/gdk/quartz/gdkwindow-quartz.c @@ -1541,6 +1541,14 @@ gdk_window_quartz_lower (GdkWindow *window) } } +static void +gdk_window_quartz_restack_toplevel (GdkWindow *window, + GdkWindow *sibling, + gboolean above) +{ + /* FIXME: Implement this */ +} + static void gdk_window_quartz_set_background (GdkWindow *window, const GdkColor *color) @@ -2907,6 +2915,7 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface) iface->get_events = gdk_window_quartz_get_events; iface->raise = gdk_window_quartz_raise; iface->lower = gdk_window_quartz_lower; + iface->restack_toplevel = gdk_window_quartz_restack_toplevel; iface->move_resize = gdk_window_quartz_move_resize; iface->set_background = gdk_window_quartz_set_background; iface->set_back_pixmap = gdk_window_quartz_set_back_pixmap; diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c index a849e260a8..c94563165c 100644 --- a/gdk/win32/gdkwindow-win32.c +++ b/gdk/win32/gdkwindow-win32.c @@ -2092,6 +2092,14 @@ gdk_win32_window_restack_under (GdkWindow *window, // ### TODO } +static void +gdk_win32_window_restack_toplevel (GdkWindow *window, + GdkWindow *sibling, + gboolean above) +{ + // ### TODO +} + void gdk_window_get_root_origin (GdkWindow *window, gint *x, @@ -3634,6 +3642,7 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface) iface->raise = gdk_win32_window_raise; iface->lower = gdk_win32_window_lower; iface->restack_under = gdk_win32_window_restack_under; + iface->restack_toplevel = gdk_win32_window_restack_toplevel; iface->move_resize = gdk_win32_window_move_resize; iface->set_background = gdk_win32_window_set_background; iface->set_back_pixmap = gdk_win32_window_set_back_pixmap; diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 1682151bb1..82ce213336 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -1715,6 +1715,21 @@ gdk_window_x11_restack_under (GdkWindow *window, g_free (windows); } +static void +gdk_window_x11_restack_toplevel (GdkWindow *window, + GdkWindow *sibling, + gboolean above) +{ + XWindowChanges changes; + + changes.sibling = GDK_WINDOW_XID (sibling); + changes.stack_mode = above ? Above : Below; + XReconfigureWMWindow (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + GDK_WINDOW_SCREEN (window), + CWStackMode | CWSibling, &changes); +} + static void gdk_window_x11_lower (GdkWindow *window) { @@ -5562,6 +5577,7 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface) iface->raise = gdk_window_x11_raise; iface->lower = gdk_window_x11_lower; iface->restack_under = gdk_window_x11_restack_under; + iface->restack_toplevel = gdk_window_x11_restack_toplevel; iface->move_resize = gdk_window_x11_move_resize; iface->set_background = gdk_window_x11_set_background; iface->set_back_pixmap = gdk_window_x11_set_back_pixmap;