diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2015-06-24 17:48:18 +0200 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2015-06-24 18:15:46 +0200 |
commit | de2268000d7e3eb5e84603810f9a6f971efb1072 (patch) | |
tree | d3518c4a511ac61e6ab33785b7d9a39a04f5bc7d | |
parent | de260ae2ea8809b992b113d5f37b2dac38b2abcf (diff) | |
download | gtk+-de2268000d7e3eb5e84603810f9a6f971efb1072.tar.gz |
wayland: Ensure device grabs generate crossing/focus events
On X11 this is something the windowing system does for us, which the
wayland backend should emulate, being grabs completely client-side.
So, if the grab and current focus windows differ, make sure we emit
focus/crossing events as it corresponds to the grab device.
-rw-r--r-- | gdk/wayland/gdkdevice-wayland.c | 94 |
1 files changed, 93 insertions, 1 deletions
diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c index 45ba21b6da..345266f554 100644 --- a/gdk/wayland/gdkdevice-wayland.c +++ b/gdk/wayland/gdkdevice-wayland.c @@ -353,6 +353,85 @@ gdk_wayland_device_query_state (GdkDevice *device, get_coordinates (wd, win_x, win_y, root_x, root_y); } +static void +emulate_crossing (GdkWindow *window, + GdkWindow *subwindow, + GdkDevice *device, + GdkEventType type, + GdkCrossingMode mode, + guint32 time_) +{ + GdkEvent *event; + + event = gdk_event_new (type); + event->crossing.window = window ? g_object_ref (window) : NULL; + event->crossing.subwindow = subwindow ? g_object_ref (subwindow) : NULL; + event->crossing.time = time_; + event->crossing.mode = mode; + event->crossing.detail = GDK_NOTIFY_NONLINEAR; + gdk_event_set_device (event, device); + gdk_event_set_source_device (event, device); + + gdk_window_get_device_position_double (window, device, + &event->crossing.x, &event->crossing.y, + &event->crossing.state); + event->crossing.x_root = event->crossing.x; + event->crossing.y_root = event->crossing.y; + + _gdk_wayland_display_deliver_event (gdk_window_get_display (window), event); +} + +static void +emulate_focus (GdkWindow *window, + GdkDevice *device, + gboolean focus_in, + guint32 time_) +{ + GdkEvent *event; + + event = gdk_event_new (GDK_FOCUS_CHANGE); + event->focus_change.window = g_object_ref (window); + event->focus_change.in = focus_in; + gdk_event_set_device (event, device); + gdk_event_set_source_device (event, device); + + _gdk_wayland_display_deliver_event (gdk_window_get_display (window), event); +} + +static void +device_emit_grab_crossing (GdkDevice *device, + GdkWindow *from, + GdkWindow *to, + GdkCrossingMode mode, + guint32 time_) +{ + if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) + { + if (from) + emulate_focus (from, device, FALSE, time_); + if (to) + emulate_focus (to, device, TRUE, time_); + } + else + { + if (from) + emulate_crossing (from, to, device, GDK_LEAVE_NOTIFY, mode, time_); + if (to) + emulate_crossing (to, from, device, GDK_ENTER_NOTIFY, mode, time_); + } +} + +static GdkWindow * +gdk_wayland_device_get_focus (GdkDevice *device) +{ + GdkWaylandDeviceData *wayland_device = GDK_WAYLAND_DEVICE (device)->device; + + if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) + return wayland_device->keyboard_focus; + else + return wayland_device->pointer_focus; +} + static GdkGrabStatus gdk_wayland_device_grab (GdkDevice *device, GdkWindow *window, @@ -363,6 +442,10 @@ gdk_wayland_device_grab (GdkDevice *device, guint32 time_) { GdkWaylandDeviceData *wayland_device = GDK_WAYLAND_DEVICE (device)->device; + GdkWindow *prev_focus = gdk_wayland_device_get_focus (device); + + if (prev_focus != window) + device_emit_grab_crossing (device, prev_focus, window, GDK_CROSSING_GRAB, time_); if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) { @@ -412,13 +495,22 @@ gdk_wayland_device_ungrab (GdkDevice *device, GdkWaylandDeviceData *wayland_device = GDK_WAYLAND_DEVICE (device)->device; GdkDisplay *display; GdkDeviceGrabInfo *grab; + GdkWindow *focus, *prev_focus = NULL; display = gdk_device_get_display (device); grab = _gdk_display_get_last_device_grab (display, device); if (grab) - grab->serial_end = grab->serial_start; + { + grab->serial_end = grab->serial_start; + prev_focus = grab->window; + } + + 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) { |