Remove gdk_windowing_{get_device_state,window_at_device_position}

The !trusted workaround code is pushed down into the GdkDevice
subclasses, and we use the device vfuncs directly in gdkdisplay.c
This commit is contained in:
Matthias Clasen 2010-12-13 17:43:10 -05:00
parent 9adb974155
commit 224726f554
8 changed files with 342 additions and 282 deletions

View File

@ -1455,3 +1455,38 @@ _gdk_device_translate_axis (GdkDevice *device,
return TRUE; return TRUE;
} }
gboolean
_gdk_device_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
GdkModifierType *mask)
{
return GDK_DEVICE_GET_CLASS (device)->query_state (device,
window,
root_window,
child_window,
root_x,
root_y,
win_x,
win_y,
mask);
}
GdkWindow *
_gdk_device_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
return GDK_DEVICE_GET_CLASS (device)->window_at_position (device,
win_x,
win_y,
mask,
get_toplevel);
}

View File

@ -85,10 +85,10 @@ struct _GdkDeviceClass
GdkScreen *screen, GdkScreen *screen,
gint x, gint x,
gint y); gint y);
gboolean (* query_state) (GdkDevice *device, gboolean (* query_state) (GdkDevice *device,
GdkWindow *window, GdkWindow *window,
GdkWindow **root_window, GdkWindow **root_window,
GdkWindow **child_window, GdkWindow **child_window,
gint *root_x, gint *root_x,
gint *root_y, gint *root_y,
gint *win_x, gint *win_x,
@ -157,6 +157,20 @@ void _gdk_device_add_slave (GdkDevice *device,
GdkDevice *slave); GdkDevice *slave);
void _gdk_device_remove_slave (GdkDevice *device, void _gdk_device_remove_slave (GdkDevice *device,
GdkDevice *slave); GdkDevice *slave);
gboolean _gdk_device_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
GdkModifierType *mask);
GdkWindow * _gdk_device_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
G_END_DECLS G_END_DECLS

View File

