summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2015-06-24 17:48:18 +0200
committerCarlos Garnacho <carlosg@gnome.org>2015-06-24 18:15:46 +0200
commitde2268000d7e3eb5e84603810f9a6f971efb1072 (patch)
treed3518c4a511ac61e6ab33785b7d9a39a04f5bc7d
parentde260ae2ea8809b992b113d5f37b2dac38b2abcf (diff)
downloadgtk+-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.c94
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)
{