diff options
author | Alexander Larsson <alexl@redhat.com> | 2009-09-28 15:21:54 +0200 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2009-09-28 15:21:54 +0200 |
commit | 5ebb32d1ffa23241d562fb4d5be02bc6f156b515 (patch) | |
tree | 7e55ae158bcbb35019c5f6e999f2ef20c8600f8e | |
parent | fe188a18f324f4545af857436a6060e676a1287d (diff) | |
download | gtk+-5ebb32d1ffa23241d562fb4d5be02bc6f156b515.tar.gz |
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.
-rw-r--r-- | gdk/directfb/gdkwindow-directfb.c | 20 | ||||
-rw-r--r-- | gdk/gdkdisplay.c | 20 | ||||
-rw-r--r-- | gdk/gdkinternals.h | 3 | ||||
-rw-r--r-- | gdk/quartz/gdkwindow-quartz.c | 23 | ||||
-rw-r--r-- | gdk/win32/gdkwindow-win32.c | 8 | ||||
-rw-r--r-- | 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 85859e707a..c0ff8e158f 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 d22ff00c77..d020b16fc3 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 de082bdaa7..51db55f2df 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 ac22d5f313..4764498340 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 c94563165c..e472b914c5 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 257dba7ef6..f98290b6a2 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); |