[gtk+] gdk: add API to convert coords between parent and child windows



commit 5a52d2a2f09c1999488190d935339e75dbe44c48
Author: Michael Natterer <mitch gimp org>
Date:   Thu Apr 15 12:59:44 2010 +0200

    gdk: add API to convert coords between parent and child windows
    
    which also works for offscreen windows and their embedder.
    Also add gdk_window_get_effective_parent() and
    gdk_window_get_effective_toplevel() which are offscreen aware.

 gdk/gdk.symbols |    4 +
 gdk/gdkwindow.c |  239 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 gdk/gdkwindow.h |   13 +++
 3 files changed, 237 insertions(+), 19 deletions(-)
---
diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols
index 548a063..bb6e2b2 100644
--- a/gdk/gdk.symbols
+++ b/gdk/gdk.symbols
@@ -685,6 +685,8 @@ gdk_window_clear
 gdk_window_clear_area
 gdk_window_clear_area_e
 gdk_window_constrain_size
+gdk_window_coords_from_parent
+gdk_window_coords_to_parent
 gdk_window_destroy
 gdk_window_end_paint
 gdk_window_flush
@@ -694,10 +696,12 @@ gdk_window_freeze_updates
 gdk_window_get_children
 gdk_window_get_internal_paint_info
 gdk_window_get_parent
+gdk_window_get_effective_parent
 gdk_window_get_pointer
 gdk_window_get_position
 gdk_window_get_state
 gdk_window_get_toplevel
+gdk_window_get_effective_toplevel
 #ifndef GDK_DISABLE_DEPRECATED
 gdk_window_get_toplevels
 #endif
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 5c9219d..37abea7 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -2237,6 +2237,30 @@ gdk_window_is_destroyed (GdkWindow *window)
   return GDK_WINDOW_DESTROYED (window);
 }
 
+static void
+to_embedder (GdkWindowObject *window,
+             gdouble          offscreen_x,
+             gdouble          offscreen_y,
+             gdouble         *embedder_x,
+             gdouble         *embedder_y)
+{
+  g_signal_emit (window, signals[TO_EMBEDDER], 0,
+                 offscreen_x, offscreen_y,
+                 embedder_x, embedder_y);
+}
+
+static void
+from_embedder (GdkWindowObject *window,
+               gdouble          embedder_x,
+               gdouble          embedder_y,
+               gdouble         *offscreen_x,
+               gdouble         *offscreen_y)
+{
+  g_signal_emit (window, signals[FROM_EMBEDDER], 0,
+                 embedder_x, embedder_y,
+                 offscreen_x, offscreen_y);
+}
+
 /**
  * gdk_window_get_position:
  * @window: a #GdkWindow
@@ -2280,6 +2304,11 @@ gdk_window_get_position (GdkWindow *window,
  * matter for toplevel windows, because the window manager may choose
  * to reparent them.
  *
+ * Note that you should use gdk_window_get_effective_parent() when
+ * writing generic code that walks up a window hierarchy, because
+ * gdk_window_get_parent() will most likely not do what you expect if
+ * there are offscreen windows in the hierarchy.
+ *
  * Return value: parent of @window
  **/
 GdkWindow*
@@ -2291,6 +2320,35 @@ gdk_window_get_parent (GdkWindow *window)
 }
 
 /**
+ * gdk_window_get_effective_parent:
+ * @window: a #GdkWindow
+ *
+ * Obtains the parent of @window, as known to GDK. Works like
+ * gdk_window_get_parent() for normal windows, but returns the
+ * window's embedder for offscreen windows.
+ *
+ * See also: gdk_offscreen_window_get_embedder()
+ *
+ * Return value: effective parent of @window
+ *
+ * Since: 2.22
+ **/
+GdkWindow *
+gdk_window_get_effective_parent (GdkWindow *window)
+{
+  GdkWindowObject *obj;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+  obj = (GdkWindowObject *)window;
+
+  if (obj->window_type == GDK_WINDOW_OFFSCREEN)
+    return gdk_offscreen_window_get_embedder (window);
+  else
+    return (GdkWindow *) obj->parent;
+}
+
+/**
  * gdk_window_get_toplevel:
  * @window: a #GdkWindow
  *
@@ -2300,9 +2358,14 @@ gdk_window_get_parent (GdkWindow *window)
  * toplevel window, as is a %GDK_WINDOW_CHILD window that
  * has a root window as parent.
  *
+ * Note that you should use gdk_window_get_effective_toplevel() when
+ * you want to get to a window's toplevel as seen on screen, because
+ * gdk_window_get_toplevel() will most likely not do what you expect
+ * if there are offscreen windows in the hierarchy.
+ *
  * Return value: the toplevel window containing @window
  **/
