gdk/wayland: "Split" GdkWaylandDevice implementation out
authorCarlos Garnacho <carlosg@gnome.org>
Fri, 3 Feb 2023 14:55:09 +0000 (15:55 +0100)
committerCarlos Garnacho <carlosg@gnome.org>
Fri, 3 Feb 2023 15:15:34 +0000 (16:15 +0100)
This is a bit spaghetti right now, since seats and devices were
heavily entangled there are a number of crossed private API calls that
should ideally not be there.

Let this be a first step, so more bits may move from the seat
implementation to devices.

gdk/wayland/gdkdevice-wayland-private.h
gdk/wayland/gdkdevice-wayland.c [new file with mode: 0644]
gdk/wayland/gdkseat-wayland.c
gdk/wayland/meson.build

index 5f43cd1fda50212c370e4903c80c1efe667db5e9..233270b4a3ea70d0ed45bc60b13c9e48d30f70db 100644 (file)
@@ -220,6 +220,19 @@ struct _GdkWaylandSeat
 #define GDK_TYPE_WAYLAND_DEVICE_PAD (gdk_wayland_device_pad_get_type ())
 GType gdk_wayland_device_pad_get_type (void);
 
+void gdk_wayland_seat_stop_cursor_animation (GdkWaylandSeat        *seat,
+                                             GdkWaylandPointerData *pointer);
+
+GdkWaylandPointerData * gdk_wayland_device_get_pointer (GdkWaylandDevice *wayland_device);
+
+void gdk_wayland_device_set_pointer (GdkWaylandDevice      *wayland_device,
+                                     GdkWaylandPointerData *pointer);
+
+GdkWaylandTouchData * gdk_wayland_device_get_emulating_touch (GdkWaylandDevice *wayland_device);
+
+void gdk_wayland_device_set_emulating_touch (GdkWaylandDevice    *wayland_device,
+                                             GdkWaylandTouchData *touch);
+
 void gdk_wayland_device_query_state (GdkDevice        *device,
                                      GdkSurface       *surface,
                                      double           *win_x,
@@ -234,4 +247,21 @@ void gdk_wayland_device_pad_set_feedback (GdkDevice           *device,
 GdkWaylandTabletPadData * gdk_wayland_seat_find_pad (GdkWaylandSeat *seat,
                                                      GdkDevice      *device);
 
+GdkWaylandTabletData * gdk_wayland_seat_find_tablet (GdkWaylandSeat *seat,
+                                                     GdkDevice      *device);
+
+GdkWaylandTouchData * gdk_wayland_seat_get_touch (GdkWaylandSeat *seat,
+                                                  uint32_t        id);
+
+void gdk_wayland_device_maybe_emit_grab_crossing (GdkDevice  *device,
+                                                  GdkSurface *window,
+                                                  guint32     time);
+
+GdkSurface * gdk_wayland_device_maybe_emit_ungrab_crossing (GdkDevice *device,
+                                                            guint32    time_);
+
+gboolean gdk_wayland_device_update_surface_cursor (GdkDevice *device);
+
+GdkModifierType gdk_wayland_device_get_modifiers (GdkDevice *device);
+
 #endif
diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c
new file mode 100644 (file)
index 0000000..9cb3cfb
--- /dev/null
@@ -0,0 +1,745 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gdkdevice-wayland-private.h"
+#include "gdkprivate-wayland.h"
+#include "gdkcursorprivate.h"
+#include "gdkeventsprivate.h"
+
+#define GDK_SLOT_TO_EVENT_SEQUENCE(s) ((GdkEventSequence *) GUINT_TO_POINTER((s) + 1))
+#define GDK_EVENT_SEQUENCE_TO_SLOT(s) (GPOINTER_TO_UINT(s) - 1)
+
+typedef struct
+{
+  GdkWaylandTouchData *emulating_touch; /* Only used on wd->logical_touch */
+  GdkWaylandPointerData *pointer;
+} GdkWaylandDevicePrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GdkWaylandDevice, gdk_wayland_device, GDK_TYPE_DEVICE)
+
+static void
+gdk_wayland_device_set_surface_cursor (GdkDevice  *device,
+                                       GdkSurface *surface,
+                                       GdkCursor  *cursor)
+{
+  GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
+  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
+  GdkWaylandPointerData *pointer =
+    gdk_wayland_device_get_pointer (wayland_device);
+
+  if (device == seat->logical_touch)
+    return;
+
+  if (seat->grab_cursor)
+    cursor = seat->grab_cursor;
+
+  if (pointer->cursor != NULL &&
+      cursor != NULL &&
+      gdk_cursor_equal (cursor, pointer->cursor))
+    return;
+
+  if (cursor == NULL)
+    {
+      if (!pointer->cursor_is_default)
+        {
+          g_clear_object (&pointer->cursor);
+          pointer->cursor = gdk_cursor_new_from_name ("default", NULL);
+          pointer->cursor_is_default = TRUE;
+
+          gdk_wayland_seat_stop_cursor_animation (seat, pointer);
+          gdk_wayland_device_update_surface_cursor (device);
+        }
+      else
+        {
+          /* Nothing to do, we'already using the default cursor */
+        }
+    }
+  else
+    {
+      g_set_object (&pointer->cursor, cursor);
+      pointer->cursor_is_default = FALSE;
+
+      gdk_wayland_seat_stop_cursor_animation (seat, pointer);
+      gdk_wayland_device_update_surface_cursor (device);
+    }
+}
+
+static GdkGrabStatus
+gdk_wayland_device_grab (GdkDevice    *device,
+                         GdkSurface   *surface,
+                         gboolean      owner_events,
+                         GdkEventMask  event_mask,
+                         GdkSurface   *confine_to,
+                         GdkCursor    *cursor,
+                         guint32       time_)
+{
+  GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
+  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
+  GdkWaylandPointerData *pointer =
+    gdk_wayland_device_get_pointer (wayland_device);
+
+  if (GDK_IS_DRAG_SURFACE (surface) &&
+      gdk_surface_get_mapped (surface))
+    {
+      g_warning ("Surface %p is already mapped at the time of grabbing. "
+                 "gdk_seat_grab() should be used to simultaneously grab input "
+                 "and show this popup. You may find oddities ahead.",
+                 surface);
+    }
+
+  gdk_wayland_device_maybe_emit_grab_crossing (device, surface, time_);
+
+  if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
+    {
+      /* Device is a keyboard */
+      gdk_wayland_surface_inhibit_shortcuts (surface,
+                                             gdk_device_get_seat (device));
+      return GDK_GRAB_SUCCESS;
+    }
+  else
+    {
+      /* Device is a pointer */
+      if (pointer->grab_surface != NULL &&
+          time_ != 0 && pointer->grab_time > time_)
+        {
+          return GDK_GRAB_ALREADY_GRABBED;
+        }
+
+      if (time_ == 0)
+        time_ = pointer->time;
+
+      pointer->grab_surface = surface;
+      pointer->grab_time = time_;
+      _gdk_wayland_surface_set_grab_seat (surface, GDK_SEAT (wayland_seat));
+
+      g_clear_object (&wayland_seat->cursor);
+
+      if (cursor)
+        wayland_seat->cursor = g_object_ref (cursor);
+
+      gdk_wayland_device_update_surface_cursor (device);
+    }
+
+  return GDK_GRAB_SUCCESS;
+}
+
+static void
+gdk_wayland_device_ungrab (GdkDevice *device,
+                           guint32    time_)
+{
+  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
+  GdkWaylandPointerData *pointer =
+    gdk_wayland_device_get_pointer (wayland_device);
+  GdkSurface *prev_focus;
+
+  prev_focus = gdk_wayland_device_maybe_emit_ungrab_crossing (device, time_);
+
+  if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
+    {
+      /* Device is a keyboard */
+      if (prev_focus)
+        gdk_wayland_surface_restore_shortcuts (prev_focus,
+                                              gdk_device_get_seat (device));
+    }
+  else
+    {
+      /* Device is a pointer */
+      gdk_wayland_device_update_surface_cursor (device);
+
+      if (pointer->grab_surface)
+        _gdk_wayland_surface_set_grab_seat (pointer->grab_surface,
+                                           NULL);
+    }
+}
+
+static GdkSurface *
+gdk_wayland_device_surface_at_position (GdkDevice       *device,
+                                        double          *win_x,
+                                        double          *win_y,
+                                        GdkModifierType *mask)
+{
+  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
+  GdkWaylandPointerData *pointer;
+
+  pointer = gdk_wayland_device_get_pointer (wayland_device);
+
+  if (!pointer)
+    return NULL;
+
+  if (win_x)
+    *win_x = pointer->surface_x;
+  if (win_y)
+    *win_y = pointer->surface_y;
+  if (mask)
+    *mask = gdk_wayland_device_get_modifiers (device);
+
+  return pointer->focus;
+}
+
+static void
+gdk_wayland_device_class_init (GdkWaylandDeviceClass *klass)
+{
+  GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
+
+  device_class->set_surface_cursor = gdk_wayland_device_set_surface_cursor;
+  device_class->grab = gdk_wayland_device_grab;
+  device_class->ungrab = gdk_wayland_device_ungrab;
+  device_class->surface_at_position = gdk_wayland_device_surface_at_position;
+}
+
+static void
+gdk_wayland_device_init (GdkWaylandDevice *device_core)
+{
+  GdkDevice *device;
+
+  device = GDK_DEVICE (device_core);
+
+  _gdk_device_add_axis (device, GDK_AXIS_X, 0, 0, 1);
+  _gdk_device_add_axis (device, GDK_AXIS_Y, 0, 0, 1);
+}
+
+GdkWaylandPointerData *
+gdk_wayland_device_get_pointer (GdkWaylandDevice *wayland_device)
+{
+  GdkWaylandDevicePrivate *priv =
+    gdk_wayland_device_get_instance_private (wayland_device);
+
+  return priv->pointer;
+}
+
+void
+gdk_wayland_device_set_pointer (GdkWaylandDevice      *wayland_device,
+                                GdkWaylandPointerData *pointer)
+{
+  GdkWaylandDevicePrivate *priv =
+    gdk_wayland_device_get_instance_private (wayland_device);
+
+  priv->pointer = pointer;
+}
+
+GdkWaylandTouchData *
+gdk_wayland_device_get_emulating_touch (GdkWaylandDevice *wayland_device)
+{
+  GdkWaylandDevicePrivate *priv =
+    gdk_wayland_device_get_instance_private (wayland_device);
+
+  return priv->emulating_touch;
+}
+
+void
+gdk_wayland_device_set_emulating_touch (GdkWaylandDevice    *wayland_device,
+                                        GdkWaylandTouchData *touch)
+{
+  GdkWaylandDevicePrivate *priv =
+    gdk_wayland_device_get_instance_private (wayland_device);
+
+  priv->emulating_touch = touch;
+}
+
+gboolean
+gdk_wayland_device_update_surface_cursor (GdkDevice *device)
+{
+  GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
+  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
+  GdkWaylandPointerData *pointer =
+    gdk_wayland_device_get_pointer (wayland_device);
+  struct wl_buffer *buffer;
+  int x, y, w, h, scale;
+  guint next_image_index, next_image_delay;
+  gboolean retval = G_SOURCE_REMOVE;
+  GdkWaylandTabletData *tablet;
+
+  tablet = gdk_wayland_seat_find_tablet (seat, device);
+
+  if (pointer->cursor)
+    {
+      buffer = _gdk_wayland_cursor_get_buffer (GDK_WAYLAND_DISPLAY (seat->display),
+                                               pointer->cursor,
+                                               pointer->current_output_scale,
+                                               pointer->cursor_image_index,
+                                               &x, &y, &w, &h, &scale);
+    }
+  else
+    {
+      pointer->cursor_timeout_id = 0;
+      return G_SOURCE_REMOVE;
+    }
+
+  if (tablet)
+    {
+      if (!tablet->current_tool)
+        {
+          pointer->cursor_timeout_id = 0;
+          return G_SOURCE_REMOVE;
+        }
+
+      zwp_tablet_tool_v2_set_cursor (tablet->current_tool->wp_tablet_tool,
+                                     pointer->enter_serial,
+                                     pointer->pointer_surface,
+                                     x, y);
+    }
+  else if (seat->wl_pointer)
+    {
+      wl_pointer_set_cursor (seat->wl_pointer,
+                             pointer->enter_serial,
+                             pointer->pointer_surface,
+                             x, y);
+    }
+  else
+    {
+      pointer->cursor_timeout_id = 0;
+      return G_SOURCE_REMOVE;
+    }
+
+  if (buffer)
+    {
+      wl_surface_attach (pointer->pointer_surface, buffer, 0, 0);
+      wl_surface_set_buffer_scale (pointer->pointer_surface, scale);
+      wl_surface_damage (pointer->pointer_surface,  0, 0, w, h);
+      wl_surface_commit (pointer->pointer_surface);
+    }
+  else
+    {
+      wl_surface_attach (pointer->pointer_surface, NULL, 0, 0);
+      wl_surface_commit (pointer->pointer_surface);
+    }
+
+  next_image_index =
+    _gdk_wayland_cursor_get_next_image_index (GDK_WAYLAND_DISPLAY (seat->display),
+                                              pointer->cursor,
+                                              pointer->current_output_scale,
+                                              pointer->cursor_image_index,
+                                              &next_image_delay);
+
+  if (next_image_index != pointer->cursor_image_index)
+    {
+      if (next_image_delay != pointer->cursor_image_delay ||
+          pointer->cursor_timeout_id == 0)
+        {
+          guint id;
+          GSource *source;
+
+          gdk_wayland_seat_stop_cursor_animation (seat, pointer);
+
+          /* Queue timeout for next frame */
+          id = g_timeout_add (next_image_delay,
+                              (GSourceFunc) gdk_wayland_device_update_surface_cursor,
+                              device);
+          source = g_main_context_find_source_by_id (NULL, id);
+          g_source_set_static_name (source, "[gtk] gdk_wayland_device_update_surface_cursor");
+          pointer->cursor_timeout_id = id;
+        }
+      else
+        retval = G_SOURCE_CONTINUE;
+
+      pointer->cursor_image_index = next_image_index;
+      pointer->cursor_image_delay = next_image_delay;
+    }
+  else
+    gdk_wayland_seat_stop_cursor_animation (seat, pointer);
+
+  return retval;
+}
+
+GdkModifierType
+gdk_wayland_device_get_modifiers (GdkDevice *device)
+{
+  GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
+  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
+  GdkWaylandPointerData *pointer =
+    gdk_wayland_device_get_pointer (wayland_device);
+  GdkModifierType mask;
+
+  mask = seat->key_modifiers;
+
+  if (pointer)
+    mask |= pointer->button_modifiers;
+
+  return mask;
+}
+
+void
+gdk_wayland_device_query_state (GdkDevice        *device,
+                                GdkSurface       *surface,
+                                double           *win_x,
+                                double           *win_y,
+                                GdkModifierType  *mask)
+{
+  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
+  GdkWaylandPointerData *pointer;
+  double x, y;
+
+  if (mask)
+    *mask = gdk_wayland_device_get_modifiers (device);
+
+  pointer = gdk_wayland_device_get_pointer (wayland_device);
+
+  if (pointer->focus == surface)
+    {
+      x = pointer->surface_x;
+      y = pointer->surface_y;
+    }
+  else
+    {
+      x = y = -1;
+    }
+
+  if (win_x)
+    *win_x = x;
+  if (win_y)
+    *win_y = y;
+}
+
+GdkSurface *
+gdk_wayland_device_get_focus (GdkDevice *device)
+{
+  GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
+  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
+  GdkWaylandPointerData *pointer;
+
+  if (device == wayland_seat->logical_keyboard)
+    return wayland_seat->keyboard_focus;
+  else
+    {
+      pointer = gdk_wayland_device_get_pointer (wayland_device);
+
+      if (pointer)
+        return pointer->focus;
+    }
+
+  return NULL;
+}
+
+static void
+emulate_touch_crossing (GdkSurface           *surface,
+                        GdkSurface           *child_surface,
+                        GdkDevice           *device,
+                        GdkDevice           *source,
+                        GdkWaylandTouchData *touch,
+                        GdkEventType         type,
+                        GdkCrossingMode      mode,
+                        guint32              time_)
+{
+  GdkEvent *event;
+
+  event = gdk_crossing_event_new (type,
+                                  surface,
+                                  device,
+                                  time_,
+                                  0,
+                                  touch->x, touch->y,
+                                  mode,
+                                  GDK_NOTIFY_NONLINEAR);
+
+  _gdk_wayland_display_deliver_event (gdk_surface_get_display (surface), event);
+}
+
+void
+gdk_wayland_device_unset_touch_grab (GdkDevice        *gdk_device,
+                                     GdkEventSequence *sequence)
+{
+  GdkWaylandSeat *seat;
+  GdkWaylandTouchData *touch;
+  GdkEvent *event;
+
+  g_return_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device));
+
+  seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (gdk_device));
+  touch = gdk_wayland_seat_get_touch (seat,
+                                      GDK_EVENT_SEQUENCE_TO_SLOT (sequence));
+
+  if (touch ==
+      gdk_wayland_device_get_emulating_touch (GDK_WAYLAND_DEVICE (seat->logical_touch)))
+    {
+      gdk_wayland_device_set_emulating_touch (GDK_WAYLAND_DEVICE (seat->logical_touch),
+                                              NULL);
+      emulate_touch_crossing (touch->surface, NULL,
+                              seat->logical_touch, seat->touch,
+                              touch, GDK_LEAVE_NOTIFY, GDK_CROSSING_NORMAL,
+                              GDK_CURRENT_TIME);
+    }
+
+  event = gdk_touch_event_new (GDK_TOUCH_CANCEL,
+                               GDK_SLOT_TO_EVENT_SEQUENCE (touch->id),
+                               touch->surface,
+                               seat->logical_touch,
+                               GDK_CURRENT_TIME,
+                               gdk_wayland_device_get_modifiers (seat->logical_touch),
+                               touch->x, touch->y,
+                               NULL,
+                               touch->initial_touch);
+  _gdk_wayland_display_deliver_event (seat->display, event);
+}
+
+/**
+ * gdk_wayland_device_get_wl_seat: (skip)
+ * @device: (type GdkWaylandDevice): a `GdkDevice`
+ *
+ * Returns the Wayland `wl_seat` of a `GdkDevice`.
+ *
+ * Returns: (transfer none): a Wayland `wl_seat`
+ */
+struct wl_seat *
+gdk_wayland_device_get_wl_seat (GdkDevice *device)
+{
+  GdkWaylandSeat *seat;
+
+  g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (device), NULL);
+
+  seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
+  return seat->wl_seat;
+}
+
+/**
+ * gdk_wayland_device_get_wl_pointer: (skip)
+ * @device: (type GdkWaylandDevice): a `GdkDevice`
+ *
+ * Returns the Wayland `wl_pointer` of a `GdkDevice`.
+ *
+ * Returns: (transfer none): a Wayland `wl_pointer`
+ */
+struct wl_pointer *
+gdk_wayland_device_get_wl_pointer (GdkDevice *device)
+{
+  GdkWaylandSeat *seat;
+
+  g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (device), NULL);
+
+  seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
+  return seat->wl_pointer;
+}
+
+/**
+ * gdk_wayland_device_get_wl_keyboard: (skip)
+ * @device: (type GdkWaylandDevice): a `GdkDevice`
+ *
+ * Returns the Wayland `wl_keyboard` of a `GdkDevice`.
+ *
+ * Returns: (transfer none): a Wayland `wl_keyboard`
+ */
+struct wl_keyboard *
+gdk_wayland_device_get_wl_keyboard (GdkDevice *device)
+{
+  GdkWaylandSeat *seat;
+
+  g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (device), NULL);
+
+  seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
+  return seat->wl_keyboard;
+}
+
+/**
+ * gdk_wayland_device_get_xkb_keymap:
+ * @device: (type GdkWaylandDevice): a `GdkDevice`
+ *
+ * Returns the `xkb_keymap` of a `GdkDevice`.
+ *
+ * Returns: (transfer none): a `struct xkb_keymap`
+ *
+ * Since: 4.4
+ */
+struct xkb_keymap *
+gdk_wayland_device_get_xkb_keymap (GdkDevice *device)
+{
+  GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
+  return _gdk_wayland_keymap_get_xkb_keymap (seat->keymap);
+}
+
+GdkKeymap *
+_gdk_wayland_device_get_keymap (GdkDevice *device)
+{
+  GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
+  return seat->keymap;
+}
+
+/**
+ * gdk_wayland_device_get_data_device: (skip)
+ * @gdk_device: (type GdkWaylandDevice): a `GdkDevice`
+ *
+ * Returns the Wayland `wl_data_device` of a `GdkDevice`.
+ *
+ * Returns: (transfer none): a Wayland `wl_data_device`
+ */
+struct wl_data_device *
+gdk_wayland_device_get_data_device (GdkDevice *gdk_device)
+{
+  GdkWaylandSeat *seat;
+
+  g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device), NULL);
+
+  seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (gdk_device));
+  return seat->data_device;
+}
+
+/**
+ * gdk_wayland_device_set_selection: (skip)
+ * @gdk_device: (type GdkWaylandDevice): a `GdkDevice`
+ * @source: the data source for the selection
+ *
+ * Sets the selection of the `GdkDevice.
+ *
+ * This is calling wl_data_device_set_selection() on
+ * the `wl_data_device` of @gdk_device.
+ */
+void
+gdk_wayland_device_set_selection (GdkDevice             *gdk_device,
+                                  struct wl_data_source *source)
+{
+  GdkWaylandSeat *seat;
+  guint32 serial;
+
+  g_return_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device));
+
+  seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (gdk_device));
+  serial = _gdk_wayland_seat_get_last_implicit_grab_serial (seat, NULL);
+  wl_data_device_set_selection (seat->data_device, source, serial);
+}
+
+/**
+ * gdk_wayland_device_get_node_path:
+ * @device: (type GdkWaylandDevice): a `GdkDevice`
+ *
+ * Returns the `/dev/input/event*` path of this device.
+ *
+ * For `GdkDevice`s that possibly coalesce multiple hardware
+ * devices (eg. mouse, keyboard, touch,...), this function
+ * will return %NULL.
+ *
+ * This is most notably implemented for devices of type
+ * %GDK_SOURCE_PEN, %GDK_SOURCE_TABLET_PAD.
+ *
+ * Returns: (nullable) (transfer none): the `/dev/input/event*`
+ *   path of this device
+ */
+const char *
+gdk_wayland_device_get_node_path (GdkDevice *device)
+{
+  GdkWaylandTabletData *tablet;
+  GdkWaylandTabletPadData *pad;
+
+  GdkSeat *seat;
+
+  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
+
+  seat = gdk_device_get_seat (device);
+  tablet = gdk_wayland_seat_find_tablet (GDK_WAYLAND_SEAT (seat), device);
+  if (tablet)
+    return tablet->path;
+
+  pad = gdk_wayland_seat_find_pad (GDK_WAYLAND_SEAT (seat), device);
+  if (pad)
+    return pad->path;
+
+  return NULL;
+}
+
+static void
+emulate_focus (GdkSurface *surface,
+               GdkDevice *device,
+               gboolean   focus_in,
+               guint32    time_)
+{
+  GdkEvent *event = gdk_focus_event_new (surface, device, focus_in);
+
+  _gdk_wayland_display_deliver_event (gdk_surface_get_display (surface), event);
+}
+
+static void
+emulate_crossing (GdkSurface       *surface,
+                  GdkSurface       *child_surface,
+                  GdkDevice       *device,
+                  GdkEventType     type,
+                  GdkCrossingMode  mode,
+                  guint32          time_)
+{
+  GdkEvent *event;
+  GdkModifierType state;
+  double x, y;
+
+  gdk_surface_get_device_position (surface, device, &x, &y, &state);
+  event = gdk_crossing_event_new (type,
+                                  surface,
+                                  device,
+                                  time_,
+                                  state,
+                                  x, y,
+                                  mode,
+                                  GDK_NOTIFY_NONLINEAR);
+
+  _gdk_wayland_display_deliver_event (gdk_surface_get_display (surface), event);
+}
+
+static void
+device_emit_grab_crossing (GdkDevice       *device,
+                           GdkSurface       *from,
+                           GdkSurface       *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_);
+    }
+}
+
+void
+gdk_wayland_device_maybe_emit_grab_crossing (GdkDevice  *device,
+                                             GdkSurface *window,
+                                             guint32     time)
+{
+  GdkSurface *surface = gdk_wayland_device_get_focus (device);
+  GdkSurface *focus = window;
+
+  if (focus != surface)
+    device_emit_grab_crossing (device, focus, window, GDK_CROSSING_GRAB, time);
+}
+
+GdkSurface*
+gdk_wayland_device_maybe_emit_ungrab_crossing (GdkDevice *device,
+                                               guint32    time_)
+{
+  GdkDeviceGrabInfo *grab;
+  GdkSurface *focus = NULL;
+  GdkSurface *surface = 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)
+    {
+      prev_focus = grab->surface;
+      surface = grab->surface;
+    }
+
+  if (focus != surface)
+    device_emit_grab_crossing (device, prev_focus, focus, GDK_CROSSING_UNGRAB, time_);
+
+  return prev_focus;
+}
index a5e1ca95f6c1da3ea2b242aa486c9d7975380287..d3e31a49201c94593d2c233853434361b45be592 100644 (file)
 
 G_DEFINE_TYPE (GdkWaylandSeat, gdk_wayland_seat, GDK_TYPE_SEAT)
 
