Manually update toplevel_under_pointer when a grab changes to owner_events
When we ungrab the pointer we don't get enter events for the window the pointer is in at the time of the ungrab, so we manually query for the window the pointer is in. The same thing actually happens on re-grab if the previous grab was !owner_events (meaning we don't get crossing events for windows other than the grab) but the new grab is owner_events (and thus non-grab windows need to get crossing events). This factors out some common code and enables it also for the re-grab to owner_events case.
This commit is contained in:
133
gdk/gdkdisplay.c
133
gdk/gdkdisplay.c
@@ -903,6 +903,42 @@ synthesize_crossing_events (GdkDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
static GdkWindow *
|
||||
get_current_toplevel (GdkDisplay *display,
|
||||
int *x_out, int *y_out,
|
||||
GdkModifierType *state_out)
|
||||
{
|
||||
GdkWindow *pointer_window;
|
||||
GdkWindowObject *w;
|
||||
int x, y;
|
||||
GdkModifierType state;
|
||||
|
||||
pointer_window = _gdk_windowing_window_at_pointer (display, &x, &y, &state);
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
switch_to_pointer_grab (GdkDisplay *display,
|
||||
GdkPointerGrabInfo *grab,
|
||||
@@ -910,8 +946,7 @@ switch_to_pointer_grab (GdkDisplay *display,
|
||||
guint32 time,
|
||||
gulong serial)
|
||||
{
|
||||
GdkWindow *src_window, *pointer_window;
|
||||
GdkWindowObject *w;
|
||||
GdkWindow *src_window, *pointer_window, *new_toplevel;
|
||||
GList *old_grabs;
|
||||
GdkModifierType state;
|
||||
int x, y;
|
||||
@@ -944,66 +979,66 @@ switch_to_pointer_grab (GdkDisplay *display,
|
||||
src_window, grab->window,
|
||||
GDK_CROSSING_GRAB, time, serial);
|
||||
}
|
||||
|
||||
|
||||
/* !owner_event Grabbing a window that we're not inside, current status is
|
||||
now NULL (i.e. outside grabbed window) */
|
||||
if (!grab->owner_events && display->pointer_info.window_under_pointer != grab->window)
|
||||
_gdk_display_set_window_under_pointer (display, NULL);
|
||||
}
|
||||
|
||||
|
||||
grab->activated = TRUE;
|
||||
}
|
||||
else if (last_grab)
|
||||
|
||||
if (last_grab)
|
||||
{
|
||||
pointer_window = _gdk_windowing_window_at_pointer (display, &x, &y, &state);
|
||||
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;
|
||||
|
||||
/* We force checked what window we're in, so we need to
|
||||
* update the toplevel_under_pointer info, as that won't get told of
|
||||
* this change.
|
||||
*/
|
||||
if (display->pointer_info.toplevel_under_pointer)
|
||||
g_object_unref (display->pointer_info.toplevel_under_pointer);
|
||||
display->pointer_info.toplevel_under_pointer = NULL;
|
||||
|
||||
if (pointer_window)
|
||||
new_toplevel = NULL;
|
||||
|
||||
if (grab == NULL /* ungrab */ ||
|
||||
(!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
|
||||
{
|
||||
/* Convert to toplevel */
|
||||
w = (GdkWindowObject *)pointer_window;
|
||||
while (/*w->parent != NULL && */
|
||||
w->parent->window_type != GDK_WINDOW_ROOT)
|
||||
/* We force check what window we're in, and update the toplevel_under_pointer info,
|
||||
* as that won't get told of this change with toplevel enter events.
|
||||
*/
|
||||
if (display->pointer_info.toplevel_under_pointer)
|
||||
g_object_unref (display->pointer_info.toplevel_under_pointer);
|
||||
display->pointer_info.toplevel_under_pointer = NULL;
|
||||
|
||||
new_toplevel = get_current_toplevel (display, &x, &y, &state);
|
||||
if (new_toplevel)
|
||||
{
|
||||
x += w->x;
|
||||
y += w->y;
|
||||
w = w->parent;
|
||||
/* w is now toplevel and x,y in toplevel coords */
|
||||
display->pointer_info.toplevel_under_pointer = g_object_ref (new_toplevel);
|
||||
display->pointer_info.toplevel_x = x;
|
||||
display->pointer_info.toplevel_y = y;
|
||||
display->pointer_info.state = state;
|
||||
}
|
||||
|
||||
/* w is now toplevel and x,y in toplevel coords */
|
||||
display->pointer_info.toplevel_under_pointer = g_object_ref (w);
|
||||
|
||||
/* Find (possibly virtual) child window */
|
||||
pointer_window =
|
||||
_gdk_window_find_descendant_at ((GdkWindow *)w,
|
||||
x, y,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
if (pointer_window != last_grab->window)
|
||||
synthesize_crossing_events (display,
|
||||
last_grab->window, pointer_window,
|
||||
GDK_CROSSING_UNGRAB, time, serial);
|
||||
|
||||
/* We're now ungrabbed, update the window_under_pointer */
|
||||
_gdk_display_set_window_under_pointer (display, pointer_window);
|
||||
|
||||
if (last_grab->implicit_ungrab)
|
||||
generate_grab_broken_event (last_grab->window,
|
||||
FALSE, TRUE,
|
||||
NULL);
|
||||
if (grab == NULL) /* Ungrabbed, send events */
|
||||
{
|
||||
pointer_window = NULL;
|
||||
if (new_toplevel)
|
||||
{
|
||||
/* Find (possibly virtual) child window */
|
||||
pointer_window =
|
||||
_gdk_window_find_descendant_at (new_toplevel,
|
||||
x, y,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
if (pointer_window != last_grab->window)
|
||||
synthesize_crossing_events (display,
|
||||
last_grab->window, pointer_window,
|
||||
GDK_CROSSING_UNGRAB, time, serial);
|
||||
|
||||
/* We're now ungrabbed, update the window_under_pointer */
|
||||
_gdk_display_set_window_under_pointer (display, pointer_window);
|
||||
|
||||
if (last_grab->implicit_ungrab)
|
||||
generate_grab_broken_event (last_grab->window,
|
||||
FALSE, TRUE,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
display->pointer_grabs = old_grabs;
|
||||
|
||||
Reference in New Issue
Block a user