[gtk+] Extend _gdk_windowing_window_at_pointer to be able to get toplevels only



commit 5ebb32d1ffa23241d562fb4d5be02bc6f156b515
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Sep 28 15:21:54 2009 +0200

    Extend _gdk_windowing_window_at_pointer to be able to get toplevels only
    
    This has two advantages:
    1) In many backends, this is faster as we can terminate the window
    hierarchy traversal earlier
    2) When used in gdkdisplay.c::get_current_toplevel() to get the
    current toplevel that has the pointer we now correctly return
    a toplevel with the pointer in it where the pointer is inside
    some foreign subwindow of a toplevel window.
    
    The second advantage fixes some bugs in client side event generation
    when the pointer is inside such a foreign child window.

 gdk/directfb/gdkwindow-directfb.c |   20 ++++++++++++++++++++
 gdk/gdkdisplay.c                  |   20 +++-----------------
 gdk/gdkinternals.h                |    3 ++-
 gdk/quartz/gdkwindow-quartz.c     |   23 ++++++++++++++++++++++-
 gdk/win32/gdkwindow-win32.c       |    8 +++++++-
 gdk/x11/gdkwindow-x11.c           |   11 ++++++++++-
 6 files changed, 64 insertions(+), 21 deletions(-)
---
diff --git a/gdk/directfb/gdkwindow-directfb.c b/gdk/directfb/gdkwindow-directfb.c
index 85859e7..c0ff8e1 100644
--- a/gdk/directfb/gdkwindow-directfb.c
+++ b/gdk/directfb/gdkwindow-directfb.c
@@ -2099,6 +2099,26 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
   if (win_y)
     *win_y = wy;
 
