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.
This commit is contained in:
		| @ -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 | ||||
|  | ||||
							
								
								
									
										239
									
								
								gdk/gdkwindow.c
									
									
									
									
									
								
							
							
						
						
									
										239
									
								
								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* | ||||
| @ -2290,6 +2319,35 @@ gdk_window_get_parent (GdkWindow *window) | ||||
|   return (GdkWindow*) ((GdkWindowObject*) window)->parent; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * 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; | ||||
| @ -2321,6 +2384,35 @@ gdk_window_get_toplevel (GdkWindow *window) | ||||
|   return GDK_WINDOW (obj); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * 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: | ||||
| @ -8969,20 +9184,6 @@ update_cursor (GdkDisplay *display) | ||||
|   impl_iface->set_cursor ((GdkWindow *)toplevel, cursor_window->cursor); | ||||
| } | ||||
|  | ||||
| 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, | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Michael Natterer
					Michael Natterer