[gtk+/client-side-windows: 88/284] Fix up gdk_window_raise and native window creation to not move native window above windows outside t



commit 28c4518cca97ec238cfc3c882678e9ebd165804a
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Jan 19 13:07:02 2009 +0100

    Fix up gdk_window_raise and native window creation to not move native window above windows outside the non-native parent
---
 gdk/gdkwindow.c |  136 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 133 insertions(+), 3 deletions(-)

diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index b7125bf..c2f4709 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -685,6 +685,46 @@ _gdk_window_update_size (GdkWindow *window)
   recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
 }
 
+/* Find the native window that would be just above "child"
+ * in the native stacking order if "child" was a native window
+ * (it doesn't have to be native). If there is no such native
+ * window inside this native parent then NULL is returned.
+ * If child is NULL, find lowest native window in parent.
+ */
+static GdkWindowObject *
+find_native_sibling_above (GdkWindowObject *parent,
+			   GdkWindowObject *child)
+{
+  GdkWindowObject *w;
+  GList *l;
+
+  if (child)
+    {
+      l = g_list_find (parent->children, child);
+      g_assert (l != NULL); /* Better be a child of its parent... */
+      l = l->prev; /* Start looking at the one above the child */
+    }
+  else
+    l = g_list_last (parent->children);
+
+  for (; l != NULL; l = l->prev)
+    {
+      w = l->data;
+	
+      if (gdk_window_has_impl (w))
+	return w;
+      
+      w = find_native_sibling_above (w, NULL);
+      if (w)
+	return w;
+    }
+
+  if (gdk_window_has_impl (parent))
+    return NULL;
+  else
+    return find_native_sibling_above (parent->parent, parent);
+}
+
 static GdkEventMask
 get_native_event_mask (GdkWindowObject *private)
 {
@@ -701,7 +741,6 @@ get_native_event_mask (GdkWindowObject *private)
     return GDK_EXPOSURE_MASK;
 }
 
-
 /**
  * gdk_window_new:
  * @parent: a #GdkWindow, or %NULL to create the window as a child of
@@ -864,10 +903,24 @@ gdk_window_new (GdkWindow     *parent,
     }
   else if (native)
     {
+      GdkWindowObject *above;
+      GList listhead = {0};
+      
       event_mask = get_native_event_mask (private);
       
       /* Create the impl */
       _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
+
+      /* This will put the native window topmost in the native parent, which may
+       * be wrong wrt other native windows in the non-native hierarchy, so restack */
+      above = find_native_sibling_above (private->parent, private);
+      if (above)
+	{
+	  listhead.data = window;
+	  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+								    &listhead);
+	}
+      
     }
   else
     {
@@ -1138,6 +1191,8 @@ gdk_window_set_has_native (GdkWindow *window, gboolean has_native)
   GdkScreen *screen;
   GdkVisual *visual;
   GdkWindowAttr attributes;
+  GdkWindowObject *above;
+  GList listhead;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -1173,6 +1228,19 @@ gdk_window_set_has_native (GdkWindow *window, gboolean has_native)
       private->impl = old_impl;
       change_impl (private, new_impl);
       
+      /* Native window creation will put the native window topmost in the
+       * native parent, which may be wrong wrt other native windows in the
+       * non-native hierarchy, so restack */
+      above = find_native_sibling_above (private->parent, private);
+      if (above)
+	{
+	  listhead.data = window;
+	  listhead.prev = NULL;
+	  listhead.next = NULL;
+	  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+								    &listhead);
+	}
+
       recompute_visible_regions (private, FALSE, FALSE);
 
       reparent_to_impl (private);
@@ -5167,11 +5235,33 @@ gdk_window_foreign_new (GdkNativeWindow anid)
   return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
 }
 
+static void
+get_all_native_children (GdkWindowObject *private,
+			 GList **native)
+{
+  GdkWindowObject *child;
+  GList *l;
+  
+  for (l = private->children; l != NULL; l = l->next)
+    {
+      child = l->data;
+
+      if (gdk_window_has_impl (child))
+	*native = g_list_prepend (*native, child);
+      else
+	get_all_native_children (child, native);
+    }
+}
+
+
 static inline void
 gdk_window_raise_internal (GdkWindow *window)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowObject *parent = private->parent;
+  GdkWindowObject *above;
+  GList *native_children;
+  GList *l, listhead;
 
   if (parent)
     {
@@ -5179,8 +5269,48 @@ gdk_window_raise_internal (GdkWindow *window)
       parent->children = g_list_prepend (parent->children, window);
     }
 
-  if (gdk_window_has_impl (private))
-    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
+  /* Just do native raise for toplevels */
+  if (private->parent == NULL ||
+      GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+    {
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
+    }
+  else if (gdk_window_has_impl (private))
+    {
+      above = find_native_sibling_above (parent, private);
+      if (above)
+	{
+	  listhead.data = window;
+	  listhead.next = NULL;
+	  listhead.prev = NULL;
+	  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+								    &listhead);
+	}
+      else
+	GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
+    }
+  else
+    {
+      native_children = NULL;
+      get_all_native_children (private, &native_children);
+      if (native_children != NULL)
+	{
+	  above = find_native_sibling_above (parent, private);
+
+	  if (above)
+	    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+								      native_children);
+	  else
+	    {
+	      /* Right order, since native_chilren is bottom-opmost first */
+	      for (l = native_children; l != NULL; l = l->next)
+		GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
+	    }
+	  
+	  g_list_free (native_children);
+	}
+      
+    }
 }
 
 static void



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]