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.
This commit is contained in:
@ -2099,6 +2099,26 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
|
|||||||
if (win_y)
|
if (win_y)
|
||||||
*win_y = wy;
|
*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;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -510,7 +510,7 @@ gdk_display_real_get_window_at_pointer (GdkDisplay *display,
|
|||||||
GdkWindow *window;
|
GdkWindow *window;
|
||||||
gint x, y;
|
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
|
/* This might need corrections, as the native window returned
|
||||||
may contain client side children */
|
may contain client side children */
|
||||||
@ -913,34 +913,20 @@ get_current_toplevel (GdkDisplay *display,
|
|||||||
GdkModifierType *state_out)
|
GdkModifierType *state_out)
|
||||||
{
|
{
|
||||||
GdkWindow *pointer_window;
|
GdkWindow *pointer_window;
|
||||||
GdkWindowObject *w;
|
|
||||||
int x, y;
|
int x, y;
|
||||||
GdkModifierType state;
|
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 &&
|
if (pointer_window != NULL &&
|
||||||
(GDK_WINDOW_DESTROYED (pointer_window) ||
|
(GDK_WINDOW_DESTROYED (pointer_window) ||
|
||||||
GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
|
GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
|
||||||
GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
|
GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
|
||||||
pointer_window = NULL;
|
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;
|
*x_out = x;
|
||||||
*y_out = y;
|
*y_out = y;
|
||||||
*state_out = state;
|
*state_out = state;
|
||||||
return (GdkWindow *)w;
|
return pointer_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@ -461,7 +461,8 @@ void _gdk_windowing_get_pointer (GdkDisplay *display,
|
|||||||
GdkWindow* _gdk_windowing_window_at_pointer (GdkDisplay *display,
|
GdkWindow* _gdk_windowing_window_at_pointer (GdkDisplay *display,
|
||||||
gint *win_x,
|
gint *win_x,
|
||||||
gint *win_y,
|
gint *win_y,
|
||||||
GdkModifierType *mask);
|
GdkModifierType *mask,
|
||||||
|
gboolean get_toplevel);
|
||||||
GdkGrabStatus _gdk_windowing_pointer_grab (GdkWindow *window,
|
GdkGrabStatus _gdk_windowing_pointer_grab (GdkWindow *window,
|
||||||
GdkWindow *native,
|
GdkWindow *native,
|
||||||
gboolean owner_events,
|
gboolean owner_events,
|
||||||
|
|||||||
@ -1938,7 +1938,8 @@ GdkWindow *
|
|||||||
_gdk_windowing_window_at_pointer (GdkDisplay *display,
|
_gdk_windowing_window_at_pointer (GdkDisplay *display,
|
||||||
gint *win_x,
|
gint *win_x,
|
||||||
gint *win_y,
|
gint *win_y,
|
||||||
GdkModifierType *mask)
|
GdkModifierType *mask,
|
||||||
|
gboolean get_toplevel)
|
||||||
{
|
{
|
||||||
GdkWindow *found_window;
|
GdkWindow *found_window;
|
||||||
gint x, y;
|
gint x, y;
|
||||||
@ -1976,6 +1977,26 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
|
|||||||
if (mask)
|
if (mask)
|
||||||
*mask = tmp_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;
|
return found_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2261,7 +2261,8 @@ GdkWindow*
|
|||||||
_gdk_windowing_window_at_pointer (GdkDisplay *display,
|
_gdk_windowing_window_at_pointer (GdkDisplay *display,
|
||||||
gint *win_x,
|
gint *win_x,
|
||||||
gint *win_y,
|
gint *win_y,
|
||||||
GdkModifierType *mask)
|
GdkModifierType *mask,
|
||||||
|
gboolean get_toplevel)
|
||||||
{
|
{
|
||||||
GdkWindow *window;
|
GdkWindow *window;
|
||||||
POINT point, pointc;
|
POINT point, pointc;
|
||||||
@ -2283,6 +2284,11 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
|
|||||||
ScreenToClient (hwnd, &point);
|
ScreenToClient (hwnd, &point);
|
||||||
|
|
||||||
do {
|
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);
|
hwndc = ChildWindowFromPoint (hwnd, point);
|
||||||
ClientToScreen (hwnd, &point);
|
ClientToScreen (hwnd, &point);
|
||||||
ScreenToClient (hwndc, &point);
|
ScreenToClient (hwndc, &point);
|
||||||
|
|||||||
@ -3215,7 +3215,8 @@ GdkWindow*
|
|||||||
_gdk_windowing_window_at_pointer (GdkDisplay *display,
|
_gdk_windowing_window_at_pointer (GdkDisplay *display,
|
||||||
gint *win_x,
|
gint *win_x,
|
||||||
gint *win_y,
|
gint *win_y,
|
||||||
GdkModifierType *mask)
|
GdkModifierType *mask,
|
||||||
|
gboolean get_toplevel)
|
||||||
{
|
{
|
||||||
GdkWindow *window;
|
GdkWindow *window;
|
||||||
GdkScreen *screen;
|
GdkScreen *screen;
|
||||||
@ -3251,6 +3252,10 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
|
|||||||
while (xwindow)
|
while (xwindow)
|
||||||
{
|
{
|
||||||
xwindow_last = 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,
|
XQueryPointer (xdisplay, xwindow,
|
||||||
&root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
|
&root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
|
||||||
}
|
}
|
||||||
@ -3310,6 +3315,10 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
|
|||||||
while (xwindow)
|
while (xwindow)
|
||||||
{
|
{
|
||||||
xwindow_last = 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 ();
|
gdk_error_trap_push ();
|
||||||
XQueryPointer (xdisplay, xwindow,
|
XQueryPointer (xdisplay, xwindow,
|
||||||
&root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
|
&root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
|
||||||
|
|||||||
Reference in New Issue
Block a user