+  if (get_toplevel)
+    {
+      GdkWindowObject *w = (GdkWindowObject *)retval;
+      /* Requested toplevel, find it. */
+      /* TODO: This can be implemented more efficient by never
+	 recursing into children in the first place */
+      if (w)
+	{
+	  /* Convert to toplevel */
+	  while (w->parent != NULL &&
+		 w->parent->window_type != GDK_WINDOW_ROOT)
+	    {
+	      *win_x += w->x;
+	      *win_y += w->y;
+	      w = w->parent;
+	    }
+	  retval = (GdkWindow *)w;
+	}
+    }
+
   return retval;
 }
 
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index d22ff00..d020b16 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -510,7 +510,7 @@ gdk_display_real_get_window_at_pointer (GdkDisplay *display,
   GdkWindow *window;
   gint x, y;
 
-  window = _gdk_windowing_window_at_pointer (display, &x, &y, NULL);
+  window = _gdk_windowing_window_at_pointer (display, &x, &y, NULL, FALSE);
 
   /* This might need corrections, as the native window returned
      may contain client side children */
@@ -913,34 +913,20 @@ get_current_toplevel (GdkDisplay *display,
 		      GdkModifierType *state_out)
 {
   GdkWindow *pointer_window;
-  GdkWindowObject *w;
   int x, y;
   GdkModifierType state;
 
-  pointer_window = _gdk_windowing_window_at_pointer (display,  &x, &y, &state);
+  pointer_window = _gdk_windowing_window_at_pointer (display,  &x, &y, &state, TRUE);
   if (pointer_window != NULL &&
       (GDK_WINDOW_DESTROYED (pointer_window) ||
        GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
        GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
     pointer_window = NULL;
 
-  w = (GdkWindowObject *)pointer_window;
-  if (w)
-    {
-      /* Convert to toplevel */
-      while (w->parent != NULL &&
-	     w->parent->window_type != GDK_WINDOW_ROOT)
-	{
-	  x += w->x;
-	  y += w->y;
-	  w = w->parent;
-	}
-    }
-
   *x_out = x;
   *y_out = y;
   *state_out = state;
-  return (GdkWindow *)w;
+  return pointer_window;
 }
 
 static void
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index de082bd..51db55f 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -461,7 +461,8 @@ void       _gdk_windowing_get_pointer        (GdkDisplay       *display,
 GdkWindow* _gdk_windowing_window_at_pointer  (GdkDisplay       *display,
 					      gint             *win_x,
 					      gint             *win_y,
-					      GdkModifierType  *mask);
+					      GdkModifierType  *mask,
+					      gboolean          get_toplevel);
 GdkGrabStatus _gdk_windowing_pointer_grab    (GdkWindow        *window,
 					      GdkWindow        *native,
 					      gboolean          owner_events,
diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c
index ac22d5f..4764498 100644
--- a/gdk/quartz/gdkwindow-quartz.c
+++ b/gdk/quartz/gdkwindow-quartz.c
@@ -1938,7 +1938,8 @@ GdkWindow *
 _gdk_windowing_window_at_pointer (GdkDisplay      *display,
 				  gint            *win_x,
 				  gint            *win_y,
-                                  GdkModifierType *mask)
+                                  GdkModifierType *mask,
+				  gboolean         get_toplevel)
 {
   GdkWindow *found_window;
   gint x, y;
@@ -1976,6 +1977,26 @@ _gdk_windowing_window_at_pointer (GdkDisplay      *display,
   if (mask)
     *mask = tmp_mask;
 
+  if (get_toplevel)
+    {
+      GdkWindowObject *w = (GdkWindowObject *)found_window;
+      /* Requested toplevel, find it. */
+      /* TODO: This can be implemented more efficient by never
+	 recursing into children in the first place */
+      if (w)
+	{
+	  /* Convert to toplevel */
+	  while (w->parent != NULL &&
+		 w->parent->window_type != GDK_WINDOW_ROOT)
+	    {
+	      *win_x += w->x;
+	      *win_y += w->y;
+	      w = w->parent;
+	    }
+	  found_window = (GdkWindow *)w;
+	}
+    }
+
   return found_window;
 }
 
diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c
index c945631..e472b91 100644
--- a/gdk/win32/gdkwindow-win32.c
+++ b/gdk/win32/gdkwindow-win32.c
@@ -2261,7 +2261,8 @@ GdkWindow*
 _gdk_windowing_window_at_pointer (GdkDisplay *display,
 				  gint       *win_x,
 				  gint       *win_y,
-				  GdkModifierType *mask)
+				  GdkModifierType *mask,
+				  gboolean    get_toplevel)
 {
   GdkWindow *window;
   POINT point, pointc;
@@ -2283,6 +2284,11 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
   ScreenToClient (hwnd, &point);
 
   do {
+    if (get_toplevel &&
+	(window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd)) != NULL &&
+	GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+      break;
+
     hwndc = ChildWindowFromPoint (hwnd, point);
     ClientToScreen (hwnd, &point);
     ScreenToClient (hwndc, &point);
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index 257dba7..f98290b 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -3215,7 +3215,8 @@ GdkWindow*
 _gdk_windowing_window_at_pointer (GdkDisplay *display,
                                   gint       *win_x,
 				  gint       *win_y,
-				  GdkModifierType *mask)
+				  GdkModifierType *mask,
+				  gboolean   get_toplevel)
 {
   GdkWindow *window;
   GdkScreen *screen;
@@ -3251,6 +3252,10 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
       while (xwindow)
 	{
 	  xwindow_last = xwindow;
+	  if (get_toplevel &&
+	      (window = gdk_window_lookup_for_display (display, xwindow)) != NULL &&
+	      GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+	    break;
 	  XQueryPointer (xdisplay, xwindow,
 			 &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
 	}
@@ -3310,6 +3315,10 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
       while (xwindow)
 	{
 	  xwindow_last = xwindow;
+	  if (get_toplevel &&
+	      (window = gdk_window_lookup_for_display (display, xwindow)) != NULL &&
+	      GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+	    break;
 	  gdk_error_trap_push ();
 	  XQueryPointer (xdisplay, xwindow,
 			 &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);



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