-GdkWindow*
+GdkWindow *
 gdk_window_get_toplevel (GdkWindow *window)
 {
   GdkWindowObject *obj;
@@ -2322,6 +2385,35 @@ gdk_window_get_toplevel (GdkWindow *window)
 }
 
 /**
+ * gdk_window_get_effective_toplevel:
+ * @window: a #GdkWindow
+ *
+ * Gets the toplevel window that's an ancestor of @window.
+ *
+ * Works like gdk_window_get_toplevel(), but treats an offscreen window's
+ * embedder as its parent, using gdk_window_get_effective_parent().
+ *
+ * See also: gdk_offscreen_window_get_embedder()
+ *
+ * Return value: the effective toplevel window containing @window
+ *
+ * Since: 2.22
+ **/
+GdkWindow *
+gdk_window_get_effective_toplevel (GdkWindow *window)
+{
+  GdkWindow *parent;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+  while ((parent = gdk_window_get_effective_parent (window)) != NULL &&
+	 (gdk_window_get_window_type (parent) != GDK_WINDOW_ROOT))
+    window = parent;
+
+  return window;
+}
+
+/**
  * gdk_window_get_children:
  * @window: a #GdkWindow
  *
@@ -7977,10 +8069,10 @@ gdk_window_get_geometry (GdkWindow *window,
 	}
       else
 	{
-	  if (x)
-	    *x = private->x;
-	  if (y)
-	    *y = private->y;
+          if (x)
+            *x = private->x;
+          if (y)
+            *y = private->y;
 	  if (width)
 	    *width = private->width;
 	  if (height)
@@ -8079,6 +8171,129 @@ gdk_window_get_root_coords (GdkWindow *window,
 			       root_x, root_y);
 }
 
+/**
+ * gdk_window_coords_to_parent:
+ * @window: a child window
+ * @x: X coordinate in child's coordinate system
+ * @y: Y coordinate in child's coordinate system
+ * @parent_x: return location for X coordinate in parent's coordinate system
+ * @parent_y: return location for Y coordinate in parent's coordinate system
+ *
+ * Transforms window coordinates from a child window to its parent
+ * window, where the parent window is the normal parent as returned by
+ * gdk_window_get_parent() for normal windows, and the window's
+ * embedder as returned by gdk_offscreen_window_get_embedder() for
+ * offscreen windows.
+ *
+ * For normal windows, calling this function is equivalent to adding
+ * the return values of gdk_window_get_position() to the child coordinates.
+ * For offscreen windows however (which can be arbitrarily transformed),
+ * this function calls the GdkWindow::to-embedder: signal to translate
+ * the coordinates.
+ *
+ * You should always use this function when writing generic code that
+ * walks up a window hierarchy.
+ *
+ * See also: gdk_window_coords_from_parent()
+ *
+ * Since: 2.22
+ **/
+void
+gdk_window_coords_to_parent (GdkWindow *window,
+                             gdouble    x,
+                             gdouble    y,
+                             gdouble   *parent_x,
+                             gdouble   *parent_y)
+{
+  GdkWindowObject *obj;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  obj = (GdkWindowObject *) window;
+
+  if (obj->window_type == GDK_WINDOW_OFFSCREEN)
+    {
+      gdouble px, py;
+
+      to_embedder (obj, x, y, &px, &py);
+
+      if (parent_x)
+        *parent_x = px;
+
+      if (parent_y)
+        *parent_y = py;
+    }
+  else
+    {
+      if (parent_x)
+        *parent_x = x + obj->x;
+
+      if (parent_y)
+        *parent_y = y + obj->y;
+    }
+}
+
+/**
+ * gdk_window_coords_from_parent:
+ * @window: a child window
+ * @parent_x: X coordinate in parent's coordinate system
+ * @parent_y: Y coordinate in parent's coordinate system
+ * @x: return location for X coordinate in child's coordinate system
+ * @y: return location for Y coordinate in child's coordinate system
+ *
+ * Transforms window coordinates from a parent window to a child
+ * window, where the parent window is the normal parent as returned by
+ * gdk_window_get_parent() for normal windows, and the window's
+ * embedder as returned by gdk_offscreen_window_get_embedder() for
+ * offscreen windows.
+ *
+ * For normal windows, calling this function is equivalent to subtracting
+ * the return values of gdk_window_get_position() from the parent coordinates.
+ * For offscreen windows however (which can be arbitrarily transformed),
+ * this function calls the GdkWindow::from-embedder: signal to translate
+ * the coordinates.
+ *
+ * You should always use this function when writing generic code that
+ * walks down a window hierarchy.
+ *
+ * See also: gdk_window_coords_to_parent()
+ *
+ * Since: 2.22
+ **/
+void
+gdk_window_coords_from_parent (GdkWindow *window,
+                               gdouble    parent_x,
+                               gdouble    parent_y,
+                               gdouble   *x,
+                               gdouble   *y)
+{
+  GdkWindowObject *obj;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  obj = (GdkWindowObject *) window;
+
+  if (obj->window_type == GDK_WINDOW_OFFSCREEN)
+    {
+      gdouble cx, cy;
+
+      from_embedder (obj, parent_x, parent_y, &cx, &cy);
+
+      if (x)
+        *x = cx;
+
+      if (y)
+        *y = cy;
+    }
+  else
+    {
+      if (x)
+        *x = parent_x - obj->x;
+
+      if (y)
+        *y = parent_y - obj->y;
+    }
+}
 
 /**
  * gdk_window_get_deskrelative_origin:
@@ -8970,20 +9185,6 @@ update_cursor (GdkDisplay *display)
 }
 
 static void
-from_embedder (GdkWindowObject *window,
-	       gdouble          embedder_x,
-               gdouble          embedder_y,
-	       gdouble         *offscreen_x,
-               gdouble         *offscreen_y)
-{
-  g_signal_emit (window,
-		 signals[FROM_EMBEDDER], 0,
-		 embedder_x, embedder_y,
-		 offscreen_x, offscreen_y,
-		 NULL);
-}
-
-static void
 convert_coords_to_child (GdkWindowObject *child,
 			 gdouble          x,
                          gdouble          y,
diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h
index 1a42ed5..2402078 100644
--- a/gdk/gdkwindow.h
+++ b/gdk/gdkwindow.h
@@ -546,6 +546,16 @@ void	      gdk_window_get_root_coords (GdkWindow	  *window,
 					  gint             y,
 					  gint		  *root_x,
 					  gint		  *root_y);
+void       gdk_window_coords_to_parent   (GdkWindow       *window,
+                                          gdouble          x,
+                                          gdouble          y,
+                                          gdouble         *parent_x,
+                                          gdouble         *parent_y);
+void       gdk_window_coords_from_parent (GdkWindow       *window,
+                                          gdouble          parent_x,
+                                          gdouble          parent_y,
+                                          gdouble         *x,
+                                          gdouble         *y);
 
 #if !defined (GDK_DISABLE_DEPRECATED) || defined (GTK_COMPILATION) || defined (GDK_COMPILATION)
 /* Used by gtk_handle_box_button_changed () */
@@ -566,6 +576,9 @@ GdkWindow*    gdk_window_get_pointer	 (GdkWindow	  *window,
 GdkWindow *   gdk_window_get_parent      (GdkWindow       *window);
 GdkWindow *   gdk_window_get_toplevel    (GdkWindow       *window);
 
+GdkWindow *   gdk_window_get_effective_parent   (GdkWindow *window);
+GdkWindow *   gdk_window_get_effective_toplevel (GdkWindow *window);
+
 GList *	      gdk_window_get_children	 (GdkWindow	  *window);
 GList *       gdk_window_peek_children   (GdkWindow       *window);
 GdkEventMask  gdk_window_get_events	 (GdkWindow	  *window);



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