[mutter/wip/carlosg/input-thread: 76/101] backends/native: Make MetaVirtualInputDevice vmethods "async"




commit 0693e1a8a86945ff2151e286d6b0dbd06a09e283
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Aug 12 17:01:02 2020 +0200

    backends/native: Make MetaVirtualInputDevice vmethods "async"
    
    These are one-way API calls, that now should get executed in the MetaSeatImpl
    context. Use the MetaSeatImpl async task plumbing so that's the case.

 .../native/meta-virtual-input-device-native.c      | 698 +++++++++++++++------
 1 file changed, 507 insertions(+), 191 deletions(-)
---
diff --git a/src/backends/native/meta-virtual-input-device-native.c 
b/src/backends/native/meta-virtual-input-device-native.c
index 2082c11ab8..28542dc94e 100644
--- a/src/backends/native/meta-virtual-input-device-native.c
+++ b/src/backends/native/meta-virtual-input-device-native.c
@@ -41,16 +41,62 @@ enum
 
 static GParamSpec *obj_props[PROP_LAST];
 
+typedef struct _ImplState ImplState;
+
+struct _ImplState
+{
+  ClutterInputDevice *device;
+  int button_count[KEY_CNT];
+};
+
 struct _MetaVirtualInputDeviceNative
 {
   ClutterVirtualInputDevice parent;
 
-  ClutterInputDevice *device;
   MetaSeatNative *seat;
   guint slot_base;
-  int button_count[KEY_CNT];
+  ImplState *impl_state;
 };
 
+typedef struct
+{
+  uint64_t time_us;
+  double x;
+  double y;
+} MetaVirtualEventMotion;
+
+typedef struct
+{
+  uint64_t time_us;
+  uint32_t button;
+  ClutterButtonState button_state;
+} MetaVirtualEventButton;
+
+typedef struct
+{
+  uint64_t time_us;
+  double dx;
+  double dy;
+  ClutterScrollDirection direction;
+  ClutterScrollSource scroll_source;
+  ClutterScrollFinishFlags finish_flags;
+} MetaVirtualEventScroll;
+
+typedef struct
+{
+  uint64_t time_us;
+  uint32_t key;
+  ClutterKeyState key_state;
+} MetaVirtualEventKey;
+
+typedef struct
+{
+  uint64_t time_us;
+  int device_slot;
+  double x;
+  double y;
+} MetaVirtualEventTouch;
+
 G_DEFINE_TYPE (MetaVirtualInputDeviceNative,
                meta_virtual_input_device_native,
                CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE)
@@ -68,9 +114,9 @@ update_button_count (MetaVirtualInputDeviceNative *virtual_evdev,
                      uint32_t                      state)
 {
   if (state)
-    return ++virtual_evdev->button_count[button];
+    return ++virtual_evdev->impl_state->button_count[button];
   else
-    return --virtual_evdev->button_count[button];
+    return --virtual_evdev->impl_state->button_count[button];
 }
 
 static EvdevButtonType
@@ -109,38 +155,41 @@ get_button_type (uint16_t code)
   return EVDEV_BUTTON_TYPE_NONE;
 }
 
-static void
-release_pressed_buttons (ClutterVirtualInputDevice *virtual_device)
+static gboolean
+release_device (GTask *task)
 {
-  MetaVirtualInputDeviceNative *virtual_evdev =
-    META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
+  ImplState *impl_state = g_task_get_task_data (task);
+  MetaInputDeviceNative *device_native;
+  MetaSeatImpl *seat_impl;
   int code;
   uint64_t time_us;
 
+  device_native = META_INPUT_DEVICE_NATIVE (impl_state->device);
+  seat_impl = meta_input_device_native_get_seat_impl (device_native);
   time_us = g_get_monotonic_time ();
 
   meta_topic (META_DEBUG_INPUT,
               "Releasing pressed buttons while destroying virtual input device "
-              "(device %p)", virtual_device);
+              "(device %p)", device_native);
 
-  for (code = 0; code < G_N_ELEMENTS (virtual_evdev->button_count); code++)
+  for (code = 0; code < G_N_ELEMENTS (impl_state->button_count); code++)
     {
-      if (virtual_evdev->button_count[code] == 0)
+      if (impl_state->button_count[code] == 0)
         continue;
 
       switch (get_button_type (code))
         {
         case EVDEV_BUTTON_TYPE_KEY:
-          meta_seat_impl_notify_key (virtual_evdev->seat->impl,
-                                     virtual_evdev->device,
+          meta_seat_impl_notify_key (seat_impl,
+                                     impl_state->device,
                                      time_us,
                                      code,
                                      CLUTTER_KEY_STATE_RELEASED,
                                      TRUE);
           break;
         case EVDEV_BUTTON_TYPE_BUTTON:
-          meta_seat_impl_notify_button (virtual_evdev->seat->impl,
-                                        virtual_evdev->device,
+          meta_seat_impl_notify_button (seat_impl,
+                                        impl_state->device,
                                         time_us,
                                         code,
                                         CLUTTER_BUTTON_STATE_RELEASED);
@@ -148,9 +197,32 @@ release_pressed_buttons (ClutterVirtualInputDevice *virtual_device)
         case EVDEV_BUTTON_TYPE_NONE:
           g_assert_not_reached ();
         }
-
-      update_button_count (virtual_evdev, code, 0);
     }
+
+  g_clear_object (&impl_state->device);
+  g_task_return_boolean (task, TRUE);
+
+  return G_SOURCE_REMOVE;
+}
+
+static gboolean
+notify_relative_motion (GTask *task)
+{
+  MetaVirtualInputDeviceNative *virtual_evdev =
+    g_task_get_source_object (task);
+  MetaSeatImpl *seat = virtual_evdev->seat->impl;
+  MetaVirtualEventMotion *event = g_task_get_task_data (task);
+
+  if (event->time_us == CLUTTER_CURRENT_TIME)
+    event->time_us = g_get_monotonic_time ();
+
+  meta_seat_impl_notify_relative_motion (seat,
+                                         virtual_evdev->impl_state->device,
+                                         event->time_us,
+                                         event->x, event->y,
+                                         event->x, event->y);
+  g_task_return_boolean (task, TRUE);
+  return G_SOURCE_REMOVE;
 }
 
 static void
@@ -159,19 +231,43 @@ meta_virtual_input_device_native_notify_relative_motion (ClutterVirtualInputDevi
                                                          double                     dx,
                                                          double                     dy)
 {
+  MetaVirtualEventMotion *event;
   MetaVirtualInputDeviceNative *virtual_evdev =
     META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
+  GTask *task;
 
-  g_return_if_fail (virtual_evdev->device != NULL);
+  g_return_if_fail (virtual_evdev->impl_state->device != NULL);
 
-  if (time_us == CLUTTER_CURRENT_TIME)
-    time_us = g_get_monotonic_time ();
+  event = g_new0 (MetaVirtualEventMotion, 1);
+  event->time_us = time_us;
+  event->x = dx;
+  event->y = dy;
 
-  meta_seat_impl_notify_relative_motion (virtual_evdev->seat->impl,
-                                         virtual_evdev->device,
-                                         time_us,
-                                         dx, dy,
-                                         dx, dy);
+  task = g_task_new (virtual_device, NULL, NULL, NULL);
+  g_task_set_task_data (task, event, g_free);
+  meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
+                                 (GSourceFunc) notify_relative_motion);
+  g_object_unref (task);
+}
+
+static gboolean
+notify_absolute_motion (GTask *task)
+{
+  MetaVirtualInputDeviceNative *virtual_evdev =
+    g_task_get_source_object (task);
+  MetaSeatImpl *seat = virtual_evdev->seat->impl;
+  MetaVirtualEventMotion *event = g_task_get_task_data (task);
+
+  if (event->time_us == CLUTTER_CURRENT_TIME)
+    event->time_us = g_get_monotonic_time ();
+
+  meta_seat_impl_notify_absolute_motion (seat,
+                                         virtual_evdev->impl_state->device,
+                                         event->time_us,
+                                         event->x, event->y,
+                                         NULL);
+  g_task_return_boolean (task, TRUE);
+  return G_SOURCE_REMOVE;
 }
 
 static void
@@ -180,19 +276,23 @@ meta_virtual_input_device_native_notify_absolute_motion (ClutterVirtualInputDevi
                                                          double                     x,
                                                          double                     y)
 {
+  MetaVirtualEventMotion *event;
   MetaVirtualInputDeviceNative *virtual_evdev =
     META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
+  GTask *task;
 
-  g_return_if_fail (virtual_evdev->device != NULL);
+  g_return_if_fail (virtual_evdev->impl_state->device != NULL);
 
-  if (time_us == CLUTTER_CURRENT_TIME)
-    time_us = g_get_monotonic_time ();
+  event = g_new0 (MetaVirtualEventMotion, 1);
+  event->time_us = time_us;
+  event->x = x;
+  event->y = y;
 
-  meta_seat_impl_notify_absolute_motion (virtual_evdev->seat->impl,
-                                         virtual_evdev->device,
-                                         time_us,
-                                         x, y,
-                                         NULL);
+  task = g_task_new (virtual_device, NULL, NULL, NULL);
+  g_task_set_task_data (task, event, g_free);
+  meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
+                                 (GSourceFunc) notify_absolute_motion);
+  g_object_unref (task);
 }
 
 static int
@@ -215,93 +315,148 @@ translate_to_evdev_button (int clutter_button)
     }
 }
 
-static void
-meta_virtual_input_device_native_notify_button (ClutterVirtualInputDevice *virtual_device,
-                                                uint64_t                   time_us,
-                                                uint32_t                   button,
-                                                ClutterButtonState         button_state)
+static gboolean
+notify_button (GTask *task)
 {
   MetaVirtualInputDeviceNative *virtual_evdev =
-    META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
+    g_task_get_source_object (task);
+  MetaSeatImpl *seat = virtual_evdev->seat->impl;
+  MetaVirtualEventButton *event = g_task_get_task_data (task);
   int button_count;
   int evdev_button;
 
-  g_return_if_fail (virtual_evdev->device != NULL);
+  if (event->time_us == CLUTTER_CURRENT_TIME)
+    event->time_us = g_get_monotonic_time ();
 
-  if (time_us == CLUTTER_CURRENT_TIME)
-    time_us = g_get_monotonic_time ();
-
-  evdev_button = translate_to_evdev_button (button);
+  evdev_button = translate_to_evdev_button (event->button);
 
   if (get_button_type (evdev_button) != EVDEV_BUTTON_TYPE_BUTTON)
     {
       g_warning ("Unknown/invalid virtual device button 0x%x pressed",
                  evdev_button);
-      return;
+      goto out;
     }
 
-  button_count = update_button_count (virtual_evdev, evdev_button, button_state);
+  button_count = update_button_count (virtual_evdev, evdev_button,
+                                      event->button_state);
   if (button_count < 0 || button_count > 1)
     {
       g_warning ("Received multiple virtual 0x%x button %s (ignoring)", evdev_button,
-                 button_state == CLUTTER_BUTTON_STATE_PRESSED ? "presses" : "releases");
-      update_button_count (virtual_evdev, evdev_button, 1 - button_state);
-      return;
+                 event->button_state == CLUTTER_BUTTON_STATE_PRESSED ?
+                 "presses" : "releases");
+      update_button_count (virtual_evdev, evdev_button, 1 - event->button_state);
+      goto out;
     }
 
   meta_topic (META_DEBUG_INPUT,
               "Emitting virtual button-%s of button 0x%x (device %p)",
-              button_state == CLUTTER_BUTTON_STATE_PRESSED ? "press" : "release",
-              evdev_button, virtual_device);
+              event->button_state == CLUTTER_BUTTON_STATE_PRESSED ?
+              "press" : "release",
+              evdev_button, virtual_evdev);
 
-  meta_seat_impl_notify_button (virtual_evdev->seat->impl,
-                                virtual_evdev->device,
-                                time_us,
+  meta_seat_impl_notify_button (seat,
+                                virtual_evdev->impl_state->device,
+                                event->time_us,
                                 evdev_button,
-                                button_state);
+                                event->button_state);
+ out:
+  g_task_return_boolean (task, TRUE);
+  return G_SOURCE_REMOVE;
 }
 
 static void
-meta_virtual_input_device_native_notify_key (ClutterVirtualInputDevice *virtual_device,
-                                             uint64_t                   time_us,
-                                             uint32_t                   key,
-                                             ClutterKeyState            key_state)
+meta_virtual_input_device_native_notify_button (ClutterVirtualInputDevice *virtual_device,
+                                                uint64_t                   time_us,
+                                                uint32_t                   button,
+                                                ClutterButtonState         button_state)
 {
+  MetaVirtualEventButton *event;
   MetaVirtualInputDeviceNative *virtual_evdev =
     META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
-  int key_count;
+  GTask *task;
 
-  g_return_if_fail (virtual_evdev->device != NULL);
+  g_return_if_fail (virtual_evdev->impl_state->device != NULL);
 
-  if (time_us == CLUTTER_CURRENT_TIME)
-    time_us = g_get_monotonic_time ();
+  event = g_new0 (MetaVirtualEventButton, 1);
+  event->time_us = time_us;
+  event->button = button;
+  event->button_state = button_state;
 
-  if (get_button_type (key) != EVDEV_BUTTON_TYPE_KEY)
+  task = g_task_new (virtual_device, NULL, NULL, NULL);
+  g_task_set_task_data (task, event, g_free);
+  meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
+                                 (GSourceFunc) notify_button);
+  g_object_unref (task);
+}
+
+static gboolean
+notify_key (GTask *task)
+{
+  MetaVirtualInputDeviceNative *virtual_evdev =
+    g_task_get_source_object (task);
+  MetaSeatImpl *seat = virtual_evdev->seat->impl;
+  MetaVirtualEventKey *event = g_task_get_task_data (task);
+  int key_count;
+
+  if (event->time_us == CLUTTER_CURRENT_TIME)
+    event->time_us = g_get_monotonic_time ();
+
+  if (get_button_type (event->key) != EVDEV_BUTTON_TYPE_KEY)
     {
-      g_warning ("Unknown/invalid virtual device key 0x%x pressed", key);
-      return;
+      g_warning ("Unknown/invalid virtual device key 0x%x pressed", event->key);
+      goto out;
     }
 
-  key_count = update_button_count (virtual_evdev, key, key_state);
+  key_count = update_button_count (virtual_evdev, event->key, event->key_state);
   if (key_count < 0 || key_count > 1)
     {
-      g_warning ("Received multiple virtual 0x%x key %s (ignoring)", key,
-                 key_state == CLUTTER_KEY_STATE_PRESSED ? "presses" : "releases");
-      update_button_count (virtual_evdev, key, 1 - key_state);
-      return;
+      g_warning ("Received multiple virtual 0x%x key %s (ignoring)", event->key,
+                 event->key_state == CLUTTER_KEY_STATE_PRESSED ?
+                 "presses" : "releases");
+      update_button_count (virtual_evdev, event->key, 1 - event->key_state);
+      goto out;
     }
 
   meta_topic (META_DEBUG_INPUT,
               "Emitting virtual key-%s of key 0x%x (device %p)",
-              key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
-              key, virtual_device);
-
-  meta_seat_impl_notify_key (virtual_evdev->seat->impl,
-                             virtual_evdev->device,
-                             time_us,
-                             key,
-                             key_state,
+              event->key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
+              event->key, virtual_evdev);
+
+  meta_seat_impl_notify_key (seat,
+                             virtual_evdev->impl_state->device,
+                             event->time_us,
+                             event->key,
+                             event->key_state,
                              TRUE);
+
+ out:
+  g_task_return_boolean (task, TRUE);
+  return G_SOURCE_REMOVE;
+}
+
+static void
+meta_virtual_input_device_native_notify_key (ClutterVirtualInputDevice *virtual_device,
+                                             uint64_t                   time_us,
+                                             uint32_t                   key,
+                                             ClutterKeyState            key_state)
+{
+  MetaVirtualEventKey *event;
+  MetaVirtualInputDeviceNative *virtual_evdev =
+    META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
+  GTask *task;
+
+  g_return_if_fail (virtual_evdev->impl_state->device != NULL);
+
+  event = g_new0 (MetaVirtualEventKey, 1);
+  event->time_us = time_us;
+  event->key = key;
+  event->key_state = key_state;
+
+  task = g_task_new (virtual_device, NULL, NULL, NULL);
+  g_task_set_task_data (task, event, g_free);
+  meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
+                                 (GSourceFunc) notify_key);
+  g_object_unref (task);
 }
 
 static gboolean
@@ -383,7 +538,7 @@ apply_level_modifiers (ClutterVirtualInputDevice *virtual_device,
                                                  &keycode, NULL))
     return;
 
-  clutter_input_device_keycode_to_evdev (virtual_evdev->device,
+  clutter_input_device_keycode_to_evdev (virtual_evdev->impl_state->device,
                                          keycode, &evcode);
 
   meta_topic (META_DEBUG_INPUT,
@@ -392,72 +547,101 @@ apply_level_modifiers (ClutterVirtualInputDevice *virtual_device,
               evcode, virtual_device);
 
   meta_seat_impl_notify_key (virtual_evdev->seat->impl,
-                             virtual_evdev->device,
+                             virtual_evdev->impl_state->device,
                              time_us,
                              evcode,
                              key_state,
                              TRUE);
 }
 
-static void
-meta_virtual_input_device_native_notify_keyval (ClutterVirtualInputDevice *virtual_device,
-                                                uint64_t                   time_us,
-                                                uint32_t                   keyval,
-                                                ClutterKeyState            key_state)
+static gboolean
+notify_keyval (GTask *task)
 {
   MetaVirtualInputDeviceNative *virtual_evdev =
-    META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
+    g_task_get_source_object (task);
+  ClutterVirtualInputDevice *virtual_device =
+    CLUTTER_VIRTUAL_INPUT_DEVICE (virtual_evdev);
+  MetaSeatImpl *seat = virtual_evdev->seat->impl;
+  MetaVirtualEventKey *event = g_task_get_task_data (task);
   int key_count;
   guint keycode = 0, level = 0, evcode = 0;
 
-  g_return_if_fail (virtual_evdev->device != NULL);
-
-  if (time_us == CLUTTER_CURRENT_TIME)
-    time_us = g_get_monotonic_time ();
+  if (event->time_us == CLUTTER_CURRENT_TIME)
+    event->time_us = g_get_monotonic_time ();
 
   if (!pick_keycode_for_keyval_in_current_group (virtual_device,
-                                                 keyval, &keycode, &level))
+                                                 event->key, &keycode, &level))
     {
-      g_warning ("No keycode found for keyval %x in current group", keyval);
-      return;
+      g_warning ("No keycode found for keyval %x in current group", event->key);
+      goto out;
     }
 
-  clutter_input_device_keycode_to_evdev (virtual_evdev->device,
+  clutter_input_device_keycode_to_evdev (virtual_evdev->impl_state->device,
                                          keycode, &evcode);
 
   if (get_button_type (evcode) != EVDEV_BUTTON_TYPE_KEY)
     {
       g_warning ("Unknown/invalid virtual device key 0x%x pressed", evcode);
-      return;
+      goto out;
     }
 
-  key_count = update_button_count (virtual_evdev, evcode, key_state);
+  key_count = update_button_count (virtual_evdev, evcode, event->key_state);
   if (key_count < 0 || key_count > 1)
     {
       g_warning ("Received multiple virtual 0x%x key %s (ignoring)", evcode,
-                 key_state == CLUTTER_KEY_STATE_PRESSED ? "presses" : "releases");
-      update_button_count (virtual_evdev, evcode, 1 - key_state);
-      return;
+                 event->key_state == CLUTTER_KEY_STATE_PRESSED ?
+                 "presses" : "releases");
+      update_button_count (virtual_evdev, evcode, 1 - event->key_state);
+      goto out;
     }
 
   meta_topic (META_DEBUG_INPUT,
               "Emitting virtual key-%s of key 0x%x with modifier level %d, "
               "press count %d (device %p)",
-              key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
-              evcode, level, key_count, virtual_device);
+              event->key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
+              evcode, level, key_count, virtual_evdev);
 
-  if (key_state)
-    apply_level_modifiers (virtual_device, time_us, level, key_state);
+  if (event->key_state)
+    apply_level_modifiers (virtual_device, event->time_us, level, event->key_state);
 
-  meta_seat_impl_notify_key (virtual_evdev->seat->impl,
-                             virtual_evdev->device,
-                             time_us,
+  meta_seat_impl_notify_key (seat,
+                             virtual_evdev->impl_state->device,
+                             event->time_us,
                              evcode,
-                             key_state,
+                             event->key_state,
                              TRUE);
 
-  if (!key_state)
-    apply_level_modifiers (virtual_device, time_us, level, key_state);
+  if (!event->key_state)
+    apply_level_modifiers (virtual_device, event->time_us, level, event->key_state);
+
+ out:
+  g_task_return_boolean (task, TRUE);
+  return G_SOURCE_REMOVE;
+}
+
+static void
+meta_virtual_input_device_native_notify_keyval (ClutterVirtualInputDevice *virtual_device,
+                                                uint64_t                   time_us,
+                                                uint32_t                   keyval,
+                                                ClutterKeyState            key_state)
+{
+  MetaVirtualEventKey *event;
+  MetaVirtualInputDeviceNative *virtual_evdev =
+    META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
+  GTask *task;
+
+  g_return_if_fail (virtual_evdev->impl_state->device != NULL);
+
+  event = g_new0 (MetaVirtualEventKey, 1);
+  event->time_us = time_us;
+  event->key = keyval;
+  event->key_state = key_state;
+
+  task = g_task_new (virtual_device, NULL, NULL, NULL);
+  g_task_set_task_data (task, event, g_free);
+  meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
+                                 (GSourceFunc) notify_keyval);
+  g_object_unref (task);
 }
 
 static void
@@ -489,28 +673,74 @@ direction_to_discrete (ClutterScrollDirection direction,
     }
 }
 
+static gboolean
+notify_discrete_scroll (GTask *task)
+{
+  MetaVirtualInputDeviceNative *virtual_evdev =
+    g_task_get_source_object (task);
+  MetaSeatImpl *seat = virtual_evdev->seat->impl;
+  MetaVirtualEventScroll *event = g_task_get_task_data (task);
+  double discrete_dx = 0.0, discrete_dy = 0.0;
+
+  if (event->time_us == CLUTTER_CURRENT_TIME)
+    event->time_us = g_get_monotonic_time ();
+
+  direction_to_discrete (event->direction, &discrete_dx, &discrete_dy);
+
+  meta_seat_impl_notify_discrete_scroll (seat,
+                                         virtual_evdev->impl_state->device,
+                                         event->time_us,
+                                         discrete_dx, discrete_dy,
+                                         event->scroll_source);
+
+  g_task_return_boolean (task, TRUE);
+  return G_SOURCE_REMOVE;
+}
+
 static void
 meta_virtual_input_device_native_notify_discrete_scroll (ClutterVirtualInputDevice *virtual_device,
                                                          uint64_t                   time_us,
                                                          ClutterScrollDirection     direction,
                                                          ClutterScrollSource        scroll_source)
 {
+  MetaVirtualEventScroll *event;
   MetaVirtualInputDeviceNative *virtual_evdev =
     META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
-  double discrete_dx = 0.0, discrete_dy = 0.0;
+  GTask *task;
 
-  g_return_if_fail (virtual_evdev->device != NULL);
+  g_return_if_fail (virtual_evdev->impl_state->device != NULL);
 
-  if (time_us == CLUTTER_CURRENT_TIME)
-    time_us = g_get_monotonic_time ();
+  event = g_new0 (MetaVirtualEventScroll, 1);
+  event->time_us = time_us;
+  event->direction = direction;
+  event->scroll_source = scroll_source;
 
-  direction_to_discrete (direction, &discrete_dx, &discrete_dy);
+  task = g_task_new (virtual_device, NULL, NULL, NULL);
+  g_task_set_task_data (task, event, g_free);
+  meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
+                                 (GSourceFunc) notify_discrete_scroll);
+  g_object_unref (task);
+}
 
-  meta_seat_impl_notify_discrete_scroll (virtual_evdev->seat->impl,
-                                         virtual_evdev->device,
-                                         time_us,
-                                         discrete_dx, discrete_dy,
-                                         scroll_source);
+static gboolean
+notify_scroll_continuous (GTask *task)
+{
+  MetaVirtualInputDeviceNative *virtual_evdev =
+    g_task_get_source_object (task);
+  MetaSeatImpl *seat = virtual_evdev->seat->impl;
+  MetaVirtualEventScroll *event = g_task_get_task_data (task);
+
+  if (event->time_us == CLUTTER_CURRENT_TIME)
+    event->time_us = g_get_monotonic_time ();
+
+  meta_seat_impl_notify_scroll_continuous (seat,
+                                           virtual_evdev->impl_state->device,
+                                           event->time_us,
+                                           event->dx, event->dy,
+                                           event->scroll_source,
+                                           CLUTTER_SCROLL_FINISHED_NONE);
+  g_task_return_boolean (task, TRUE);
+  return G_SOURCE_REMOVE;
 }
 
 static void
@@ -521,20 +751,58 @@ meta_virtual_input_device_native_notify_scroll_continuous (ClutterVirtualInputDe
                                                            ClutterScrollSource        scroll_source,
                                                            ClutterScrollFinishFlags   finish_flags)
 {
+  MetaVirtualEventScroll *event;
   MetaVirtualInputDeviceNative *virtual_evdev =
     META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
+  GTask *task;
+
+  g_return_if_fail (virtual_evdev->impl_state->device != NULL);
+
+  event = g_new0 (MetaVirtualEventScroll, 1);
+  event->time_us = time_us;
+  event->dx = dx;
+  event->dy = dy;
+  event->scroll_source = scroll_source;
+  event->finish_flags = finish_flags;
+
+  task = g_task_new (virtual_device, NULL, NULL, NULL);
+  g_task_set_task_data (task, event, g_free);
+  meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
+                                 (GSourceFunc) notify_scroll_continuous);
+  g_object_unref (task);
+}
+
+static gboolean
+notify_touch_down (GTask *task)
+{
+  MetaVirtualInputDeviceNative *virtual_evdev =
+    g_task_get_source_object (task);
+  MetaSeatImpl *seat = virtual_evdev->seat->impl;
+  MetaVirtualEventTouch *event = g_task_get_task_data (task);
+  MetaTouchState *touch_state;
 
-  g_return_if_fail (virtual_evdev->device != NULL);
+  if (event->time_us == CLUTTER_CURRENT_TIME)
+    event->time_us = g_get_monotonic_time ();
 
-  if (time_us == CLUTTER_CURRENT_TIME)
-    time_us = g_get_monotonic_time ();
+  touch_state = meta_seat_impl_acquire_touch_state (seat,
+                                                    event->device_slot);
+  if (!touch_state)
+    goto out;
 
-  meta_seat_impl_notify_scroll_continuous (virtual_evdev->seat->impl,
-                                           virtual_evdev->device,
-                                           time_us,
-                                           dx, dy,
-                                           scroll_source,
-                                           CLUTTER_SCROLL_FINISHED_NONE);
+  touch_state->coords.x = event->x;
+  touch_state->coords.y = event->y;
+
+  meta_seat_impl_notify_touch_event (seat,
+                                     virtual_evdev->impl_state->device,
+                                     CLUTTER_TOUCH_BEGIN,
+                                     event->time_us,
+                                     touch_state->seat_slot,
+                                     touch_state->coords.x,
+                                     touch_state->coords.y);
+
+ out:
+  g_task_return_boolean (task, TRUE);
+  return G_SOURCE_REMOVE;
 }
 
 static void
@@ -544,32 +812,57 @@ meta_virtual_input_device_native_notify_touch_down (ClutterVirtualInputDevice *v
                                                     double                     x,
                                                     double                     y)
 {
+  MetaVirtualEventTouch *event;
   MetaVirtualInputDeviceNative *virtual_evdev =
     META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
-  MetaTouchState *touch_state;
-  guint seat_slot;
+  GTask *task;
 
-  g_return_if_fail (virtual_evdev->device != NULL);
+  g_return_if_fail (virtual_evdev->impl_state->device != NULL);
 
-  if (time_us == CLUTTER_CURRENT_TIME)
-    time_us = g_get_monotonic_time ();
+  event = g_new0 (MetaVirtualEventTouch, 1);
+  event->time_us = time_us;
+  event->device_slot = virtual_evdev->slot_base + (guint) device_slot;
+  event->x = x;
+  event->y = y;
 
-  seat_slot = virtual_evdev->slot_base + (guint) device_slot;
-  touch_state = meta_seat_impl_acquire_touch_state (virtual_evdev->seat->impl,
-                                                    seat_slot);
+  task = g_task_new (virtual_device, NULL, NULL, NULL);
+  g_task_set_task_data (task, event, g_free);
+  meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
+                                 (GSourceFunc) notify_touch_down);
+  g_object_unref (task);
+}
+
+static gboolean
+notify_touch_motion (GTask *task)
+{
+  MetaVirtualInputDeviceNative *virtual_evdev =
+    g_task_get_source_object (task);
+  MetaSeatImpl *seat = virtual_evdev->seat->impl;
+  MetaVirtualEventTouch *event = g_task_get_task_data (task);
+  MetaTouchState *touch_state;
+
+  if (event->time_us == CLUTTER_CURRENT_TIME)
+    event->time_us = g_get_monotonic_time ();
+
+  touch_state = meta_seat_impl_lookup_touch_state (seat,
+                                                   event->device_slot);
   if (!touch_state)
-    return;
+    goto out;
 
-  touch_state->coords.x = x;
-  touch_state->coords.y = y;
+  touch_state->coords.x = event->x;
+  touch_state->coords.y = event->y;
 
-  meta_seat_impl_notify_touch_event (virtual_evdev->seat->impl,
-                                     virtual_evdev->device,
-                                     CLUTTER_TOUCH_BEGIN,
-                                     time_us,
+  meta_seat_impl_notify_touch_event (seat,
+                                     virtual_evdev->impl_state->device,
+                                     CLUTTER_TOUCH_UPDATE,
+                                     event->time_us,
                                      touch_state->seat_slot,
                                      touch_state->coords.x,
                                      touch_state->coords.y);
+
+ out:
+  g_task_return_boolean (task, TRUE);
+  return G_SOURCE_REMOVE;
 }
 
 static void
@@ -579,32 +872,57 @@ meta_virtual_input_device_native_notify_touch_motion (ClutterVirtualInputDevice
                                                       double                     x,
                                                       double                     y)
 {
+  MetaVirtualEventTouch *event;
   MetaVirtualInputDeviceNative *virtual_evdev =
     META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
-  MetaTouchState *touch_state;
-  guint seat_slot;
+  GTask *task;
 
-  g_return_if_fail (virtual_evdev->device != NULL);
+  g_return_if_fail (virtual_evdev->impl_state->device != NULL);
 
-  if (time_us == CLUTTER_CURRENT_TIME)
-    time_us = g_get_monotonic_time ();
+  event = g_new0 (MetaVirtualEventTouch, 1);
+  event->time_us = time_us;
+  event->device_slot = virtual_evdev->slot_base + (guint) device_slot;
+  event->x = x;
+  event->y = y;
 
-  seat_slot = virtual_evdev->slot_base + (guint) device_slot;
-  touch_state = meta_seat_impl_lookup_touch_state (virtual_evdev->seat->impl,
-                                                   seat_slot);
-  if (!touch_state)
-    return;
+  task = g_task_new (virtual_device, NULL, NULL, NULL);
+  g_task_set_task_data (task, event, g_free);
+  meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
+                                 (GSourceFunc) notify_touch_motion);
+  g_object_unref (task);
+}
 
-  touch_state->coords.x = x;
-  touch_state->coords.y = y;
+static gboolean
+notify_touch_up (GTask *task)
+{
+  MetaVirtualInputDeviceNative *virtual_evdev =
+    g_task_get_source_object (task);
+  MetaSeatImpl *seat = virtual_evdev->seat->impl;
+  MetaVirtualEventTouch *event = g_task_get_task_data (task);
+  MetaTouchState *touch_state;
 
-  meta_seat_impl_notify_touch_event (virtual_evdev->seat->impl,
-                                     virtual_evdev->device,
-                                     CLUTTER_TOUCH_BEGIN,
-                                     time_us,
+  if (event->time_us == CLUTTER_CURRENT_TIME)
+    event->time_us = g_get_monotonic_time ();
+
+  touch_state = meta_seat_impl_lookup_touch_state (seat,
+                                                   event->device_slot);
+  if (!touch_state)
+    goto out;
+
+  meta_seat_impl_notify_touch_event (seat,
+                                     virtual_evdev->impl_state->device,
+                                     CLUTTER_TOUCH_END,
+                                     event->time_us,
                                      touch_state->seat_slot,
                                      touch_state->coords.x,
                                      touch_state->coords.y);
+
+  meta_seat_impl_release_touch_state (virtual_evdev->seat->impl,
+                                      touch_state->seat_slot);
+
+ out:
+  g_task_return_boolean (task, TRUE);
+  return G_SOURCE_REMOVE;
 }
 
 static void
@@ -612,32 +930,22 @@ meta_virtual_input_device_native_notify_touch_up (ClutterVirtualInputDevice *vir
                                                   uint64_t                   time_us,
                                                   int                        device_slot)
 {
+  MetaVirtualEventTouch *event;
   MetaVirtualInputDeviceNative *virtual_evdev =
     META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
-  MetaTouchState *touch_state;
-  guint seat_slot;
+  GTask *task;
 
-  g_return_if_fail (virtual_evdev->device != NULL);
-
-  if (time_us == CLUTTER_CURRENT_TIME)
-    time_us = g_get_monotonic_time ();
-
-  seat_slot = virtual_evdev->slot_base + (guint) device_slot;
-  touch_state = meta_seat_impl_lookup_touch_state (virtual_evdev->seat->impl,
-                                                   seat_slot);
-  if (!touch_state)
-    return;
+  g_return_if_fail (virtual_evdev->impl_state->device != NULL);
 
-  meta_seat_impl_notify_touch_event (virtual_evdev->seat->impl,
-                                     virtual_evdev->device,
-                                     CLUTTER_TOUCH_BEGIN,
-                                     time_us,
-                                     touch_state->seat_slot,
-                                     touch_state->coords.x,
-                                     touch_state->coords.y);
+  event = g_new0 (MetaVirtualEventTouch, 1);
+  event->time_us = time_us;
+  event->device_slot = virtual_evdev->slot_base + (guint) device_slot;
 
-  meta_seat_impl_release_touch_state (virtual_evdev->seat->impl,
-                                      touch_state->seat_slot);
+  task = g_task_new (virtual_device, NULL, NULL, NULL);
+  g_task_set_task_data (task, event, g_free);
+  meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
+                                 (GSourceFunc) notify_touch_up);
+  g_object_unref (task);
 }
 
 static void
@@ -701,14 +1009,18 @@ meta_virtual_input_device_native_constructed (GObject *object)
               "Creating new virtual input device of type %d (%p)",
               device_type, virtual_device);
 
-  virtual_evdev->device =
+  virtual_evdev->impl_state = g_new0 (ImplState, 1);
+  virtual_evdev->impl_state->device =
     meta_input_device_native_new_virtual (virtual_evdev->seat->impl,
                                           device_type,
                                           CLUTTER_INPUT_MODE_PHYSICAL);
+}
 
-  g_signal_emit_by_name (virtual_evdev->seat,
-                         "device-added",
-                         virtual_evdev->device);
+static void
+impl_state_free (ImplState *impl_state)
+{
+  g_clear_object (&impl_state->device);
+  g_free (impl_state);
 }
 
 static void
@@ -721,14 +1033,18 @@ meta_virtual_input_device_native_dispose (GObject *object)
   GObjectClass *object_class =
     G_OBJECT_CLASS (meta_virtual_input_device_native_parent_class);
 
-  if (virtual_evdev->device)
+  if (virtual_evdev->impl_state)
     {
-      release_pressed_buttons (virtual_device);
-      g_signal_emit_by_name (virtual_evdev->seat,
-                             "device-removed",
-                             virtual_evdev->device);
+      GTask *task;
+
+      task = g_task_new (virtual_device, NULL, NULL, NULL);
+      g_task_set_task_data (task, virtual_evdev->impl_state,
+                            (GDestroyNotify) impl_state_free);
+      meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
+                                     (GSourceFunc) release_device);
+      g_object_unref (task);
 
-      g_clear_object (&virtual_evdev->device);
+      virtual_evdev->impl_state = NULL;
     }
 
   meta_seat_native_release_touch_slots (virtual_evdev->seat,



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