mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-15 14:50:06 +00:00
wayland: check native surface for crossing events
gdk_wayland_*_grab()/ungrab() would emit crossing events which translate as focus_in/focus_out events for keyboard. However, the ungrab() functions compare the native toplevel as this is what gets the Wayland pointer enter/leave events with the grab surface, so if the grab is issued on a child gdk surface, those won't match and we would emit more focus_out events than focus_in. This means that a widget such as spice-gtk which issues a keyboard grab whenever the pointer enters the surface and releases the grab when it leaves the surface would get uneven numbers of focus_in/focus_out events. Also, gdk_wayland_seat_ungrab() would not emit crossing events for keyboard devices, whereas gdk_wayland_device_ungrab() does, which adds even more potential discrepancies between focus_in/focus_out events. To solve this problem, introduce two new helper functions which check the relevant native surfaces to emit crossing events when needed that get called evenly from both gdk_wayland_seat_grab()/ungrab() and gdk _wayland_device_grab()/ungrab() APIs. Fixes: https://bugzilla.gnome.org/show_bug.cgi?id=780422 Closes https://gitlab.gnome.org/GNOME/gtk/issues/792
This commit is contained in:
parent
47872e5172
commit
d3885e92a7
@ -712,6 +712,43 @@ gdk_wayland_device_get_focus (GdkDevice *device)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
device_maybe_emit_grab_crossing (GdkDevice *device,
|
||||||
|
GdkSurface *window,
|
||||||
|
guint32 time)
|
||||||
|
{
|
||||||
|
GdkSurface *native = gdk_wayland_device_get_focus (device);
|
||||||
|
GdkSurface *focus = gdk_surface_get_toplevel (window);
|
||||||
|
|
||||||
|
if (focus != native)
|
||||||
|
device_emit_grab_crossing (device, focus, window, GDK_CROSSING_GRAB, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkSurface*
|
||||||
|
device_maybe_emit_ungrab_crossing (GdkDevice *device,
|
||||||
|
guint32 time)
|
||||||
|
{
|
||||||
|
GdkDeviceGrabInfo *grab;
|
||||||
|
GdkSurface *focus = NULL;
|
||||||
|
GdkSurface *native = NULL;
|
||||||
|
GdkSurface *prev_focus = NULL;
|
||||||
|
|
||||||
|
focus = gdk_wayland_device_get_focus (device);
|
||||||
|
grab = _gdk_display_get_last_device_grab (gdk_device_get_display (device), device);
|
||||||
|
|
||||||
|
if (grab)
|
||||||
|
{
|
||||||
|
grab->serial_end = grab->serial_start;
|
||||||
|
prev_focus = grab->surface;
|
||||||
|
native = grab->native_surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (focus != native)
|
||||||
|
device_emit_grab_crossing (device, prev_focus, focus, GDK_CROSSING_UNGRAB, time);
|
||||||
|
|
||||||
|
return prev_focus;
|
||||||
|
}
|
||||||
|
|
||||||
static GdkGrabStatus
|
static GdkGrabStatus
|
||||||
gdk_wayland_device_grab (GdkDevice *device,
|
gdk_wayland_device_grab (GdkDevice *device,
|
||||||
GdkSurface *surface,
|
GdkSurface *surface,
|
||||||
@ -722,7 +759,6 @@ gdk_wayland_device_grab (GdkDevice *device,
|
|||||||
guint32 time_)
|
guint32 time_)
|
||||||
{
|
{
|
||||||
GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
|
GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
|
||||||
GdkSurface *prev_focus = gdk_wayland_device_get_focus (device);
|
|
||||||
GdkWaylandPointerData *pointer = GDK_WAYLAND_DEVICE (device)->pointer;
|
GdkWaylandPointerData *pointer = GDK_WAYLAND_DEVICE (device)->pointer;
|
||||||
|
|
||||||
if (gdk_surface_get_surface_type (surface) == GDK_SURFACE_TEMP &&
|
if (gdk_surface_get_surface_type (surface) == GDK_SURFACE_TEMP &&
|
||||||
@ -734,8 +770,7 @@ gdk_wayland_device_grab (GdkDevice *device,
|
|||||||
surface);
|
surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev_focus != surface)
|
device_maybe_emit_grab_crossing (device, surface, time_);
|
||||||
device_emit_grab_crossing (device, prev_focus, surface, GDK_CROSSING_GRAB, time_);
|
|
||||||
|
|
||||||
if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
|
if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
|
||||||
{
|
{
|
||||||
@ -776,24 +811,9 @@ gdk_wayland_device_ungrab (GdkDevice *device,
|
|||||||
guint32 time_)
|
guint32 time_)
|
||||||
{
|
{
|
||||||
GdkWaylandPointerData *pointer = GDK_WAYLAND_DEVICE (device)->pointer;
|
GdkWaylandPointerData *pointer = GDK_WAYLAND_DEVICE (device)->pointer;
|
||||||
GdkDisplay *display;
|
GdkSurface *prev_focus;
|
||||||
GdkDeviceGrabInfo *grab;
|
|
||||||
GdkSurface *focus, *prev_focus = NULL;
|
|
||||||
|
|
||||||
display = gdk_device_get_display (device);
|
prev_focus = device_maybe_emit_ungrab_crossing (device, time_);
|
||||||
|
|
||||||
grab = _gdk_display_get_last_device_grab (display, device);
|
|
||||||
|
|
||||||
if (grab)
|
|
||||||
{
|
|
||||||
grab->serial_end = grab->serial_start;
|
|
||||||
prev_focus = grab->surface;
|
|
||||||
}
|
|
||||||
|
|
||||||
focus = gdk_wayland_device_get_focus (device);
|
|
||||||
|
|
||||||
if (focus != prev_focus)
|
|
||||||
device_emit_grab_crossing (device, prev_focus, focus, GDK_CROSSING_UNGRAB, time_);
|
|
||||||
|
|
||||||
if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
|
if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
|
||||||
{
|
{
|
||||||
@ -4665,11 +4685,8 @@ gdk_wayland_seat_grab (GdkSeat *seat,
|
|||||||
if (wayland_seat->master_pointer &&
|
if (wayland_seat->master_pointer &&
|
||||||
capabilities & GDK_SEAT_CAPABILITY_POINTER)
|
capabilities & GDK_SEAT_CAPABILITY_POINTER)
|
||||||
{
|
{
|
||||||
GdkSurface *prev_focus = gdk_wayland_device_get_focus (wayland_seat->master_pointer);
|
device_maybe_emit_grab_crossing (wayland_seat->master_pointer,
|
||||||
|
native, evtime);
|
||||||
if (prev_focus != native)
|
|
||||||
device_emit_grab_crossing (wayland_seat->master_pointer, prev_focus,
|
|
||||||
native, GDK_CROSSING_GRAB, evtime);
|
|
||||||
|
|
||||||
_gdk_display_add_device_grab (display,
|
_gdk_display_add_device_grab (display,
|
||||||
wayland_seat->master_pointer,
|
wayland_seat->master_pointer,
|
||||||
@ -4690,11 +4707,8 @@ gdk_wayland_seat_grab (GdkSeat *seat,
|
|||||||
if (wayland_seat->touch_master &&
|
if (wayland_seat->touch_master &&
|
||||||
capabilities & GDK_SEAT_CAPABILITY_TOUCH)
|
capabilities & GDK_SEAT_CAPABILITY_TOUCH)
|
||||||
{
|
{
|
||||||
GdkSurface *prev_focus = gdk_wayland_device_get_focus (wayland_seat->touch_master);
|
device_maybe_emit_grab_crossing (wayland_seat->touch_master,
|
||||||
|
native, evtime);
|
||||||
if (prev_focus != native)
|
|
||||||
device_emit_grab_crossing (wayland_seat->touch_master, prev_focus,
|
|
||||||
native, GDK_CROSSING_GRAB, evtime);
|
|
||||||
|
|
||||||
_gdk_display_add_device_grab (display,
|
_gdk_display_add_device_grab (display,
|
||||||
wayland_seat->touch_master,
|
wayland_seat->touch_master,
|
||||||
@ -4711,11 +4725,8 @@ gdk_wayland_seat_grab (GdkSeat *seat,
|
|||||||
if (wayland_seat->master_keyboard &&
|
if (wayland_seat->master_keyboard &&
|
||||||
capabilities & GDK_SEAT_CAPABILITY_KEYBOARD)
|
capabilities & GDK_SEAT_CAPABILITY_KEYBOARD)
|
||||||
{
|
{
|
||||||
GdkSurface *prev_focus = gdk_wayland_device_get_focus (wayland_seat->master_keyboard);
|
device_maybe_emit_grab_crossing (wayland_seat->master_keyboard,
|
||||||
|
native, evtime);
|
||||||
if (prev_focus != native)
|
|
||||||
device_emit_grab_crossing (wayland_seat->master_keyboard, prev_focus,
|
|
||||||
native, GDK_CROSSING_GRAB, evtime);
|
|
||||||
|
|
||||||
_gdk_display_add_device_grab (display,
|
_gdk_display_add_device_grab (display,
|
||||||
wayland_seat->master_keyboard,
|
wayland_seat->master_keyboard,
|
||||||
@ -4739,11 +4750,8 @@ gdk_wayland_seat_grab (GdkSeat *seat,
|
|||||||
for (l = wayland_seat->tablets; l; l = l->next)
|
for (l = wayland_seat->tablets; l; l = l->next)
|
||||||
{
|
{
|
||||||
GdkWaylandTabletData *tablet = l->data;
|
GdkWaylandTabletData *tablet = l->data;
|
||||||
GdkSurface *prev_focus = gdk_wayland_device_get_focus (tablet->master);
|
|
||||||
|
|
||||||
if (prev_focus != native)
|
device_maybe_emit_grab_crossing (tablet->master, native, evtime);
|
||||||
device_emit_grab_crossing (tablet->master, prev_focus,
|
|
||||||
native, GDK_CROSSING_GRAB, evtime);
|
|
||||||
|
|
||||||
_gdk_display_add_device_grab (display,
|
_gdk_display_add_device_grab (display,
|
||||||
tablet->master,
|
tablet->master,
|
||||||
@ -4777,36 +4785,20 @@ gdk_wayland_seat_ungrab (GdkSeat *seat)
|
|||||||
|
|
||||||
if (wayland_seat->master_pointer)
|
if (wayland_seat->master_pointer)
|
||||||
{
|
{
|
||||||
GdkSurface *focus, *prev_focus = NULL;
|
device_maybe_emit_ungrab_crossing (wayland_seat->master_pointer,
|
||||||
|
GDK_CURRENT_TIME);
|
||||||
grab = _gdk_display_get_last_device_grab (display, wayland_seat->master_pointer);
|
|
||||||
|
|
||||||
if (grab)
|
|
||||||
{
|
|
||||||
grab->serial_end = grab->serial_start;
|
|
||||||
prev_focus = grab->surface;
|
|
||||||
}
|
|
||||||
|
|
||||||
focus = gdk_wayland_device_get_focus (wayland_seat->master_pointer);
|
|
||||||
|
|
||||||
if (focus != prev_focus)
|
|
||||||
device_emit_grab_crossing (wayland_seat->master_pointer, prev_focus,
|
|
||||||
focus, GDK_CROSSING_UNGRAB,
|
|
||||||
GDK_CURRENT_TIME);
|
|
||||||
|
|
||||||
gdk_wayland_device_update_surface_cursor (wayland_seat->master_pointer);
|
gdk_wayland_device_update_surface_cursor (wayland_seat->master_pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wayland_seat->master_keyboard)
|
if (wayland_seat->master_keyboard)
|
||||||
{
|
{
|
||||||
grab = _gdk_display_get_last_device_grab (display, wayland_seat->master_keyboard);
|
GdkSurface *prev_focus;
|
||||||
|
|
||||||
if (grab)
|
prev_focus = device_maybe_emit_ungrab_crossing (wayland_seat->master_keyboard,
|
||||||
{
|
GDK_CURRENT_TIME);
|
||||||
grab->serial_end = grab->serial_start;
|
if (prev_focus)
|
||||||
if (grab->surface)
|
gdk_wayland_surface_restore_shortcuts (prev_focus, seat);
|
||||||
gdk_wayland_surface_restore_shortcuts (grab->surface, seat);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wayland_seat->touch_master)
|
if (wayland_seat->touch_master)
|
||||||
|
Loading…
Reference in New Issue
Block a user