-typedef struct
-{
-  GdkWaylandTouchData *emulating_touch; /* Only used on wd->logical_touch */
-  GdkWaylandPointerData *pointer;
-} GdkWaylandDevicePrivate;
-
-G_DEFINE_TYPE_WITH_PRIVATE (GdkWaylandDevice, gdk_wayland_device, GDK_TYPE_DEVICE)
-
 static void init_pointer_data (GdkWaylandPointerData *pointer_data,
                                GdkDisplay            *display_wayland,
                                GdkDevice             *logical_device);
@@ -113,8 +105,9 @@ static void deliver_key_event (GdkWaylandSeat       *seat,
                                uint32_t              state,
                                gboolean              from_key_repeat);
 
-static void
-gdk_wayland_pointer_stop_cursor_animation (GdkWaylandPointerData *pointer)
+void
+gdk_wayland_seat_stop_cursor_animation (GdkWaylandSeat        *seat,
+                                        GdkWaylandPointerData *pointer)
 {
   if (pointer->cursor_timeout_id > 0)
     {
@@ -126,7 +119,7 @@ gdk_wayland_pointer_stop_cursor_animation (GdkWaylandPointerData *pointer)
   pointer->cursor_image_index = 0;
 }
 
-static GdkWaylandTabletData *
+GdkWaylandTabletData *
 gdk_wayland_seat_find_tablet (GdkWaylandSeat *seat,
                               GdkDevice      *device)
 {
@@ -161,245 +154,6 @@ gdk_wayland_seat_find_pad (GdkWaylandSeat *seat,
   return NULL;
 }
 
-static GdkWaylandPointerData *
-gdk_wayland_device_get_pointer (GdkWaylandDevice *wayland_device)
-{
-  GdkWaylandDevicePrivate *priv =
-    gdk_wayland_device_get_instance_private (wayland_device);
-
-  return priv->pointer;
-}
-
-static void
-gdk_wayland_device_set_pointer (GdkWaylandDevice      *wayland_device,
-                                GdkWaylandPointerData *pointer)
-{
-  GdkWaylandDevicePrivate *priv =
-    gdk_wayland_device_get_instance_private (wayland_device);
-
-  priv->pointer = pointer;
-}
-
-static GdkWaylandTouchData *
-gdk_wayland_device_get_emulating_touch (GdkWaylandDevice *wayland_device)
-{
-  GdkWaylandDevicePrivate *priv =
-    gdk_wayland_device_get_instance_private (wayland_device);
-
-  return priv->emulating_touch;
-}
-
-static void
-gdk_wayland_device_set_emulating_touch (GdkWaylandDevice    *wayland_device,
-                                        GdkWaylandTouchData *touch)
-{
-  GdkWaylandDevicePrivate *priv =
-    gdk_wayland_device_get_instance_private (wayland_device);
-
-  priv->emulating_touch = touch;
-}
-
-static gboolean
-gdk_wayland_device_update_surface_cursor (GdkDevice *device)
-{
-  GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
-  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
-  GdkWaylandPointerData *pointer =
-    gdk_wayland_device_get_pointer (wayland_device);
-  struct wl_buffer *buffer;
-  int x, y, w, h, scale;
-  guint next_image_index, next_image_delay;
-  gboolean retval = G_SOURCE_REMOVE;
-  GdkWaylandTabletData *tablet;
-
-  tablet = gdk_wayland_seat_find_tablet (seat, device);
-
-  if (pointer->cursor)
-    {
-      buffer = _gdk_wayland_cursor_get_buffer (GDK_WAYLAND_DISPLAY (seat->display),
-                                               pointer->cursor,
-                                               pointer->current_output_scale,
-                                               pointer->cursor_image_index,
-                                               &x, &y, &w, &h, &scale);
-    }
-  else
-    {
-      pointer->cursor_timeout_id = 0;
-      return G_SOURCE_REMOVE;
-    }
-
-  if (tablet)
-    {
-      if (!tablet->current_tool)
-        {
-          pointer->cursor_timeout_id = 0;
-          return G_SOURCE_REMOVE;
-        }
-
-      zwp_tablet_tool_v2_set_cursor (tablet->current_tool->wp_tablet_tool,
-                                     pointer->enter_serial,
-                                     pointer->pointer_surface,
-                                     x, y);
-    }
-  else if (seat->wl_pointer)
-    {
-      wl_pointer_set_cursor (seat->wl_pointer,
-                             pointer->enter_serial,
-                             pointer->pointer_surface,
-                             x, y);
-    }
-  else
-    {
-      pointer->cursor_timeout_id = 0;
-      return G_SOURCE_REMOVE;
-    }
-
-  if (buffer)
-    {
-      wl_surface_attach (pointer->pointer_surface, buffer, 0, 0);
-      wl_surface_set_buffer_scale (pointer->pointer_surface, scale);
-      wl_surface_damage (pointer->pointer_surface,  0, 0, w, h);
-      wl_surface_commit (pointer->pointer_surface);
-    }
-  else
-    {
-      wl_surface_attach (pointer->pointer_surface, NULL, 0, 0);
-      wl_surface_commit (pointer->pointer_surface);
-    }
-
-  next_image_index =
-    _gdk_wayland_cursor_get_next_image_index (GDK_WAYLAND_DISPLAY (seat->display),
-                                              pointer->cursor,
-                                              pointer->current_output_scale,
-                                              pointer->cursor_image_index,
-                                              &next_image_delay);
-
-  if (next_image_index != pointer->cursor_image_index)
-    {
-      if (next_image_delay != pointer->cursor_image_delay ||
-          pointer->cursor_timeout_id == 0)
-        {
-          guint id;
-          GSource *source;
-
-          gdk_wayland_pointer_stop_cursor_animation (pointer);
-
-          /* Queue timeout for next frame */
-          id = g_timeout_add (next_image_delay,
-                              (GSourceFunc) gdk_wayland_device_update_surface_cursor,
-                              device);
-          source = g_main_context_find_source_by_id (NULL, id);
-          g_source_set_static_name (source, "[gtk] gdk_wayland_device_update_surface_cursor");
-          pointer->cursor_timeout_id = id;
-        }
-      else
-        retval = G_SOURCE_CONTINUE;
-
-      pointer->cursor_image_index = next_image_index;
-      pointer->cursor_image_delay = next_image_delay;
-    }
-  else
-    gdk_wayland_pointer_stop_cursor_animation (pointer);
-
-  return retval;
-}
-
-static void
-gdk_wayland_device_set_surface_cursor (GdkDevice  *device,
-                                       GdkSurface *surface,
-                                       GdkCursor  *cursor)
-{
-  GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
-  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
-  GdkWaylandPointerData *pointer =
-    gdk_wayland_device_get_pointer (wayland_device);
-
-  if (device == seat->logical_touch)
-    return;
-
-  if (seat->grab_cursor)
-    cursor = seat->grab_cursor;
-
-  if (pointer->cursor != NULL &&
-      cursor != NULL &&
-      gdk_cursor_equal (cursor, pointer->cursor))
-    return;
-
-  if (cursor == NULL)
-    {
-      if (!pointer->cursor_is_default)
-        {
-          g_clear_object (&pointer->cursor);
-          pointer->cursor = gdk_cursor_new_from_name ("default", NULL);
-          pointer->cursor_is_default = TRUE;
-
-          gdk_wayland_pointer_stop_cursor_animation (pointer);
-          gdk_wayland_device_update_surface_cursor (device);
-        }
-      else
-        {
-          /* Nothing to do, we'already using the default cursor */
-        }
-    }
-  else
-    {
-      g_set_object (&pointer->cursor, cursor);
-      pointer->cursor_is_default = FALSE;
-
-      gdk_wayland_pointer_stop_cursor_animation (pointer);
-      gdk_wayland_device_update_surface_cursor (device);
-    }
-}
-
-static GdkModifierType
-device_get_modifiers (GdkDevice *device)
-{
-  GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
-  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
-  GdkWaylandPointerData *pointer =
-    gdk_wayland_device_get_pointer (wayland_device);
-  GdkModifierType mask;
-
-  mask = seat->key_modifiers;
-
-  if (pointer)
-    mask |= pointer->button_modifiers;
-
-  return mask;
-}
-
-void
-gdk_wayland_device_query_state (GdkDevice        *device,
-                                GdkSurface       *surface,
-                                double           *win_x,
-                                double           *win_y,
-                                GdkModifierType  *mask)
-{
-  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
-  GdkWaylandPointerData *pointer;
-  double x, y;
-
-  if (mask)
-    *mask = device_get_modifiers (device);
-
-  pointer = gdk_wayland_device_get_pointer (wayland_device);
-
-  if (pointer->focus == surface)
-    {
-      x = pointer->surface_x;
-      y = pointer->surface_y;
-    }
-  else
-    {
-      x = y = -1;
-    }
-
-  if (win_x)
-    *win_x = x;
-  if (win_y)
-    *win_y = y;
-}
-
 static void
 emulate_crossing (GdkSurface       *surface,
                   GdkSurface       *child_surface,
@@ -449,311 +203,6 @@ emulate_touch_crossing (GdkSurface           *surface,
   _gdk_wayland_display_deliver_event (gdk_surface_get_display (surface), event);
 }
 
-static void
-emulate_focus (GdkSurface *surface,
-               GdkDevice *device,
-               gboolean   focus_in,
-               guint32    time_)
-{
-  GdkEvent *event = gdk_focus_event_new (surface, device, focus_in);
-
-  _gdk_wayland_display_deliver_event (gdk_surface_get_display (surface), event);
-}
-
-static void
-device_emit_grab_crossing (GdkDevice       *device,
-                           GdkSurface       *from,
-                           GdkSurface       *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_);
-    }
-}
-
-GdkSurface *
-gdk_wayland_device_get_focus (GdkDevice *device)
-{
-  GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
-  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
-  GdkWaylandPointerData *pointer;
-
-  if (device == wayland_seat->logical_keyboard)
-    return wayland_seat->keyboard_focus;
-  else
-    {
-      pointer = gdk_wayland_device_get_pointer (wayland_device);
-
-      if (pointer)
-        return pointer->focus;
-    }
-
-  return NULL;
-}
-
-static void
-device_maybe_emit_grab_crossing (GdkDevice  *device,
-                                 GdkSurface *window,
-                                 guint32     time)
-{
-  GdkSurface *surface = gdk_wayland_device_get_focus (device);
-  GdkSurface *focus = window;
-
-  if (focus != surface)
-    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 *surface = 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)
-    {
-      prev_focus = grab->surface;
-      surface = grab->surface;
-    }
-
-  if (focus != surface)
-    device_emit_grab_crossing (device, prev_focus, focus, GDK_CROSSING_UNGRAB, time_);
-
-  return prev_focus;
-}
-
-static GdkGrabStatus
-gdk_wayland_device_grab (GdkDevice    *device,
-                         GdkSurface   *surface,
-                         gboolean      owner_events,
-                         GdkEventMask  event_mask,
-                         GdkSurface   *confine_to,
-                         GdkCursor    *cursor,
-                         guint32       time_)
-{
-  GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
-  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
-  GdkWaylandPointerData *pointer =
-    gdk_wayland_device_get_pointer (wayland_device);
-
-  if (GDK_IS_DRAG_SURFACE (surface) &&
-      gdk_surface_get_mapped (surface))
-    {
-      g_warning ("Surface %p is already mapped at the time of grabbing. "
-                 "gdk_seat_grab() should be used to simultaneously grab input "
-                 "and show this popup. You may find oddities ahead.",
-                 surface);
-    }
-
-  device_maybe_emit_grab_crossing (device, surface, time_);
-
-  if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
-    {
-      /* Device is a keyboard */
-      gdk_wayland_surface_inhibit_shortcuts (surface,
-                                             gdk_device_get_seat (device));
-      return GDK_GRAB_SUCCESS;
-    }
-  else
-    {
-      /* Device is a pointer */
-      if (pointer->grab_surface != NULL &&
-          time_ != 0 && pointer->grab_time > time_)
-        {
-          return GDK_GRAB_ALREADY_GRABBED;
-        }
-
-      if (time_ == 0)
-        time_ = pointer->time;
-
-      pointer->grab_surface = surface;
-      pointer->grab_time = time_;
-      _gdk_wayland_surface_set_grab_seat (surface, GDK_SEAT (wayland_seat));
-
-      g_clear_object (&wayland_seat->cursor);
-
-      if (cursor)
-        wayland_seat->cursor = g_object_ref (cursor);
-
-      gdk_wayland_device_update_surface_cursor (device);
-    }
-
-  return GDK_GRAB_SUCCESS;
-}
-
-static void
-gdk_wayland_device_ungrab (GdkDevice *device,
-                           guint32    time_)
-{
-  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
-  GdkWaylandPointerData *pointer =
-    gdk_wayland_device_get_pointer (wayland_device);
-  GdkSurface *prev_focus;
-
-  prev_focus = device_maybe_emit_ungrab_crossing (device, time_);
-
-  if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
-    {
-      /* Device is a keyboard */
-      if (prev_focus)
-        gdk_wayland_surface_restore_shortcuts (prev_focus,
-                                              gdk_device_get_seat (device));
-    }
-  else
-    {
-      /* Device is a pointer */
-      gdk_wayland_device_update_surface_cursor (device);
-
-      if (pointer->grab_surface)
-        _gdk_wayland_surface_set_grab_seat (pointer->grab_surface,
-                                           NULL);
-    }
-}
-
-static GdkSurface *
-gdk_wayland_device_surface_at_position (GdkDevice       *device,
-                                        double          *win_x,
-                                        double          *win_y,
-                                        GdkModifierType *mask)
-{
-  GdkWaylandDevice *wayland_device = GDK_WAYLAND_DEVICE (device);
-  GdkWaylandPointerData *pointer;
-
-  pointer = gdk_wayland_device_get_pointer (wayland_device);
-
-  if (!pointer)
-    return NULL;
-
-  if (win_x)
-    *win_x = pointer->surface_x;
-  if (win_y)
-    *win_y = pointer->surface_y;
-  if (mask)
-    *mask = device_get_modifiers (device);
-
-  return pointer->focus;
-}
-
-static void
-gdk_wayland_device_class_init (GdkWaylandDeviceClass *klass)
-{
-  GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
-
-  device_class->set_surface_cursor = gdk_wayland_device_set_surface_cursor;
-  device_class->grab = gdk_wayland_device_grab;
-  device_class->ungrab = gdk_wayland_device_ungrab;
-  device_class->surface_at_position = gdk_wayland_device_surface_at_position;
-}
-
-static void
-gdk_wayland_device_init (GdkWaylandDevice *device_core)
-{
-  GdkDevice *device;
-
-  device = GDK_DEVICE (device_core);
-
-  _gdk_device_add_axis (device, GDK_AXIS_X, 0, 0, 1);
-  _gdk_device_add_axis (device, GDK_AXIS_Y, 0, 0, 1);
-}
-
-/**
- * gdk_wayland_device_get_wl_seat: (skip)
- * @device: (type GdkWaylandDevice): a `GdkDevice`
- *
- * Returns the Wayland `wl_seat` of a `GdkDevice`.
- *
- * Returns: (transfer none): a Wayland `wl_seat`
- */
-struct wl_seat *
-gdk_wayland_device_get_wl_seat (GdkDevice *device)
-{
-  GdkWaylandSeat *seat;
-
-  g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (device), NULL);
-
-  seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
-  return seat->wl_seat;
-}
-
-/**
- * gdk_wayland_device_get_wl_pointer: (skip)
- * @device: (type GdkWaylandDevice): a `GdkDevice`
- *
- * Returns the Wayland `wl_pointer` of a `GdkDevice`.
- *
- * Returns: (transfer none): a Wayland `wl_pointer`
- */
-struct wl_pointer *
-gdk_wayland_device_get_wl_pointer (GdkDevice *device)
-{
-  GdkWaylandSeat *seat;
-
-  g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (device), NULL);
-
-  seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
-  return seat->wl_pointer;
-}
-
-/**
- * gdk_wayland_device_get_wl_keyboard: (skip)
- * @device: (type GdkWaylandDevice): a `GdkDevice`
- *
- * Returns the Wayland `wl_keyboard` of a `GdkDevice`.
- *
- * Returns: (transfer none): a Wayland `wl_keyboard`
- */
-struct wl_keyboard *
-gdk_wayland_device_get_wl_keyboard (GdkDevice *device)
-{
-  GdkWaylandSeat *seat;
-
-  g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (device), NULL);
-
-  seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
-  return seat->wl_keyboard;
-}
-
-/**
- * gdk_wayland_device_get_xkb_keymap:
- * @device: (type GdkWaylandDevice): a `GdkDevice`
- *
- * Returns the `xkb_keymap` of a `GdkDevice`.
- *
- * Returns: (transfer none): a `struct xkb_keymap`
- *
- * Since: 4.4
- */
-struct xkb_keymap *
-gdk_wayland_device_get_xkb_keymap (GdkDevice *device)
-{
-  GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
-  return _gdk_wayland_keymap_get_xkb_keymap (seat->keymap);
-}
-
-GdkKeymap *
-_gdk_wayland_device_get_keymap (GdkDevice *device)
-{
-  GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
-  return seat->keymap;
-}
-
 static void
 gdk_wayland_seat_discard_pending_offer (GdkWaylandSeat *seat)
 {
@@ -1096,7 +545,7 @@ flush_discrete_scroll_event (GdkWaylandSeat     *seat,
                                              source,
                                              NULL,
                                              seat->pointer_info.time,
-                                             device_get_modifiers (seat->logical_pointer),
+                                             gdk_wayland_device_get_modifiers (seat->logical_pointer),
                                              direction,
                                              value120_x,
                                              value120_y);
@@ -1112,7 +561,7 @@ flush_discrete_scroll_event (GdkWaylandSeat     *seat,
                                                  source,
                                                  NULL,
                                                  seat->pointer_info.time,
-                                                 device_get_modifiers (seat->logical_pointer),
+                                                 gdk_wayland_device_get_modifiers (seat->logical_pointer),
                                                  direction);
         }
     }
