Commit 5ebb32d1 authored by Alexander Larsson's avatar Alexander Larsson

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.
parent fe188a18
......@@ -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;
}
......
......@@ -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
......
......@@ -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,
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment