[mutter/wip/garnacho/virtual-input-device: 4/22] clutter/evdev: Move keyboard and pointer notification into seat



commit c1184e4d45799f10775a4105c9315c1f794e927a
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Fri Jun 17 17:42:16 2016 -0400

    clutter/evdev: Move keyboard and pointer notification into seat
    
    We notify per seat; so lets move the logic there. Touch and tablets to
    follow later.

 .../clutter/evdev/clutter-device-manager-evdev.c   |  318 ++++---------------
 .../clutter/evdev/clutter-device-manager-evdev.h   |   26 ++
 clutter/clutter/evdev/clutter-seat-evdev.c         |  335 ++++++++++++++++++++
 clutter/clutter/evdev/clutter-seat-evdev.h         |   28 ++
 4 files changed, 456 insertions(+), 251 deletions(-)
---
diff --git a/clutter/clutter/evdev/clutter-device-manager-evdev.c 
b/clutter/clutter/evdev/clutter-device-manager-evdev.c
index 616b4f1..8a3574e 100644
--- a/clutter/clutter/evdev/clutter-device-manager-evdev.c
+++ b/clutter/clutter/evdev/clutter-device-manager-evdev.c
@@ -61,8 +61,6 @@
 
 #define DISCRETE_SCROLL_STEP 10.0
 
-#define AUTOREPEAT_VALUE 2
-
 
 /*
  * Clutter makes the assumption that two core devices have ID's 2 and 3 (core
@@ -153,24 +151,6 @@ static const char *option_xkb_layout = "us";
 static const char *option_xkb_variant = "";
 static const char *option_xkb_options = "";
 
-static inline guint64
-us (guint64 us)
-{
-  return us;
-}
-
-static inline guint64
-ms2us (guint64 ms)
-{
-  return us (ms * 1000);
-}
-
-static inline guint32
-us2ms (guint64 us)
-{
-  return (guint32) (us / 1000);
-}
-
 static void
 clutter_device_manager_evdev_copy_event_data (ClutterEventExtender *event_extender,
                                               const ClutterEvent   *src,
@@ -254,120 +234,34 @@ queue_event (ClutterEvent *event)
   _clutter_event_push (event, FALSE);
 }
 
-static gboolean
-keyboard_repeat (gpointer data);
-
-static void
-notify_key_device (ClutterInputDevice *input_device,
-                  guint64             time_us,
-                  guint32             key,
-                  guint32             state,
-                  gboolean            update_keys)
-{
-  ClutterInputDeviceEvdev *device_evdev =
-    CLUTTER_INPUT_DEVICE_EVDEV (input_device);
-  ClutterSeatEvdev *seat = _clutter_input_device_evdev_get_seat (device_evdev);
-  ClutterStage *stage;
-  ClutterEvent *event = NULL;
-  enum xkb_state_component changed_state;
-
-  /* We can drop the event on the floor if no stage has been
-   * associated with the device yet. */
-  stage = _clutter_input_device_get_stage (input_device);
-  if (stage == NULL)
-    {
-      clutter_seat_evdev_clear_repeat_timer (seat);
-      return;
-    }
-
-  event = _clutter_key_event_new_from_evdev (input_device,
-                                            seat->core_keyboard,
-                                            stage,
-                                            seat->xkb,
-                                            seat->button_state,
-                                            us2ms (time_us), key, state);
-  _clutter_evdev_event_set_event_code (event, key);
-
-  /* We must be careful and not pass multiple releases to xkb, otherwise it gets
-     confused and locks the modifiers */
-  if (state != AUTOREPEAT_VALUE)
+void
+_clutter_device_manager_evdev_constrain_pointer (ClutterDeviceManagerEvdev *manager_evdev,
+                                                 ClutterInputDevice        *core_pointer,
+                                                 uint64_t                   time_us,
+                                                 float                      x,
+                                                 float                      y,
+                                                 float                     *new_x,
+                                                 float                     *new_y)
+{
+  if (manager_evdev->priv->constrain_callback)
     {
-      changed_state = xkb_state_update_key (seat->xkb,
-                                            event->key.hardware_keycode,
-                                            state ? XKB_KEY_DOWN : XKB_KEY_UP);
+      manager_evdev->priv->constrain_callback (core_pointer,
+                                               us2ms (time_us),
+                                               x, y,
+                                               new_x, new_y,
+                                              manager_evdev->priv->constrain_data);
     }
   else
     {
-      changed_state = 0;
-      clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_SYNTHETIC);
-    }
+      ClutterActor *stage = CLUTTER_ACTOR (manager_evdev->priv->stage);
+      float stage_width = clutter_actor_get_width (stage);
+      float stage_height = clutter_actor_get_height (stage);
 
-  queue_event (event);
-
-  if (update_keys && (changed_state & XKB_STATE_LEDS))
-    clutter_seat_evdev_sync_leds (seat);
-
-  if (state == 0 ||             /* key release */
-      !seat->repeat ||
-      !xkb_keymap_key_repeats (xkb_state_get_keymap (seat->xkb), event->key.hardware_keycode))
-    {
-      clutter_seat_evdev_clear_repeat_timer (seat);
-      return;
-    }
-
-  if (state == 1)               /* key press */
-    seat->repeat_count = 0;
-
-  seat->repeat_count += 1;
-  seat->repeat_key = key;
-
-  switch (seat->repeat_count)
-    {
-    case 1:
-    case 2:
-      {
-        guint32 interval;
-
-        clutter_seat_evdev_clear_repeat_timer (seat);
-        seat->repeat_device = g_object_ref (input_device);
-
-        if (seat->repeat_count == 1)
-          interval = seat->repeat_delay;
-        else
-          interval = seat->repeat_interval;
-
-        seat->repeat_timer =
-          clutter_threads_add_timeout_full (CLUTTER_PRIORITY_EVENTS,
-                                            interval,
-                                            keyboard_repeat,
-                                            seat,
-                                            NULL);
-        return;
-      }
-    default:
-      return;
+      x = CLAMP (x, 0.f, stage_width - 1);
+      y = CLAMP (y, 0.f, stage_height - 1);
     }
 }
 
-static gboolean
-keyboard_repeat (gpointer data)
-{
-  ClutterSeatEvdev *seat = data;
-  GSource *source;
-  guint32 time_ms;
-
-  g_return_val_if_fail (seat->repeat_device != NULL, G_SOURCE_REMOVE);
-  source = g_main_context_find_source_by_id (NULL, seat->repeat_timer);
-  time_ms = g_source_get_time (source) / 1000;
-
-  notify_key_device (seat->repeat_device,
-                     ms2us (time_ms),
-                     seat->repeat_key,
-                     AUTOREPEAT_VALUE,
-                     FALSE);
-
-  return G_SOURCE_CONTINUE;
-}
 
 static ClutterEvent *
 new_absolute_motion_event (ClutterInputDevice *input_device,
@@ -606,118 +500,6 @@ notify_scroll (ClutterInputDevice       *input_device,
 }
 
 static void
-notify_button (ClutterInputDevice *input_device,
-               guint64             time_us,
-               guint32             button,
-               guint32             state)
-{
-  ClutterInputDeviceEvdev *device_evdev;
-  ClutterSeatEvdev *seat;
-  ClutterStage *stage;
-  ClutterEvent *event = NULL;
-  gint button_nr;
-  static gint maskmap[8] =
-    {
-      CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON3_MASK, CLUTTER_BUTTON2_MASK,
-      CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK, 0, 0, 0
-    };
-
-  /* We can drop the event on the floor if no stage has been
-   * associated with the device yet. */
-  stage = _clutter_input_device_get_stage (input_device);
-  if (stage == NULL)
-    return;
-
-  device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
-  seat = _clutter_input_device_evdev_get_seat (device_evdev);
-
-  /* The evdev button numbers don't map sequentially to clutter button
-   * numbers (the right and middle mouse buttons are in the opposite
-   * order) so we'll map them directly with a switch statement */
-  switch (button)
-    {
-    case BTN_LEFT:
-    case BTN_TOUCH:
-      button_nr = CLUTTER_BUTTON_PRIMARY;
-      break;
-
-    case BTN_RIGHT:
-    case BTN_STYLUS:
-      button_nr = CLUTTER_BUTTON_SECONDARY;
-      break;
-
-    case BTN_MIDDLE:
-    case BTN_STYLUS2:
-      button_nr = CLUTTER_BUTTON_MIDDLE;
-      break;
-
-    default:
-      /* For compatibility reasons, all additional buttons go after the old 4-7 scroll ones */
-      if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
-        button_nr = button - BTN_TOOL_PEN + 4;
-      else
-        button_nr = button - (BTN_LEFT - 1) + 4;
-      break;
-    }
-
-  if (button_nr < 1 || button_nr > 12)
-    {
-      g_warning ("Unhandled button event 0x%x", button);
-      return;
-    }
-
-  if (state)
-    event = clutter_event_new (CLUTTER_BUTTON_PRESS);
-  else
-    event = clutter_event_new (CLUTTER_BUTTON_RELEASE);
-
-  if (button_nr < G_N_ELEMENTS (maskmap))
-    {
-      /* Update the modifiers */
-      if (state)
-        seat->button_state |= maskmap[button_nr - 1];
-      else
-        seat->button_state &= ~maskmap[button_nr - 1];
-    }
-
-  _clutter_evdev_event_set_time_usec (event, time_us);
-  event->button.time = us2ms (time_us);
-  event->button.stage = CLUTTER_STAGE (stage);
-  _clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
-  event->button.button = button_nr;
-
-  if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
-    {
-      ClutterPoint point;
-
-      clutter_input_device_get_coords (input_device, NULL, &point);
-      event->button.x = point.x;
-      event->button.y = point.y;
-    }
-  else
-    {
-      event->button.x = seat->pointer_x;
-      event->button.y = seat->pointer_y;
-    }
-
-  clutter_event_set_source_device (event, input_device);
-
-  _clutter_evdev_event_set_event_code (event, button);
-
-  if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
-    {
-      clutter_event_set_device_tool (event, device_evdev->last_tool);
-      clutter_event_set_device (event, input_device);
-    }
-  else
-    clutter_event_set_device (event, seat->core_pointer);
-
-  _clutter_input_device_set_stage (seat->core_pointer, stage);
-
-  queue_event (event);
-}
-
-static void
 notify_touch_event (ClutterInputDevice *input_device,
                    ClutterEventType    evtype,
                    guint64             time_us,
@@ -1387,6 +1169,14 @@ translate_tablet_axes (struct libinput_event_tablet_tool *tablet_event)
     return (gdouble *) g_array_free (axes, FALSE);
 }
 
+static ClutterSeatEvdev *
+seat_from_device (ClutterInputDevice *device)
+{
+  ClutterInputDeviceEvdev *device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
+
+  return _clutter_input_device_evdev_get_seat (device_evdev);
+}
+
 static gboolean
 process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
                       struct libinput_event *event)
@@ -1403,8 +1193,8 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
         guint64 time_us;
         struct libinput_event_keyboard *key_event =
           libinput_event_get_keyboard_event (event);
-        device = libinput_device_get_user_data (libinput_device);
 
+        device = libinput_device_get_user_data (libinput_device);
         time_us = libinput_event_keyboard_get_time_usec (key_event);
         key = libinput_event_keyboard_get_key (key_event);
         key_state = libinput_event_keyboard_get_key_state (key_event) ==
@@ -1419,18 +1209,35 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
             seat_key_count != 0))
           break;
 
-        notify_key_device (device, time_us, key, key_state, TRUE);
+        clutter_seat_evdev_notify_key (seat_from_device (device),
+                                       device,
+                                       time_us, key, key_state, TRUE);
 
         break;
       }
 
     case LIBINPUT_EVENT_POINTER_MOTION:
       {
-        struct libinput_event_pointer *motion_event =
+        struct libinput_event_pointer *pointer_event =
           libinput_event_get_pointer_event (event);
-        device = libinput_device_get_user_data (libinput_device);
+        uint64_t time_us;
+        double dx;
+        double dy;
+        double dx_unaccel;
+        double dy_unaccel;
 
-        notify_relative_motion (device, motion_event);
+        device = libinput_device_get_user_data (libinput_device);
+        time_us = libinput_event_pointer_get_time_usec (pointer_event);
+        dx = libinput_event_pointer_get_dx (pointer_event);
+        dy = libinput_event_pointer_get_dy (pointer_event);
+        dx_unaccel = libinput_event_pointer_get_dx_unaccelerated (pointer_event);
+        dy_unaccel = libinput_event_pointer_get_dy_unaccelerated (pointer_event);
+
+        clutter_seat_evdev_notify_relative_motion (seat_from_device (device),
+                                                   device,
+                                                   time_us,
+                                                   dx, dy,
+                                                   dx_unaccel, dy_unaccel);
 
         break;
       }
@@ -1457,7 +1264,12 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
                                                                stage_width);
         y = libinput_event_pointer_get_absolute_y_transformed (motion_event,
                                                                stage_height);
-        notify_absolute_motion (device, time_us, x, y, NULL);
+
+        clutter_seat_evdev_notify_absolute_motion (seat_from_device (device),
+                                                   device,
+                                                   time_us,
+                                                   x, y,
+                                                   NULL);
 
         break;
       }
@@ -1484,8 +1296,8 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
              seat_button_count != 0))
           break;
 
-        notify_button (device, time_us, button, button_state);
-
+        clutter_seat_evdev_notify_button (seat_from_device (device), device,
+                                          time_us, button, button_state);
         break;
       }
 
@@ -1823,34 +1635,38 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
       }
     case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
       {
-        guint64 time;
+        guint64 time_us;
         guint32 button_state;
         struct libinput_event_tablet_tool *tablet_event =
           libinput_event_get_tablet_tool_event (event);
         guint tablet_button;
 
         device = libinput_device_get_user_data (libinput_device);
-        time = libinput_event_tablet_tool_get_time_usec (tablet_event);
+        time_us = libinput_event_tablet_tool_get_time_usec (tablet_event);
         tablet_button = libinput_event_tablet_tool_get_button (tablet_event);
 
         button_state = libinput_event_tablet_tool_get_button_state (tablet_event) ==
                        LIBINPUT_BUTTON_STATE_PRESSED;
-        notify_button (device, time, tablet_button, button_state);
+
+        clutter_seat_evdev_notify_button (seat_from_device (device), device,
+                                          time_us, tablet_button, button_state);
         break;
       }
     case LIBINPUT_EVENT_TABLET_TOOL_TIP:
       {
-        guint64 time;
+        guint64 time_us;
         guint32 button_state;
         struct libinput_event_tablet_tool *tablet_event =
           libinput_event_get_tablet_tool_event (event);
 
         device = libinput_device_get_user_data (libinput_device);
-        time = libinput_event_tablet_tool_get_time_usec (tablet_event);
+        time_us = libinput_event_tablet_tool_get_time_usec (tablet_event);
 
         button_state = libinput_event_tablet_tool_get_tip_state (tablet_event) ==
                        LIBINPUT_TABLET_TOOL_TIP_DOWN;
-        notify_button (device, time, BTN_TOUCH, button_state);
+
+        clutter_seat_evdev_notify_button (seat_from_device (device), device,
+                                          time_us, BTN_TOUCH, button_state);
         break;
       }
     default:
diff --git a/clutter/clutter/evdev/clutter-device-manager-evdev.h 
b/clutter/clutter/evdev/clutter-device-manager-evdev.h
index a92a0fc..1b01b8d 100644
--- a/clutter/clutter/evdev/clutter-device-manager-evdev.h
+++ b/clutter/clutter/evdev/clutter-device-manager-evdev.h
@@ -68,6 +68,32 @@ struct xkb_keymap * _clutter_device_manager_evdev_get_keymap (ClutterDeviceManag
 
 ClutterStage * _clutter_device_manager_evdev_get_stage (ClutterDeviceManagerEvdev *manager_evdev);
 
+void _clutter_device_manager_evdev_constrain_pointer (ClutterDeviceManagerEvdev *manager_evdev,
+                                                      ClutterInputDevice        *core_pointer,
+                                                      uint64_t                   time_us,
+                                                      float                      x,
+                                                      float                      y,
+                                                      float                     *new_x,
+                                                      float                     *new_y);
+
+static inline guint64
+us (guint64 us)
+{
+  return us;
+}
+
+static inline guint64
+ms2us (guint64 ms)
+{
+  return us (ms * 1000);
+}
+
+static inline guint32
+us2ms (guint64 us)
+{
+  return (guint32) (us / 1000);
+}
+
 G_END_DECLS
 
 #endif /* __CLUTTER_DEVICE_MANAGER_EVDEV_H__ */
diff --git a/clutter/clutter/evdev/clutter-seat-evdev.c b/clutter/clutter/evdev/clutter-seat-evdev.c
index 1db3f8b..6a7c5ef 100644
--- a/clutter/clutter/evdev/clutter-seat-evdev.c
+++ b/clutter/clutter/evdev/clutter-seat-evdev.c
@@ -28,13 +28,19 @@
 
 #include "clutter-seat-evdev.h"
 
+#include <linux/input.h>
+
+#include "clutter-event-private.h"
 #include "clutter-input-device-evdev.h"
+#include "clutter-main.h"
 
 /* Try to keep the pointer inside the stage. Hopefully no one is using
  * this backend with stages smaller than this. */
 #define INITIAL_POINTER_X 16
 #define INITIAL_POINTER_Y 16
 
+#define AUTOREPEAT_VALUE 2
+
 void
 clutter_seat_evdev_set_libinput_seat (ClutterSeatEvdev     *seat,
                                       struct libinput_seat *libinput_seat)
@@ -171,6 +177,335 @@ clutter_seat_evdev_clear_repeat_timer (ClutterSeatEvdev *seat)
     }
 }
 
+static gboolean
+keyboard_repeat (gpointer data)
+{
+  ClutterSeatEvdev *seat = data;
+  GSource *source;
+  guint32 time_ms;
+
+  g_return_val_if_fail (seat->repeat_device != NULL, G_SOURCE_REMOVE);
+  source = g_main_context_find_source_by_id (NULL, seat->repeat_timer);
+  time_ms = g_source_get_time (source) / 1000;
+
+  clutter_seat_evdev_notify_key (seat,
+                                 seat->repeat_device,
+                                 ms2us (time_ms),
+                                 seat->repeat_key,
+                                 AUTOREPEAT_VALUE,
+                                 FALSE);
+
+  return G_SOURCE_CONTINUE;
+}
+
+static void
+queue_event (ClutterEvent *event)
+{
+  _clutter_event_push (event, FALSE);
+}
+
+void
+clutter_seat_evdev_notify_key (ClutterSeatEvdev   *seat,
+                               ClutterInputDevice *device,
+                               uint64_t            time_us,
+                               uint32_t            key,
+                               uint32_t            state,
+                               gboolean            update_keys)
+{
+  ClutterStage *stage;
+  ClutterEvent *event = NULL;
+  enum xkb_state_component changed_state;
+
+  /* We can drop the event on the floor if no stage has been
+   * associated with the device yet. */
+  stage = _clutter_input_device_get_stage (device);
+  if (stage == NULL)
+    {
+      clutter_seat_evdev_clear_repeat_timer (seat);
+      return;
+    }
+
+  event = _clutter_key_event_new_from_evdev (device,
+                                            seat->core_keyboard,
+                                            stage,
+                                            seat->xkb,
+                                            seat->button_state,
+                                            us2ms (time_us), key, state);
+  _clutter_evdev_event_set_event_code (event, key);
+
+  /* We must be careful and not pass multiple releases to xkb, otherwise it gets
+     confused and locks the modifiers */
+  if (state != AUTOREPEAT_VALUE)
+    {
+      changed_state = xkb_state_update_key (seat->xkb,
+                                            event->key.hardware_keycode,
+                                            state ? XKB_KEY_DOWN : XKB_KEY_UP);
+    }
+  else
+    {
+      changed_state = 0;
+      clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_SYNTHETIC);
+    }
+
+  queue_event (event);
+
+  if (update_keys && (changed_state & XKB_STATE_LEDS))
+    clutter_seat_evdev_sync_leds (seat);
+
+  if (state == 0 ||             /* key release */
+      !seat->repeat ||
+      !xkb_keymap_key_repeats (xkb_state_get_keymap (seat->xkb),
+                               event->key.hardware_keycode))
+    {
+      clutter_seat_evdev_clear_repeat_timer (seat);
+      return;
+    }
+
+  if (state == 1)               /* key press */
+    seat->repeat_count = 0;
+
+  seat->repeat_count += 1;
+  seat->repeat_key = key;
+
+  switch (seat->repeat_count)
+    {
+    case 1:
+    case 2:
+      {
+        guint32 interval;
+
+        clutter_seat_evdev_clear_repeat_timer (seat);
+        seat->repeat_device = g_object_ref (device);
+
+        if (seat->repeat_count == 1)
+          interval = seat->repeat_delay;
+        else
+          interval = seat->repeat_interval;
+
+        seat->repeat_timer =
+          clutter_threads_add_timeout_full (CLUTTER_PRIORITY_EVENTS,
+                                            interval,
+                                            keyboard_repeat,
+                                            seat,
+                                            NULL);
+        return;
+      }
+    default:
+      return;
+    }
+}
+
+static ClutterEvent *
+new_absolute_motion_event (ClutterSeatEvdev   *seat,
+                           ClutterInputDevice *input_device,
+                           guint64             time_us,
+                           gfloat              x,
+                           gfloat              y,
+                           gdouble            *axes)
+{
+  ClutterStage *stage = _clutter_input_device_get_stage (input_device);
+  ClutterEvent *event;
+
+  event = clutter_event_new (CLUTTER_MOTION);
+
+  if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE)
+    _clutter_device_manager_evdev_constrain_pointer (seat->manager_evdev,
+                                                     seat->core_pointer,
+                                                     time_us,
+                                                     seat->pointer_x,
+                                                     seat->pointer_y,
+                                                     &x, &y);
+
+  _clutter_evdev_event_set_time_usec (event, time_us);
+  event->motion.time = us2ms (time_us);
+  event->motion.stage = stage;
+  event->motion.device = seat->core_pointer;
+  _clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
+  event->motion.x = x;
+  event->motion.y = y;
+  event->motion.axes = axes;
+  clutter_event_set_source_device (event, input_device);
+
+  if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
+    {
+      ClutterInputDeviceEvdev *device_evdev =
+        CLUTTER_INPUT_DEVICE_EVDEV (input_device);
+
+      clutter_event_set_device_tool (event, device_evdev->last_tool);
+      clutter_event_set_device (event, input_device);
+    }
+  else
+    {
+      clutter_event_set_device (event, seat->core_pointer);
+    }
+
+  _clutter_input_device_set_stage (seat->core_pointer, stage);
+
+  if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE)
+    {
+      seat->pointer_x = x;
+      seat->pointer_y = y;
+    }
+
+  return event;
+}
+
+void
+clutter_seat_evdev_notify_relative_motion (ClutterSeatEvdev   *seat,
+                                           ClutterInputDevice *input_device,
+                                           uint64_t            time_us,
+                                           float               dx,
+                                           float               dy,
+                                           float               dx_unaccel,
+                                           float               dy_unaccel)
+{
+  gfloat new_x, new_y;
+  ClutterEvent *event;
+
+  /* We can drop the event on the floor if no stage has been
+   * associated with the device yet. */
+  if (!_clutter_input_device_get_stage (input_device))
+    return;
+
+  new_x = seat->pointer_x + dx;
+  new_y = seat->pointer_y + dy;
+  event = new_absolute_motion_event (seat, input_device,
+                                     time_us, new_x, new_y, NULL);
+
+  _clutter_evdev_event_set_relative_motion (event,
+                                            dx, dy,
+                                            dx_unaccel, dy_unaccel);
+
+  queue_event (event);
+}
+
+void clutter_seat_evdev_notify_absolute_motion (ClutterSeatEvdev   *seat,
+                                                ClutterInputDevice *input_device,
+                                                uint64_t            time_us,
+                                                float               x,
+                                                float               y,
+                                                double             *axes)
+{
+  ClutterEvent *event;
+
+  event = new_absolute_motion_event (seat, input_device, time_us, x, x, axes);
+
+  queue_event (event);
+}
+
+void
+clutter_seat_evdev_notify_button (ClutterSeatEvdev   *seat,
+                                  ClutterInputDevice *input_device,
+                                  uint64_t            time_us,
+                                  uint32_t            button,
+                                  uint32_t            state)
+{
+  ClutterStage *stage;
+  ClutterEvent *event = NULL;
+  gint button_nr;
+  static gint maskmap[8] =
+    {
+      CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON3_MASK, CLUTTER_BUTTON2_MASK,
+      CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK, 0, 0, 0
+    };
+
+  /* We can drop the event on the floor if no stage has been
+   * associated with the device yet. */
+  stage = _clutter_input_device_get_stage (input_device);
+  if (stage == NULL)
+    return;
+
+  /* The evdev button numbers don't map sequentially to clutter button
+   * numbers (the right and middle mouse buttons are in the opposite
+   * order) so we'll map them directly with a switch statement */
+  switch (button)
+    {
+    case BTN_LEFT:
+    case BTN_TOUCH:
+      button_nr = CLUTTER_BUTTON_PRIMARY;
+      break;
+
+    case BTN_RIGHT:
+    case BTN_STYLUS:
+      button_nr = CLUTTER_BUTTON_SECONDARY;
+      break;
+
+    case BTN_MIDDLE:
+    case BTN_STYLUS2:
+      button_nr = CLUTTER_BUTTON_MIDDLE;
+      break;
+
+    default:
+      /* For compatibility reasons, all additional buttons go after the old 4-7 scroll ones */
+      if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
+        button_nr = button - BTN_TOOL_PEN + 4;
+      else
+        button_nr = button - (BTN_LEFT - 1) + 4;
+      break;
+    }
+
+  if (button_nr < 1 || button_nr > 12)
+    {
+      g_warning ("Unhandled button event 0x%x", button);
+      return;
+    }
+
+  if (state)
+    event = clutter_event_new (CLUTTER_BUTTON_PRESS);
+  else
+    event = clutter_event_new (CLUTTER_BUTTON_RELEASE);
+
+  if (button_nr < G_N_ELEMENTS (maskmap))
+    {
+      /* Update the modifiers */
+      if (state)
+        seat->button_state |= maskmap[button_nr - 1];
+      else
+        seat->button_state &= ~maskmap[button_nr - 1];
+    }
+
+  _clutter_evdev_event_set_time_usec (event, time_us);
+  event->button.time = us2ms (time_us);
+  event->button.stage = CLUTTER_STAGE (stage);
+  _clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
+  event->button.button = button_nr;
+
+  if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
+    {
+      ClutterPoint point;
+
+      clutter_input_device_get_coords (input_device, NULL, &point);
+      event->button.x = point.x;
+      event->button.y = point.y;
+    }
+  else
+    {
+      event->button.x = seat->pointer_x;
+      event->button.y = seat->pointer_y;
+    }
+
+  clutter_event_set_source_device (event, input_device);
+
+  _clutter_evdev_event_set_event_code (event, button);
+
+  if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
+    {
+      ClutterInputDeviceEvdev *device_evdev =
+        CLUTTER_INPUT_DEVICE_EVDEV (input_device);
+
+      clutter_event_set_device_tool (event, device_evdev->last_tool);
+      clutter_event_set_device (event, input_device);
+    }
+  else
+    {
+      clutter_event_set_device (event, seat->core_pointer);
+    }
+
+  _clutter_input_device_set_stage (seat->core_pointer, stage);
+
+  queue_event (event);
+}
+
 void
 clutter_seat_evdev_free (ClutterSeatEvdev *seat)
 {
diff --git a/clutter/clutter/evdev/clutter-seat-evdev.h b/clutter/clutter/evdev/clutter-seat-evdev.h
index 9cf3acf..f246434 100644
--- a/clutter/clutter/evdev/clutter-seat-evdev.h
+++ b/clutter/clutter/evdev/clutter-seat-evdev.h
@@ -76,6 +76,34 @@ struct _ClutterSeatEvdev
   gfloat accum_scroll_dy;
 };
 
+void clutter_seat_evdev_notify_key (ClutterSeatEvdev   *seat,
+                                    ClutterInputDevice *device,
+                                    uint64_t            time_us,
+                                    uint32_t            key,
+                                    uint32_t            state,
+                                    gboolean            update_keys);
+
+void clutter_seat_evdev_notify_relative_motion (ClutterSeatEvdev   *seat_evdev,
+                                                ClutterInputDevice *input_device,
+                                                uint64_t            time_us,
+                                                float               dx,
+                                                float               dy,
+                                                float               dx_unaccel,
+                                                float               dy_unaccel);
+
+void clutter_seat_evdev_notify_absolute_motion (ClutterSeatEvdev   *seat_evdev,
+                                                ClutterInputDevice *input_device,
+                                                uint64_t            time_us,
+                                                float               x,
+                                                float               y,
+                                                double             *axes);
+
+void clutter_seat_evdev_notify_button (ClutterSeatEvdev   *seat,
+                                       ClutterInputDevice *input_device,
+                                       uint64_t            time_us,
+                                       uint32_t            button,
+                                       uint32_t            state);
+
 void clutter_seat_evdev_set_libinput_seat (ClutterSeatEvdev     *seat,
                                            struct libinput_seat *libinput_seat);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]