@@ -1135,7 +584,7 @@ flush_smooth_scroll_event (GdkWaylandSeat *seat,
                                 source,
                                 NULL,
                                 seat->pointer_info.time,
-                                device_get_modifiers (seat->logical_pointer),
+                                gdk_wayland_device_get_modifiers (seat->logical_pointer),
                                 delta_x, delta_y,
                                 is_stop,
                                 GDK_SCROLL_UNIT_SURFACE);
@@ -1307,7 +756,7 @@ pointer_handle_leave (void              *data,
   g_object_unref (seat->pointer_info.focus);
   seat->pointer_info.focus = NULL;
   if (seat->cursor)
-    gdk_wayland_pointer_stop_cursor_animation (&seat->pointer_info);
+    gdk_wayland_seat_stop_cursor_animation (seat, &seat->pointer_info);
 
   if (display_wayland->seat_version < WL_POINTER_HAS_FRAME)
     gdk_wayland_seat_flush_frame_event (seat);
@@ -1335,7 +784,7 @@ pointer_handle_motion (void              *data,
                                 seat->logical_pointer,
                                 NULL,
                                 time,
-                                device_get_modifiers (seat->logical_pointer),
+                                gdk_wayland_device_get_modifiers (seat->logical_pointer),
                                 seat->pointer_info.surface_x,
                                 seat->pointer_info.surface_y,
                                 NULL);
@@ -1396,7 +845,7 @@ pointer_handle_button (void              *data,
                                 seat->logical_pointer,
                                 NULL,
                                 time,
-                                device_get_modifiers (seat->logical_pointer),
+                                gdk_wayland_device_get_modifiers (seat->logical_pointer),
                                 gdk_button,
                                 seat->pointer_info.surface_x,
                                 seat->pointer_info.surface_y,
@@ -1902,7 +1351,7 @@ deliver_key_event (GdkWaylandSeat *seat,
                              seat->logical_keyboard,
                              time_,
                              key,
-                             device_get_modifiers (seat->logical_pointer),
+                             gdk_wayland_device_get_modifiers (seat->logical_pointer),
                              _gdk_wayland_keymap_key_is_modifier (keymap, key),
                              &translated,
                              &no_lock,
@@ -2126,7 +1575,7 @@ gdk_wayland_seat_add_touch (GdkWaylandSeat    *seat,
   return touch;
 }
 
-static GdkWaylandTouchData *
+GdkWaylandTouchData *
 gdk_wayland_seat_get_touch (GdkWaylandSeat *seat,
                             uint32_t        id)
 {
@@ -2224,7 +1673,7 @@ touch_handle_down (void              *data,
                                touch->surface,
                                seat->logical_touch,
                                time,
-                               device_get_modifiers (seat->logical_touch),
+                               gdk_wayland_device_get_modifiers (seat->logical_touch),
                                touch->x, touch->y,
                                NULL,
                                touch->initial_touch);
@@ -2267,7 +1716,7 @@ touch_handle_up (void            *data,
                                touch->surface,
                                seat->logical_touch,
                                time,
-                               device_get_modifiers (seat->logical_touch),
+                               gdk_wayland_device_get_modifiers (seat->logical_touch),
                                touch->x, touch->y,
                                NULL,
                                touch->initial_touch);
@@ -2315,7 +1764,7 @@ touch_handle_motion (void            *data,
                                touch->surface,
                                seat->logical_touch,
                                time,
-                               device_get_modifiers (seat->logical_touch),
+                               gdk_wayland_device_get_modifiers (seat->logical_touch),
                                touch->x, touch->y,
                                NULL,
                                touch->initial_touch);
@@ -2357,7 +1806,7 @@ touch_handle_cancel (void            *data,
                                    touch->surface,
                                    seat->logical_touch,
                                    GDK_CURRENT_TIME,
-                                   device_get_modifiers (seat->logical_touch),
+                                   gdk_wayland_device_get_modifiers (seat->logical_touch),
                                    touch->x, touch->y,
                                    NULL,
                                    touch->initial_touch);
@@ -2407,7 +1856,7 @@ emit_gesture_swipe_event (GdkWaylandSeat          *seat,
                                         GDK_SLOT_TO_EVENT_SEQUENCE (seat->pointer_info.touchpad_event_sequence),
                                         seat->logical_pointer,
                                         _time,
-                                        device_get_modifiers (seat->logical_pointer),
+                                        gdk_wayland_device_get_modifiers (seat->logical_pointer),
                                         phase,
                                         seat->pointer_info.surface_x,
                                         seat->pointer_info.surface_y,
@@ -2501,7 +1950,7 @@ emit_gesture_pinch_event (GdkWaylandSeat          *seat,
                                         GDK_SLOT_TO_EVENT_SEQUENCE (seat->pointer_info.touchpad_event_sequence),
                                         seat->logical_pointer,
                                         _time,
-                                        device_get_modifiers (seat->logical_pointer),
+                                        gdk_wayland_device_get_modifiers (seat->logical_pointer),
                                         phase,
                                         seat->pointer_info.surface_x,
                                         seat->pointer_info.surface_y,
@@ -2597,7 +2046,7 @@ emit_gesture_hold_event (GdkWaylandSeat          *seat,
                                        GDK_SLOT_TO_EVENT_SEQUENCE (seat->pointer_info.touchpad_event_sequence),
                                        seat->logical_pointer,
                                        _time,
-                                       device_get_modifiers (seat->logical_pointer),
+                                       gdk_wayland_device_get_modifiers (seat->logical_pointer),
                                        phase,
                                        seat->pointer_info.surface_x,
                                        seat->pointer_info.surface_y,
@@ -3417,7 +2866,8 @@ tablet_tool_handle_proximity_out (void                      *data,
                                    tablet->pointer_info.time);
   gdk_wayland_tablet_set_frame_event (tablet, event);
 
-  gdk_wayland_pointer_stop_cursor_animation (&tablet->pointer_info);
+  gdk_wayland_seat_stop_cursor_animation (GDK_WAYLAND_SEAT (tool->seat),
+                                          &tablet->pointer_info);
 
   tablet->pointer_info.pointer_surface_outputs =
     g_slist_remove (tablet->pointer_info.pointer_surface_outputs,
@@ -3453,7 +2903,7 @@ tablet_create_button_event_frame (GdkWaylandTabletData *tablet,
                                 tablet->logical_device,
                                 tablet->current_tool->tool,
                                 tablet->pointer_info.time,
-                                device_get_modifiers (tablet->logical_device),
+                                gdk_wayland_device_get_modifiers (tablet->logical_device),
                                 button,
                                 tablet->pointer_info.surface_x,
                                 tablet->pointer_info.surface_y,
@@ -3517,7 +2967,7 @@ tablet_tool_handle_motion (void                      *data,
                                 tablet->logical_device,
                                 tool->tool,
                                 tablet->pointer_info.time,
-                                device_get_modifiers (tablet->logical_device),
+                                gdk_wayland_device_get_modifiers (tablet->logical_device),
                                 tablet->pointer_info.surface_x,
                                 tablet->pointer_info.surface_y,
                                 tablet_copy_axes (tablet));
@@ -3709,7 +3159,7 @@ tablet_tool_handle_wheel (void                      *data,
                                 tablet->logical_device,
                                 tablet->current_tool->tool,
                                 tablet->pointer_info.time,
-                                device_get_modifiers (tablet->logical_device),
+                                gdk_wayland_device_get_modifiers (tablet->logical_device),
                                 0, clicks,
                                 FALSE,
                                 GDK_SCROLL_UNIT_WHEEL);
@@ -4531,8 +3981,8 @@ gdk_wayland_seat_grab (GdkSeat                *seat,
   if (wayland_seat->logical_pointer &&
       capabilities & GDK_SEAT_CAPABILITY_POINTER)
     {
-      device_maybe_emit_grab_crossing (wayland_seat->logical_pointer,
-                                       surface, evtime);
+      gdk_wayland_device_maybe_emit_grab_crossing (wayland_seat->logical_pointer,
+                                                   surface, evtime);
 
       _gdk_display_add_device_grab (display,
                                     wayland_seat->logical_pointer,
@@ -4551,8 +4001,8 @@ gdk_wayland_seat_grab (GdkSeat                *seat,
   if (wayland_seat->logical_touch &&
       capabilities & GDK_SEAT_CAPABILITY_TOUCH)
     {
-      device_maybe_emit_grab_crossing (wayland_seat->logical_touch,
-                                       surface, evtime);
+      gdk_wayland_device_maybe_emit_grab_crossing (wayland_seat->logical_touch,
+                                                   surface, evtime);
 
       _gdk_display_add_device_grab (display,
                                     wayland_seat->logical_touch,
@@ -4567,8 +4017,8 @@ gdk_wayland_seat_grab (GdkSeat                *seat,
   if (wayland_seat->logical_keyboard &&
       capabilities & GDK_SEAT_CAPABILITY_KEYBOARD)
     {
-      device_maybe_emit_grab_crossing (wayland_seat->logical_keyboard,
-                                       surface, evtime);
+      gdk_wayland_device_maybe_emit_grab_crossing (wayland_seat->logical_keyboard,
+                                                   surface, evtime);
 
       _gdk_display_add_device_grab (display,
                                     wayland_seat->logical_keyboard,
@@ -4591,9 +4041,9 @@ gdk_wayland_seat_grab (GdkSeat                *seat,
         {
           GdkWaylandTabletData *tablet = l->data;
 
-          device_maybe_emit_grab_crossing (tablet->logical_device,
-                                           surface,
-                                           evtime);
+          gdk_wayland_device_maybe_emit_grab_crossing (tablet->logical_device,
+                                                       surface,
+                                                       evtime);
 
           _gdk_display_add_device_grab (display,
                                         tablet->logical_device,
@@ -4625,8 +4075,8 @@ gdk_wayland_seat_ungrab (GdkSeat *seat)
 
   if (wayland_seat->logical_pointer)
     {
-      device_maybe_emit_ungrab_crossing (wayland_seat->logical_pointer,
-                                         GDK_CURRENT_TIME);
+      gdk_wayland_device_maybe_emit_ungrab_crossing (wayland_seat->logical_pointer,
+                                                     GDK_CURRENT_TIME);
 
       gdk_wayland_device_update_surface_cursor (wayland_seat->logical_pointer);
     }
@@ -4635,8 +4085,8 @@ gdk_wayland_seat_ungrab (GdkSeat *seat)
     {
       GdkSurface *prev_focus;
 
-      prev_focus = device_maybe_emit_ungrab_crossing (wayland_seat->logical_keyboard,
-                                                      GDK_CURRENT_TIME);
+      prev_focus = gdk_wayland_device_maybe_emit_ungrab_crossing (wayland_seat->logical_keyboard,
+                                                                  GDK_CURRENT_TIME);
       if (prev_focus)
         gdk_wayland_surface_restore_shortcuts (prev_focus, seat);
     }
@@ -4932,43 +4382,6 @@ _gdk_wayland_seat_get_last_implicit_grab_serial (GdkWaylandSeat    *seat,
   return serial;
 }
 
-void
-gdk_wayland_device_unset_touch_grab (GdkDevice        *gdk_device,
-                                     GdkEventSequence *sequence)
-{
-  GdkWaylandSeat *seat;
-  GdkWaylandTouchData *touch;
-  GdkEvent *event;
-
-  g_return_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device));
-
-  seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (gdk_device));
-  touch = gdk_wayland_seat_get_touch (seat,
-                                      GDK_EVENT_SEQUENCE_TO_SLOT (sequence));
-
-  if (touch ==
-      gdk_wayland_device_get_emulating_touch (GDK_WAYLAND_DEVICE (seat->logical_touch)))
-    {
-      gdk_wayland_device_set_emulating_touch (GDK_WAYLAND_DEVICE (seat->logical_touch),
-                                              NULL);
-      emulate_touch_crossing (touch->surface, NULL,
-                              seat->logical_touch, seat->touch,
-                              touch, GDK_LEAVE_NOTIFY, GDK_CROSSING_NORMAL,
-                              GDK_CURRENT_TIME);
-    }
-
-  event = gdk_touch_event_new (GDK_TOUCH_CANCEL,
-                               GDK_SLOT_TO_EVENT_SEQUENCE (touch->id),
-                               touch->surface,
-                               seat->logical_touch,
-                               GDK_CURRENT_TIME,
-                               device_get_modifiers (seat->logical_touch),
-                               touch->x, touch->y,
-                               NULL,
-                               touch->initial_touch);
-  _gdk_wayland_display_deliver_event (seat->display, event);
-}
-
 void
 gdk_wayland_seat_set_global_cursor (GdkSeat   *seat,
                                     GdkCursor *cursor)
@@ -4979,9 +4392,9 @@ gdk_wayland_seat_set_global_cursor (GdkSeat   *seat,
   pointer = gdk_seat_get_pointer (seat);
 
   g_set_object (&wayland_seat->grab_cursor, cursor);
-  gdk_wayland_device_set_surface_cursor (pointer,
-                                        gdk_wayland_device_get_focus (pointer),
-                                        NULL);
+  GDK_DEVICE_GET_CLASS (pointer)->set_surface_cursor (pointer,
+                                                      gdk_wayland_device_get_focus (pointer),
+                                                      NULL);
 }
 
 void
@@ -4993,49 +4406,6 @@ gdk_wayland_seat_set_drag (GdkSeat *seat,
   g_set_object (&wayland_seat->drag, drag);
 }
 
-/**
- * gdk_wayland_device_get_data_device: (skip)
- * @gdk_device: (type GdkWaylandDevice): a `GdkDevice`
- *
- * Returns the Wayland `wl_data_device` of a `GdkDevice`.
- *
- * Returns: (transfer none): a Wayland `wl_data_device`
- */
-struct wl_data_device *
-gdk_wayland_device_get_data_device (GdkDevice *gdk_device)
-{
-  GdkWaylandSeat *seat;
-
-  g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device), NULL);
-
-  seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (gdk_device));
-  return seat->data_device;
-}
-
-/**
- * gdk_wayland_device_set_selection: (skip)
- * @gdk_device: (type GdkWaylandDevice): a `GdkDevice`
- * @source: the data source for the selection
- *
- * Sets the selection of the `GdkDevice.
- *
- * This is calling wl_data_device_set_selection() on
- * the `wl_data_device` of @gdk_device.
- */
-void
-gdk_wayland_device_set_selection (GdkDevice             *gdk_device,
-                                  struct wl_data_source *source)
-{
-  GdkWaylandSeat *seat;
-  guint32 serial;
-
-  g_return_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device));
-
-  seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (gdk_device));
-  serial = _gdk_wayland_seat_get_last_implicit_grab_serial (seat, NULL);
-  wl_data_device_set_selection (seat->data_device, source, serial);
-}
-
 /**
  * gdk_wayland_seat_get_wl_seat: (skip)
  * @seat: (type GdkWaylandSeat): a `GdkSeat`
@@ -5051,41 +4421,3 @@ gdk_wayland_seat_get_wl_seat (GdkSeat *seat)
 
   return GDK_WAYLAND_SEAT (seat)->wl_seat;
 }
-
-/**
- * gdk_wayland_device_get_node_path:
- * @device: (type GdkWaylandDevice): a `GdkDevice`
- *
- * Returns the `/dev/input/event*` path of this device.
- *
- * For `GdkDevice`s that possibly coalesce multiple hardware
- * devices (eg. mouse, keyboard, touch,...), this function
- * will return %NULL.
- *
- * This is most notably implemented for devices of type
- * %GDK_SOURCE_PEN, %GDK_SOURCE_TABLET_PAD.
- *
- * Returns: (nullable) (transfer none): the `/dev/input/event*`
- *   path of this device
- */
-const char *
-gdk_wayland_device_get_node_path (GdkDevice *device)
-{
-  GdkWaylandTabletData *tablet;
-  GdkWaylandTabletPadData *pad;
-
-  GdkSeat *seat;
-
-  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
-
-  seat = gdk_device_get_seat (device);
-  tablet = gdk_wayland_seat_find_tablet (GDK_WAYLAND_SEAT (seat), device);
-  if (tablet)
-    return tablet->path;
-
-  pad = gdk_wayland_seat_find_pad (GDK_WAYLAND_SEAT (seat), device);
-  if (pad)
-    return pad->path;
-
-  return NULL;
-}
index 79a770c1f1060c1e8b88ef37ac3be83cee666bcc..48317bdb8840af89524ab1d32f6b3395f01b753e 100644 (file)
@@ -5,6 +5,7 @@ gdk_wayland_sources = files([
   'gdkcairocontext-wayland.c',
   'gdkclipboard-wayland.c',
   'gdkcursor-wayland.c',
+  'gdkdevice-wayland.c',
   'gdkdevicepad-wayland.c',
   'gdkdisplay-wayland.c',
   'gdkdrag-wayland.c',