@ -133,12 +133,18 @@ static GdkWindow *gdk_display_real_get_window_at_device_position (GdkDisplay
GdkDevice *device, GdkDevice *device,
gint *win_x, gint *win_x,
gint *win_y); gint *win_y);
static void gdk_display_real_get_device_state (GdkDisplay *display,
GdkDevice *device,
GdkScreen **screen,
gint *x,
gint *y,
GdkModifierType *mask);
static GdkAppLaunchContext *gdk_display_real_get_app_launch_context (GdkDisplay *display); static GdkAppLaunchContext *gdk_display_real_get_app_launch_context (GdkDisplay *display);
static guint signals[LAST_SIGNAL] = { 0 }; static guint signals[LAST_SIGNAL] = { 0 };
static const GdkDisplayDeviceHooks default_device_hooks = { static const GdkDisplayDeviceHooks default_device_hooks = {
_gdk_windowing_get_device_state, gdk_display_real_get_device_state,
gdk_window_real_window_get_device_position, gdk_window_real_window_get_device_position,
gdk_display_real_get_window_at_device_position gdk_display_real_get_window_at_device_position
}; };
@ -838,7 +844,7 @@ gdk_display_real_get_window_at_device_position (GdkDisplay *display,
GdkWindow *window; GdkWindow *window;
gint x, y; gint x, y;
window = _gdk_windowing_window_at_device_position (display, device, &x, &y, NULL, FALSE); window = _gdk_device_window_at_position (device, &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 */
@ -951,6 +957,32 @@ multihead_window_at_device_position (GdkDisplay *display,
return multihead_current_pointer_hooks->window_at_pointer (display, win_x, win_y); return multihead_current_pointer_hooks->window_at_pointer (display, win_x, win_y);
} }
static void
gdk_display_real_get_device_state (GdkDisplay *display,
GdkDevice *device,
GdkScreen **screen,
gint *x,
gint *y,
GdkModifierType *mask)
{
GdkScreen *default_screen;
GdkWindow *root;
if (gdk_display_is_closed (display))
return;
default_screen = gdk_display_get_default_screen (display);
_gdk_device_query_state (device,
gdk_screen_get_root_window (default_screen),
&root, NULL,
x, y,
NULL, NULL,
mask);
*screen = gdk_window_get_screen (root);
}
static void static void
multihead_default_get_pointer (GdkDisplay *display, multihead_default_get_pointer (GdkDisplay *display,
GdkScreen **screen, GdkScreen **screen,
@ -958,9 +990,8 @@ multihead_default_get_pointer (GdkDisplay *display,
gint *y, gint *y,
GdkModifierType *mask) GdkModifierType *mask)
{ {
return _gdk_windowing_get_device_state (display, gdk_display_real_get_device_state (display, display->core_pointer,
display->core_pointer, screen, x, y, mask);
screen, x, y, mask);
} }
static GdkWindow * static GdkWindow *
@ -1329,7 +1360,7 @@ get_current_toplevel (GdkDisplay *display,
int x, y; int x, y;
GdkModifierType state; GdkModifierType state;
pointer_window = _gdk_windowing_window_at_device_position (display, device, &x, &y, &state, TRUE); pointer_window = _gdk_device_window_at_position (device, &x, &y, &state, TRUE);
if (pointer_window != NULL && if (pointer_window != NULL &&
(GDK_WINDOW_DESTROYED (pointer_window) || (GDK_WINDOW_DESTROYED (pointer_window) ||
@ -1340,6 +1371,7 @@ get_current_toplevel (GdkDisplay *display,
*x_out = x; *x_out = x;
*y_out = y; *y_out = y;
*state_out = state; *state_out = state;
return pointer_window; return pointer_window;
} }

View File

@ -326,40 +326,17 @@ extern const GOptionEntry _gdk_windowing_args[];
gchar *_gdk_windowing_substitute_screen_number (const gchar *display_name, gchar *_gdk_windowing_substitute_screen_number (const gchar *display_name,
gint screen_number); gint screen_number);
gulong _gdk_windowing_window_get_next_serial (GdkDisplay *display);
void _gdk_windowing_window_get_offsets (GdkWindow *window, void _gdk_windowing_window_get_offsets (GdkWindow *window,
gint *x_offset, gint *x_offset,
gint *y_offset); gint *y_offset);
void _gdk_windowing_get_device_state (GdkDisplay *display,
GdkDevice *device,
GdkScreen **screen,
gint *x,
gint *y,
GdkModifierType *mask);
GdkWindow* _gdk_windowing_window_at_device_position (GdkDisplay *display,
GdkDevice *device,
gint *win_x,
gint *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
void _gdk_windowing_got_event (GdkDisplay *display, void _gdk_windowing_got_event (GdkDisplay *display,
GList *event_link, GList *event_link,
GdkEvent *event, GdkEvent *event,
gulong serial); gulong serial);
void _gdk_windowing_window_process_updates_recurse (GdkWindow *window,
cairo_region_t *expose_region);
void _gdk_windowing_before_process_all_updates (void);
void _gdk_windowing_after_process_all_updates (void);
#define GDK_WINDOW_IS_MAPPED(window) (((window)->state & GDK_WINDOW_STATE_WITHDRAWN) == 0) #define GDK_WINDOW_IS_MAPPED(window) (((window)->state & GDK_WINDOW_STATE_WITHDRAWN) == 0)
void _gdk_windowing_display_set_sm_client_id (GdkDisplay *display,
const gchar *sm_client_id);
#define GDK_TYPE_PAINTABLE (_gdk_paintable_get_type ()) #define GDK_TYPE_PAINTABLE (_gdk_paintable_get_type ())
#define GDK_PAINTABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_PAINTABLE, GdkPaintable)) #define GDK_PAINTABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_PAINTABLE, GdkPaintable))
#define GDK_IS_PAINTABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_PAINTABLE)) #define GDK_IS_PAINTABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_PAINTABLE))

View File

@ -243,23 +243,49 @@ gdk_device_core_query_state (GdkDevice *device,
GdkModifierType *mask) GdkModifierType *mask)
{ {
GdkDisplay *display; GdkDisplay *display;
GdkScreen *default_screen;
Window xroot_window, xchild_window; Window xroot_window, xchild_window;
int xroot_x, xroot_y, xwin_x, xwin_y; int xroot_x, xroot_y, xwin_x, xwin_y;
unsigned int xmask; unsigned int xmask;
display = gdk_window_get_display (window); display = gdk_window_get_display (window);
default_screen = gdk_display_get_default_screen (display);
if (!XQueryPointer (GDK_WINDOW_XDISPLAY (window), if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
GDK_WINDOW_XID (window),
&xroot_window,
&xchild_window,
&xroot_x,
&xroot_y,
&xwin_x,
&xwin_y,
&xmask))
{ {
return FALSE; if (!XQueryPointer (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
&xroot_window,
&xchild_window,
&xroot_x,
&xroot_y,
&xwin_x,
&xwin_y,
&xmask))
return FALSE;
}
else
{
XSetWindowAttributes attributes;
Display *xdisplay;
Window xwindow, w;
/* FIXME: untrusted clients not multidevice-safe */
xdisplay = GDK_SCREEN_XDISPLAY (default_screen);
xwindow = GDK_SCREEN_XROOTWIN (default_screen);
w = XCreateWindow (xdisplay, xwindow, 0, 0, 1, 1, 0,
CopyFromParent, InputOnly, CopyFromParent,
0, &attributes);
XQueryPointer (xdisplay, w,
&xroot_window,
&xchild_window,
&xroot_x,
&xroot_y,
&xwin_x,
&xwin_y,
&xmask);
XDestroyWindow (xdisplay, w);
} }
if (root_window) if (root_window)
@ -415,25 +441,92 @@ gdk_device_core_window_at_position (GdkDevice *device,
xdisplay = GDK_SCREEN_XDISPLAY (screen); xdisplay = GDK_SCREEN_XDISPLAY (screen);
xwindow = GDK_SCREEN_XROOTWIN (screen); xwindow = GDK_SCREEN_XROOTWIN (screen);
XQueryPointer (xdisplay, xwindow, if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
&root, &child, {
&xroot_x, &xroot_y, XQueryPointer (xdisplay, xwindow,
&xwin_x, &xwin_y, &root, &child,
&xmask); &xroot_x, &xroot_y,
&xwin_x, &xwin_y,
&xmask);
if (root == xwindow) if (root == xwindow)
xwindow = child; xwindow = child;
else
xwindow = root;
}
else else
xwindow = root; {
gint i, screens, width, height;
GList *toplevels, *list;
Window pointer_window, root, child;
int rootx = -1, rooty = -1;
int winx, winy;
unsigned int xmask;
/* FIXME: untrusted clients case not multidevice-safe */
pointer_window = None;
screens = gdk_display_get_n_screens (display);
for (i = 0; i < screens; ++i)
{
screen = gdk_display_get_screen (display, i);
toplevels = gdk_screen_get_toplevel_windows (screen);
for (list = toplevels; list != NULL; list = g_list_next (list))
{
window = GDK_WINDOW (list->data);
xwindow = GDK_WINDOW_XID (window);
gdk_x11_display_error_trap_push (display);
XQueryPointer (xdisplay, xwindow,
&root, &child, &rootx, &rooty, &winx, &winy, &xmask);
if (gdk_x11_display_error_trap_pop (display))
continue;
if (child != None)
{
pointer_window = child;
break;
}
gdk_window_get_geometry (window, NULL, NULL, &width, &height);
if (winx >= 0 && winy >= 0 && winx < width && winy < height)
{
/* A childless toplevel, or below another window? */
XSetWindowAttributes attributes;
Window w;
w = XCreateWindow (xdisplay, xwindow, winx, winy, 1, 1, 0,
CopyFromParent, InputOnly, CopyFromParent,
0, &attributes);
XMapWindow (xdisplay, w);
XQueryPointer (xdisplay, xwindow,
&root, &child,
&rootx, &rooty, &winx, &winy, &xmask);
XDestroyWindow (xdisplay, w);
if (child == w)
{
pointer_window = xwindow;
break;
}
}
}
g_list_free (toplevels);
if (pointer_window != None)
break;
}
xwindow = pointer_window;
}
while (xwindow) while (xwindow)
{ {
last = xwindow; last = xwindow;
gdk_x11_display_error_trap_push (display);
XQueryPointer (xdisplay, xwindow, XQueryPointer (xdisplay, xwindow,
&root, &xwindow, &root, &xwindow,
&xroot_x, &xroot_y, &xroot_x, &xroot_y,
&xwin_x, &xwin_y, &xwin_x, &xwin_y,
&xmask); &xmask);
if (gdk_x11_display_error_trap_pop (display))
break;
if (get_toplevel && last != root && if (get_toplevel && last != root &&
(window = gdk_window_lookup_for_display (display, last)) != NULL && (window = gdk_window_lookup_for_display (display, last)) != NULL &&

View File

@ -491,6 +491,7 @@ gdk_device_xi_window_at_position (GdkDevice *device,
{ {
return NULL; return NULL;
} }
static void static void
gdk_device_xi_select_window_events (GdkDevice *device, gdk_device_xi_select_window_events (GdkDevice *device,
GdkWindow *window, GdkWindow *window,

View File

@ -298,6 +298,7 @@ gdk_device_xi2_query_state (GdkDevice *device,
GdkModifierType *mask) GdkModifierType *mask)
{ {
GdkDisplay *display; GdkDisplay *display;
GdkScreen *default_screen;
GdkDeviceXI2Private *priv; GdkDeviceXI2Private *priv;
Window xroot_window, xchild_window; Window xroot_window, xchild_window;
gdouble xroot_x, xroot_y, xwin_x, xwin_y; gdouble xroot_x, xroot_y, xwin_x, xwin_y;
@ -310,21 +311,49 @@ gdk_device_xi2_query_state (GdkDevice *device,
priv = GDK_DEVICE_XI2 (device)->priv; priv = GDK_DEVICE_XI2 (device)->priv;
display = gdk_window_get_display (window); display = gdk_window_get_display (window);
default_screen = gdk_display_get_default_screen (display);
if (!XIQueryPointer (GDK_WINDOW_XDISPLAY (window), if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
priv->device_id,
GDK_WINDOW_XID (window),
&xroot_window,
&xchild_window,
&xroot_x,
&xroot_y,
&xwin_x,
&xwin_y,
&button_state,
&mod_state,
&group_state))
{ {
return FALSE; if (!XIQueryPointer (GDK_WINDOW_XDISPLAY (window),
priv->device_id,
GDK_WINDOW_XID (window),
&xroot_window,
&xchild_window,
&xroot_x,
&xroot_y,
&xwin_x,
&xwin_y,
&button_state,
&mod_state,
&group_state))
return FALSE;
}
else
{
XSetWindowAttributes attributes;
Display *xdisplay;
Window xwindow, w;
/* FIXME: untrusted clients not multidevice-safe */
xdisplay = GDK_SCREEN_XDISPLAY (default_screen);
xwindow = GDK_SCREEN_XROOTWIN (default_screen);
w = XCreateWindow (xdisplay, xwindow, 0, 0, 1, 1, 0,
CopyFromParent, InputOnly, CopyFromParent,
0, &attributes);
XIQueryPointer (xdisplay, priv->device_id,
w,
&xroot_window,
&xchild_window,
&xroot_x,
&xroot_y,
&xwin_x,
&xwin_y,
&button_state,
&mod_state,
&group_state);
XDestroyWindow (xdisplay, w);
} }
if (root_window) if (root_window)
@ -455,24 +484,99 @@ gdk_device_xi2_window_at_position (GdkDevice *device,
xdisplay = GDK_SCREEN_XDISPLAY (screen); xdisplay = GDK_SCREEN_XDISPLAY (screen);
xwindow = GDK_SCREEN_XROOTWIN (screen); xwindow = GDK_SCREEN_XROOTWIN (screen);
XIQueryPointer (xdisplay, if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
priv->device_id, {
xwindow, XIQueryPointer (xdisplay,
&root, &child, priv->device_id,
&xroot_x, &xroot_y, xwindow,
&xwin_x, &xwin_y, &root, &child,
&button_state, &xroot_x, &xroot_y,
&mod_state, &xwin_x, &xwin_y,
&group_state); &button_state,
&mod_state,
&group_state);
if (root == xwindow) if (root == xwindow)
xwindow = child; xwindow = child;
else
xwindow = root;
}
else else
xwindow = root; {
gint i, screens, width, height;
GList *toplevels, *list;
Window pointer_window, root, child;
/* FIXME: untrusted clients case not multidevice-safe */
pointer_window = None;
screens = gdk_display_get_n_screens (display);
for (i = 0; i < screens; ++i)
{
screen = gdk_display_get_screen (display, i);
toplevels = gdk_screen_get_toplevel_windows (screen);
for (list = toplevels; list != NULL; list = g_list_next (list))
{
window = GDK_WINDOW (list->data);
xwindow = GDK_WINDOW_XID (window);
gdk_x11_display_error_trap_push (display);
XIQueryPointer (xdisplay,
priv->device_id,
xwindow,
&root, &child,
&xroot_x, &xroot_y,
&xwin_x, &xwin_y,
&button_state,
&mod_state,
&group_state);
if (gdk_x11_display_error_trap_pop (display))
continue;
if (child != None)
{
pointer_window = child;
break;
}
gdk_window_get_geometry (window, NULL, NULL, &width, &height);
if (xwin_x >= 0 && xwin_y >= 0 && xwin_x < width && xwin_y < height)
{
/* A childless toplevel, or below another window? */
XSetWindowAttributes attributes;
Window w;
w = XCreateWindow (xdisplay, xwindow, (int)xwin_x, (int)xwin_y, 1, 1, 0,
CopyFromParent, InputOnly, CopyFromParent,
0, &attributes);
XMapWindow (xdisplay, w);
XIQueryPointer (xdisplay,
priv->device_id,
xwindow,
&root, &child,
&xroot_x, &xroot_y,
&xwin_x, &xwin_y,
&button_state,
&mod_state,
&group_state);
XDestroyWindow (xdisplay, w);
if (child == w)
{
pointer_window = xwindow;
break;
}
}
}
g_list_free (toplevels);
if (pointer_window != None)
break;
}
xwindow = pointer_window;
}
while (xwindow) while (xwindow)
{ {
last = xwindow; last = xwindow;
gdk_x11_display_error_trap_push (display);
XIQueryPointer (xdisplay, XIQueryPointer (xdisplay,
priv->device_id, priv->device_id,
xwindow, xwindow,
@ -482,6 +586,8 @@ gdk_device_xi2_window_at_position (GdkDevice *device,
&button_state, &button_state,
&mod_state, &mod_state,
&group_state); &group_state);
if (gdk_x11_display_error_trap_pop (display))
break;
if (get_toplevel && last != root && if (get_toplevel && last != root &&
(window = gdk_window_lookup_for_display (display, last)) != NULL && (window = gdk_window_lookup_for_display (display, last)) != NULL &&

View File

@ -2781,66 +2781,6 @@ gdk_x11_window_get_frame_extents (GdkWindow *window,
gdk_error_trap_pop_ignored (); gdk_error_trap_pop_ignored ();
} }
void
_gdk_windowing_get_device_state (GdkDisplay *display,
GdkDevice *device,
GdkScreen **screen,
gint *x,
gint *y,
GdkModifierType *mask)
{
GdkScreen *default_screen;
if (gdk_display_is_closed (display))
return;
default_screen = gdk_display_get_default_screen (display);
if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
{
GdkWindow *root;
GDK_DEVICE_GET_CLASS (device)->query_state (device,
gdk_screen_get_root_window (default_screen),
&root, NULL,
x, y,
NULL, NULL,
mask);
*screen = gdk_window_get_screen (root);
}
else
{
XSetWindowAttributes attributes;
Display *xdisplay;
Window xwindow, w, root, child;
int rootx, rooty, winx, winy;
unsigned int xmask;
/* FIXME: untrusted clients not multidevice-safe */
xdisplay = GDK_SCREEN_XDISPLAY (default_screen);
xwindow = GDK_SCREEN_XROOTWIN (default_screen);
w = XCreateWindow (xdisplay, xwindow, 0, 0, 1, 1, 0,
CopyFromParent, InputOnly, CopyFromParent,
0, &attributes);
XQueryPointer (xdisplay, w,
&root, &child, &rootx, &rooty, &winx, &winy, &xmask);
XDestroyWindow (xdisplay, w);
if (root != None)
{
GdkWindow *gdk_root = gdk_window_lookup_for_display (display, root);
*screen = gdk_window_get_screen (gdk_root);
}
*x = rootx;
*y = rooty;
*mask = xmask;
}
}
static gboolean static gboolean
gdk_window_x11_get_device_state (GdkWindow *window, gdk_window_x11_get_device_state (GdkWindow *window,
GdkDevice *device, GdkDevice *device,
@ -2848,156 +2788,18 @@ gdk_window_x11_get_device_state (GdkWindow *window,
gint *y, gint *y,
GdkModifierType *mask) GdkModifierType *mask)
{ {
GdkDisplay *display = GDK_WINDOW_DISPLAY (window); GdkWindow *child;
gboolean return_val;
g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE); g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
return_val = TRUE; if (GDK_WINDOW_DESTROYED (window))
return FALSE;
if (!GDK_WINDOW_DESTROYED (window)) GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
{ NULL, &child,
if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) NULL, NULL,
{ x, y, mask);
GdkWindow *child; return child != NULL;
GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
NULL, &child,
NULL, NULL,
x, y, mask);
return_val = (child != NULL);
}
else
{
GdkScreen *screen;
int originx, originy;
int rootx, rooty;
int winx = 0;
int winy = 0;
unsigned int xmask = 0;
_gdk_windowing_get_device_state (gdk_window_get_display (window), device,
&screen, &rootx, &rooty, &xmask);
gdk_window_get_origin (window, &originx, &originy);
winx = rootx - originx;
winy = rooty - originy;
*x = winx;
*y = winy;
*mask = xmask;
}
}
return return_val;
}
GdkWindow*
_gdk_windowing_window_at_device_position (GdkDisplay *display,
GdkDevice *device,
gint *win_x,
gint *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
GdkWindow *window;
GdkScreen *screen;
screen = gdk_display_get_default_screen (display);
/* This function really only works if the mouse pointer is held still
* during its operation. If it moves from one leaf window to another
* than we'll end up with inaccurate values for win_x, win_y
* and the result.
*/
gdk_x11_display_grab (display);
if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
window = GDK_DEVICE_GET_CLASS (device)->window_at_position (device, win_x, win_y, mask, get_toplevel);
else
{
gint i, screens, width, height;
GList *toplevels, *list;
Window pointer_window, root, xwindow, child;
Window xwindow_last = 0;
Display *xdisplay;
int rootx = -1, rooty = -1;
int winx, winy;
unsigned int xmask;
/* FIXME: untrusted clients case not multidevice-safe */
xwindow = GDK_SCREEN_XROOTWIN (screen);
xdisplay = GDK_SCREEN_XDISPLAY (screen);
pointer_window = None;
screens = gdk_display_get_n_screens (display);
for (i = 0; i < screens; ++i) {
screen = gdk_display_get_screen (display, i);
toplevels = gdk_screen_get_toplevel_windows (screen);
for (list = toplevels; list != NULL; list = g_list_next (list)) {
window = GDK_WINDOW (list->data);
xwindow = GDK_WINDOW_XID (window);
gdk_error_trap_push ();
XQueryPointer (xdisplay, xwindow,
&root, &child, &rootx, &rooty, &winx, &winy, &xmask);
if (gdk_error_trap_pop ())
continue;
if (child != None)
{
pointer_window = child;
break;
}
gdk_window_get_geometry (window, NULL, NULL, &width, &height);
if (winx >= 0 && winy >= 0 && winx < width && winy < height)
{
/* A childless toplevel, or below another window? */
XSetWindowAttributes attributes;
Window w;
w = XCreateWindow (xdisplay, xwindow, winx, winy, 1, 1, 0,
CopyFromParent, InputOnly, CopyFromParent,
0, &attributes);
XMapWindow (xdisplay, w);
XQueryPointer (xdisplay, xwindow,
&root, &child, &rootx, &rooty, &winx, &winy, &xmask);
XDestroyWindow (xdisplay, w);
if (child == w)
{
pointer_window = xwindow;
break;
}
}
}
g_list_free (toplevels);
if (pointer_window != None)
break;
}
xwindow = pointer_window;
while (xwindow)
{
xwindow_last = xwindow;
gdk_error_trap_push ();
XQueryPointer (xdisplay, xwindow,
&root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
if (gdk_error_trap_pop ())
break;
if (get_toplevel && xwindow_last != root &&
(window = gdk_window_lookup_for_display (display, xwindow_last)) != NULL &&
GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
break;
}
window = gdk_window_lookup_for_display (display, xwindow_last);
*win_x = window ? winx : -1;
*win_y = window ? winy : -1;
if (mask)
*mask = xmask;
}
gdk_x11_display_ungrab (display);
return window;
} }
static GdkEventMask static GdkEventMask