summaryrefslogtreecommitdiff
path: root/gdk
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2009-09-28 15:21:54 +0200
committerAlexander Larsson <alexl@redhat.com>2009-09-28 15:21:54 +0200
commit5ebb32d1ffa23241d562fb4d5be02bc6f156b515 (patch)
tree7e55ae158bcbb35019c5f6e999f2ef20c8600f8e /gdk
parentfe188a18f324f4545af857436a6060e676a1287d (diff)
downloadgtk+-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.
Diffstat (limited to 'gdk')
-rw-r--r--gdk/directfb/gdkwindow-directfb.c20
-rw-r--r--gdk/gdkdisplay.c20
-rw-r--r--gdk/gdkinternals.h3
-rw-r--r--gdk/quartz/gdkwindow-quartz.c23
-rw-r--r--gdk/win32/gdkwindow-win32.c8
-rw-r--r--gdk/x11/gdkwindow-x11.c11
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);