[mutter/wip/carlosg/input-thread: 86/88] backends/native: Add input thread inside MetaSeatImpl




commit 4f958b276e83449d72e85ab6531dddb4f89eeebc
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Aug 12 18:04:34 2020 +0200

    backends/native: Add input thread inside MetaSeatImpl
    
    This (now) doesn't change anything in regards to the API that the UI
    thread should access from the MetaSeatImpl. The MetaInputDeviceNative,
    MetaInputSettings and MetaKeymap objects are now considered owned by
    the input thread, as well as all of libinput objects.
    
    The MetaEventSource now dispatches events in a GMainContext that is
    the thread default to this thread, and all UI-thread-accessible API
    (seat and virtual input device API) will be handled in a serialized
    manner by that same input thread.
    
    The MetaSeatImpl itself is still considered to be owned by the caller
    thread, and all the signals that this object emits will be emitted in
    the GMainContext that is default at the time of calling
    meta_seat_impl_new().
    
    The MetaInputSettings configuration changes will likewise be handled
    in the input thread, close to libinput devices.

 src/backends/native/meta-input-device-native.c |  63 ++++--
 src/backends/native/meta-input-device-native.h |   6 +-
 src/backends/native/meta-seat-impl.c           | 279 ++++++++++++++++++-------
 src/backends/native/meta-seat-impl.h           |   9 +-
 4 files changed, 256 insertions(+), 101 deletions(-)
---
diff --git a/src/backends/native/meta-input-device-native.c b/src/backends/native/meta-input-device-native.c
index 899c2613b9..d64bdbd016 100644
--- a/src/backends/native/meta-input-device-native.c
+++ b/src/backends/native/meta-input-device-native.c
@@ -48,7 +48,7 @@ typedef struct _SlowKeysEventPending
 {
   MetaInputDeviceNative *device;
   ClutterEvent *event;
-  guint timer;
+  GSource *timer;
 } SlowKeysEventPending;
 
 typedef struct _PadFeature PadFeature;
@@ -207,7 +207,7 @@ meta_input_device_native_free_pending_slow_key (gpointer data)
   SlowKeysEventPending *slow_keys_event = data;
 
   clutter_event_free (slow_keys_event->event);
-  g_clear_handle_id (&slow_keys_event->timer, g_source_remove);
+  g_clear_pointer (&slow_keys_event->timer, g_source_destroy);
   g_free (slow_keys_event);
 }
 
@@ -264,6 +264,24 @@ find_pending_event_by_keycode (gconstpointer a,
   return kb->hardware_keycode - ka->hardware_keycode;
 }
 
+static GSource *
+timeout_source_new (MetaSeatImpl *seat_impl,
+                    guint         interval,
+                    GSourceFunc   func,
+                    gpointer      user_data)
+{
+  GSource *source;
+
+  source = g_timeout_source_new (interval);
+  g_source_set_callback (source,
+                         func,
+                         user_data, NULL);
+  g_source_attach (source, seat_impl->input_context);
+  g_source_unref (source);
+
+  return source;
+}
+
 static gboolean
 start_slow_keys (ClutterEvent          *event,
                  MetaInputDeviceNative *device)
@@ -278,9 +296,10 @@ start_slow_keys (ClutterEvent          *event,
   slow_keys_event->device = device;
   slow_keys_event->event = clutter_event_copy (event);
   slow_keys_event->timer =
-    clutter_threads_add_timeout (get_slow_keys_delay (CLUTTER_INPUT_DEVICE (device)),
-                                 trigger_slow_keys,
-                                 slow_keys_event);
+    timeout_source_new (device->seat_impl,
+                        get_slow_keys_delay (CLUTTER_INPUT_DEVICE (device)),
+                        trigger_slow_keys,
+                        slow_keys_event);
   device->slow_keys_list = g_list_append (device->slow_keys_list, slow_keys_event);
 
   if (device->a11y_flags & META_A11Y_SLOW_KEYS_BEEP_PRESS)
@@ -346,15 +365,16 @@ start_bounce_keys (ClutterEvent          *event,
 
   device->debounce_key = ((ClutterKeyEvent *) event)->hardware_keycode;
   device->debounce_timer =
-    clutter_threads_add_timeout (get_debounce_delay (CLUTTER_INPUT_DEVICE (device)),
-                                 clear_bounce_keys,
-                                 device);
+    timeout_source_new (device->seat_impl,
+                        get_debounce_delay (CLUTTER_INPUT_DEVICE (device)),
+                        clear_bounce_keys,
+                        device);
 }
 
 static void
 stop_bounce_keys (MetaInputDeviceNative *device)
 {
-  g_clear_handle_id (&device->debounce_timer, g_source_remove);
+  g_clear_pointer (&device->debounce_timer, g_source_destroy);
 }
 
 static void
@@ -625,15 +645,16 @@ start_toggle_slowkeys (MetaInputDeviceNative *device)
     return;
 
   device->toggle_slowkeys_timer =
-    clutter_threads_add_timeout (8 * 1000 /* 8 secs */,
-                                 trigger_toggle_slowkeys,
-                                 device);
+    timeout_source_new (device->seat_impl,
+                        8 * 1000 /* 8 secs */,
+                        trigger_toggle_slowkeys,
+                        device);
 }
 
 static void
 stop_toggle_slowkeys (MetaInputDeviceNative *device)
 {
-  g_clear_handle_id (&device->toggle_slowkeys_timer, g_source_remove);
+  g_clear_pointer (&device->toggle_slowkeys_timer, g_source_destroy);
 }
 
 static void
@@ -892,18 +913,20 @@ trigger_mousekeys_move (gpointer data)
     {
       /* This is the first move, Secdule at mk_init_delay */
       device->move_mousekeys_timer =
-        clutter_threads_add_timeout (device->mousekeys_init_delay,
-                                     trigger_mousekeys_move,
-                                     device);
+        timeout_source_new (device->seat_impl,
+                            device->mousekeys_init_delay,
+                            trigger_mousekeys_move,
+                            device);
 
     }
   else
     {
       /* More moves, reschedule at mk_interval */
       device->move_mousekeys_timer =
-        clutter_threads_add_timeout (100, /* msec between mousekey events */
-                                     trigger_mousekeys_move,
-                                     device);
+        timeout_source_new (device->seat_impl,
+                            100, /* msec between mousekey events */
+                            trigger_mousekeys_move,
+                            device);
     }
 
   /* Pointer motion */
@@ -964,7 +987,7 @@ stop_mousekeys_move (MetaInputDeviceNative *device)
   device->mousekeys_first_motion_time = 0;
   device->mousekeys_last_motion_time = 0;
 
-  g_clear_handle_id (&device->move_mousekeys_timer, g_source_remove);
+  g_clear_pointer (&device->move_mousekeys_timer, g_source_destroy);
 }
 
 static void
diff --git a/src/backends/native/meta-input-device-native.h b/src/backends/native/meta-input-device-native.h
index 560081dfd6..603579708b 100644
--- a/src/backends/native/meta-input-device-native.h
+++ b/src/backends/native/meta-input-device-native.h
@@ -85,12 +85,12 @@ struct _MetaInputDeviceNative
   /* Keyboard a11y */
   MetaKeyboardA11yFlags a11y_flags;
   GList *slow_keys_list;
-  guint debounce_timer;
+  GSource *debounce_timer;
   uint16_t debounce_key;
   xkb_mod_mask_t stickykeys_depressed_mask;
   xkb_mod_mask_t stickykeys_latched_mask;
   xkb_mod_mask_t stickykeys_locked_mask;
-  guint toggle_slowkeys_timer;
+  GSource *toggle_slowkeys_timer;
   uint16_t shift_count;
   uint32_t last_shift_time;
   int mousekeys_btn;
@@ -101,7 +101,7 @@ struct _MetaInputDeviceNative
   guint mousekeys_accel_time;
   guint mousekeys_max_speed;
   double mousekeys_curve_factor;
-  guint move_mousekeys_timer;
+  GSource *move_mousekeys_timer;
   uint16_t last_mousekeys_key;
 };
 
diff --git a/src/backends/native/meta-seat-impl.c b/src/backends/native/meta-seat-impl.c
index dc48aeefab..d4b12e5f3b 100644
--- a/src/backends/native/meta-seat-impl.c
+++ b/src/backends/native/meta-seat-impl.c
@@ -119,7 +119,11 @@ enum
 
 static guint signals[N_SIGNALS] = { 0 };
 
-G_DEFINE_TYPE (MetaSeatImpl, meta_seat_impl, G_TYPE_OBJECT)
+static void meta_seat_impl_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (MetaSeatImpl, meta_seat_impl, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+                                                meta_seat_impl_initable_iface_init))
 
 static void process_events (MetaSeatImpl *seat_impl);
 void meta_seat_impl_constrain_pointer (MetaSeatImpl       *seat_impl,
@@ -135,7 +139,7 @@ void meta_seat_impl_filter_relative_motion (MetaSeatImpl       *seat_impl,
                                             float               y,
                                             float              *dx,
                                             float              *dy);
-void meta_seat_impl_clear_repeat_timer (MetaSeatImpl *seat_impl);
+void meta_seat_impl_clear_repeat_source (MetaSeatImpl *seat_impl);
 
 void
 meta_seat_impl_run_input_task (MetaSeatImpl *seat_impl,
@@ -238,11 +242,11 @@ meta_seat_impl_release_touch_state (MetaSeatImpl *seat_impl,
 }
 
 void
-meta_seat_impl_clear_repeat_timer (MetaSeatImpl *seat_impl)
+meta_seat_impl_clear_repeat_source (MetaSeatImpl *seat_impl)
 {
-  if (seat_impl->repeat_timer)
+  if (seat_impl->repeat_source)
     {
-      g_clear_handle_id (&seat_impl->repeat_timer, g_source_remove);
+      g_source_destroy (seat_impl->repeat_source);
       g_clear_object (&seat_impl->repeat_device);
     }
 }
@@ -258,20 +262,18 @@ static gboolean
 keyboard_repeat (gpointer data)
 {
   MetaSeatImpl *seat_impl = data;
-  GSource *source;
 
   /* There might be events queued in libinput that could cancel the
      repeat timer. */
   dispatch_libinput (seat_impl);
-  if (!seat_impl->repeat_timer)
+  if (!seat_impl->repeat_source)
     return G_SOURCE_REMOVE;
 
   g_return_val_if_fail (seat_impl->repeat_device != NULL, G_SOURCE_REMOVE);
-  source = g_main_context_find_source_by_id (NULL, seat_impl->repeat_timer);
 
   meta_seat_impl_notify_key (seat_impl,
                              seat_impl->repeat_device,
-                             g_source_get_time (source),
+                             g_source_get_time (seat_impl->repeat_source),
                              seat_impl->repeat_key,
                              AUTOREPEAT_VALUE,
                              FALSE);
@@ -310,6 +312,65 @@ update_button_count (MetaSeatImpl *seat_impl,
     }
 }
 
+typedef struct
+{
+  MetaSeatImpl *seat_impl;
+  guint signal_id;
+  GArray *args;
+} MetaSeatSignalData;
+
+static gboolean
+emit_signal_in_main (MetaSeatSignalData *data)
+{
+  g_signal_emitv ((GValue *) data->args->data,
+                  data->signal_id,
+                  0, NULL);
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+signal_data_free (MetaSeatSignalData *data)
+{
+  g_array_unref (data->args);
+  g_free (data);
+}
+
+static void
+emit_signal (MetaSeatImpl *seat_impl,
+             guint         signal_id,
+             GValue       *args,
+             int           n_args)
+{
+  MetaSeatSignalData *emit_signal_data;
+  GSource *source;
+  GArray *array;
+  GValue self = G_VALUE_INIT;
+
+  g_value_init (&self, META_TYPE_SEAT_IMPL);
+  g_value_set_object (&self, seat_impl);
+
+  array = g_array_new (FALSE, FALSE, sizeof (GValue));
+  g_array_append_val (array, self);
+  if (args && n_args > 0)
+    g_array_append_vals (array, args, n_args);
+
+  emit_signal_data = g_new0 (MetaSeatSignalData, 1);
+  emit_signal_data->seat_impl = seat_impl;
+  emit_signal_data->signal_id = signal_id;
+  emit_signal_data->args = array;
+
+  source = g_idle_source_new ();
+  g_source_set_priority (source, G_PRIORITY_HIGH);
+  g_source_set_callback (source,
+                         (GSourceFunc) emit_signal_in_main,
+                         emit_signal_data,
+                         (GDestroyNotify) signal_data_free);
+
+  g_source_attach (source, seat_impl->main_context);
+  g_source_unref (source);
+}
+
 void
 meta_seat_impl_notify_key (MetaSeatImpl       *seat_impl,
                            ClutterInputDevice *device,
@@ -368,7 +429,7 @@ meta_seat_impl_notify_key (MetaSeatImpl       *seat_impl,
     {
       MetaInputDeviceNative *keyboard_native;
 
-      g_signal_emit (seat_impl, signals[MODS_STATE_CHANGED], 0);
+      emit_signal (seat_impl, signals[MODS_STATE_CHANGED], NULL, 0);
       meta_seat_impl_sync_leds (seat_impl);
       keyboard_native = META_INPUT_DEVICE_NATIVE (seat_impl->core_keyboard);
       meta_input_device_native_a11y_maybe_notify_toggle_keys (keyboard_native);
@@ -379,7 +440,8 @@ meta_seat_impl_notify_key (MetaSeatImpl       *seat_impl,
       !xkb_keymap_key_repeats (xkb_state_get_keymap (seat_impl->xkb),
                                keycode))
     {
-      meta_seat_impl_clear_repeat_timer (seat_impl);
+      seat_impl->repeat_count = 0;
+      meta_seat_impl_clear_repeat_source (seat_impl);
       return;
     }
 
@@ -396,7 +458,7 @@ meta_seat_impl_notify_key (MetaSeatImpl       *seat_impl,
       {
         uint32_t interval;
 
-        meta_seat_impl_clear_repeat_timer (seat_impl);
+        meta_seat_impl_clear_repeat_source (seat_impl);
         seat_impl->repeat_device = g_object_ref (device);
 
         if (seat_impl->repeat_count == 1)
@@ -404,12 +466,11 @@ meta_seat_impl_notify_key (MetaSeatImpl       *seat_impl,
         else
           interval = seat_impl->repeat_interval;
 
-        seat_impl->repeat_timer =
-          clutter_threads_add_timeout_full (CLUTTER_PRIORITY_EVENTS,
-                                            interval,
-                                            keyboard_repeat,
-                                            seat_impl,
-                                            NULL);
+        seat_impl->repeat_source = g_timeout_source_new (interval);
+        g_source_set_priority (seat_impl->repeat_source, CLUTTER_PRIORITY_EVENTS);
+        g_source_set_callback (seat_impl->repeat_source,
+                               keyboard_repeat, seat_impl, NULL);
+        g_source_attach (seat_impl->repeat_source, seat_impl->input_context);
         return;
       }
     default:
@@ -878,26 +939,13 @@ meta_seat_impl_notify_touch_event (MetaSeatImpl       *seat_impl,
 /*
  * MetaEventSource for reading input devices
  */
-static gboolean
-meta_event_prepare (GSource *source,
-                    int     *timeout)
-{
-  gboolean retval;
-
-  *timeout = -1;
-  retval = clutter_events_pending ();
-
-  return retval;
-}
-
 static gboolean
 meta_event_check (GSource *source)
 {
   MetaEventSource *event_source = (MetaEventSource *) source;
   gboolean retval;
 
-  retval = ((event_source->event_poll_fd.revents & G_IO_IN) ||
-            clutter_events_pending ());
+  retval = !!(event_source->event_poll_fd.revents & G_IO_IN);
 
   return retval;
 }
@@ -1375,19 +1423,13 @@ meta_event_dispatch (GSource     *g_source,
 
   seat_impl = source->seat_impl;
 
-  /* Don't queue more events if we haven't finished handling the previous batch
-   */
-  if (clutter_events_pending ())
-    goto queue_event;
-
   dispatch_libinput (seat_impl);
 
- queue_event:
-
   return TRUE;
 }
+
 static GSourceFuncs event_funcs = {
-  meta_event_prepare,
+  NULL,
   meta_event_check,
   meta_event_dispatch,
   NULL
@@ -1414,7 +1456,7 @@ meta_event_source_new (MetaSeatImpl *seat_impl)
   g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS);
   g_source_add_poll (source, &event_source->event_poll_fd);
   g_source_set_can_recurse (source, TRUE);
-  g_source_attach (source, NULL);
+  g_source_attach (source, seat_impl->input_context);
 
   return event_source;
 }
@@ -1497,8 +1539,13 @@ update_touch_mode (MetaSeatImpl *seat_impl)
 
   if (seat_impl->touch_mode != touch_mode)
     {
+      GValue value = G_VALUE_INIT;
+
+      g_value_init (&value, G_TYPE_BOOLEAN);
+      g_value_set_boolean (&value, touch_mode);
       seat_impl->touch_mode = touch_mode;
-      g_signal_emit (seat_impl, signals[TOUCH_MODE], 0, touch_mode);
+      emit_signal (seat_impl, signals[TOUCH_MODE], &value, 1);
+      g_value_unset (&value);
     }
 }
 
@@ -1555,8 +1602,8 @@ evdev_remove_device (MetaSeatImpl          *seat_impl,
   if (is_touchscreen || is_tablet_switch)
     update_touch_mode (seat_impl);
 
-  if (seat_impl->repeat_timer && seat_impl->repeat_device == device)
-    meta_seat_impl_clear_repeat_timer (seat_impl);
+  if (seat_impl->repeat_source && seat_impl->repeat_device == device)
+    meta_seat_impl_clear_repeat_source (seat_impl);
 
   g_object_unref (device);
 }
@@ -2484,35 +2531,21 @@ kbd_a11y_changed_cb (MetaInputSettings   *input_settings,
   meta_input_device_native_apply_kbd_a11y_settings (keyboard, a11y_settings);
 }
 
-static void
-meta_seat_impl_constructed (GObject *object)
+static gpointer
+input_thread (MetaSeatImpl *seat_impl)
 {
-  MetaSeatImpl *seat_impl = META_SEAT_IMPL (object);
-  ClutterInputDevice *device;
   MetaEventSource *source;
   struct udev *udev;
   struct xkb_keymap *xkb_keymap;
 
-  device = meta_input_device_native_new_virtual (
-      seat_impl, CLUTTER_POINTER_DEVICE,
-      CLUTTER_INPUT_MODE_LOGICAL);
-  seat_impl->pointer_x = INITIAL_POINTER_X;
-  seat_impl->pointer_y = INITIAL_POINTER_Y;
-  meta_input_device_native_set_coords (META_INPUT_DEVICE_NATIVE (device),
-                                       seat_impl->pointer_x,
-                                       seat_impl->pointer_y);
-  seat_impl->core_pointer = device;
-
-  device = meta_input_device_native_new_virtual (
-      seat_impl, CLUTTER_KEYBOARD_DEVICE,
-      CLUTTER_INPUT_MODE_LOGICAL);
-  seat_impl->core_keyboard = device;
+  g_main_context_push_thread_default (seat_impl->input_context);
 
   udev = udev_new ();
   if (G_UNLIKELY (udev == NULL))
     {
       g_warning ("Failed to create udev object");
-      return;
+      seat_impl->input_thread_initialized = TRUE;
+      return NULL;
     }
 
   seat_impl->libinput = libinput_udev_create_context (&libinput_interface,
@@ -2520,7 +2553,8 @@ meta_seat_impl_constructed (GObject *object)
   if (seat_impl->libinput == NULL)
     {
       g_critical ("Failed to create the libinput object.");
-      return;
+      seat_impl->input_thread_initialized = TRUE;
+      return NULL;
     }
 
   if (libinput_udev_assign_seat (seat_impl->libinput, seat_impl->seat_id) == -1)
@@ -2528,7 +2562,8 @@ meta_seat_impl_constructed (GObject *object)
       g_critical ("Failed to assign a seat to the libinput object.");
       libinput_unref (seat_impl->libinput);
       seat_impl->libinput = NULL;
-      return;
+      seat_impl->input_thread_initialized = TRUE;
+      return NULL;
     }
 
   udev_unref (udev);
@@ -2537,12 +2572,11 @@ meta_seat_impl_constructed (GObject *object)
   g_signal_connect_object (seat_impl->input_settings, "kbd-a11y-changed",
                            G_CALLBACK (kbd_a11y_changed_cb), seat_impl, 0);
 
-  seat_impl->udev_client = g_udev_client_new ((const char *[]) { "input", NULL });
-
   source = meta_event_source_new (seat_impl);
   seat_impl->event_source = source;
 
   seat_impl->keymap = g_object_new (META_TYPE_KEYMAP_NATIVE, NULL);
+
   xkb_keymap = meta_keymap_native_get_keyboard_map (seat_impl->keymap);
 
   if (xkb_keymap)
@@ -2561,6 +2595,71 @@ meta_seat_impl_constructed (GObject *object)
   seat_impl->has_tablet_switch = has_tablet_switch (seat_impl);
   update_touch_mode (seat_impl);
 
+  g_mutex_lock (&seat_impl->init_mutex);
+  seat_impl->input_thread_initialized = TRUE;
+  g_cond_signal (&seat_impl->init_cond);
+  g_mutex_unlock (&seat_impl->init_mutex);
+
+  seat_impl->input_loop = g_main_loop_new (seat_impl->input_context, FALSE);
+  g_main_loop_run (seat_impl->input_loop);
+  g_main_loop_unref (seat_impl->input_loop);
+
+  g_main_context_pop_thread_default (seat_impl->input_context);
+
+  return NULL;
+}
+
+static gboolean
+meta_seat_impl_initable_init (GInitable     *initable,
+                              GCancellable  *cancellable,
+                              GError       **error)
+{
+  MetaSeatImpl *seat_impl = META_SEAT_IMPL (initable);
+
+  seat_impl->input_context = g_main_context_new ();
+  seat_impl->main_context = g_main_context_ref_thread_default ();
+  g_assert (seat_impl->main_context == g_main_context_default ());
+
+  seat_impl->input_thread =
+    g_thread_try_new ("Mutter Input Thread",
+                      (GThreadFunc) input_thread,
+                      initable,
+                      error);
+  if (!seat_impl->input_thread)
+    return FALSE;
+
+  /* Initialize thread synchronously */
+  g_mutex_lock (&seat_impl->init_mutex);
+  while (!seat_impl->input_thread_initialized)
+    g_cond_wait (&seat_impl->init_cond, &seat_impl->init_mutex);
+  g_mutex_unlock (&seat_impl->init_mutex);
+
+  return TRUE;
+}
+
+static void
+meta_seat_impl_constructed (GObject *object)
+{
+  MetaSeatImpl *seat_impl = META_SEAT_IMPL (object);
+  ClutterInputDevice *device;
+
+  device = meta_input_device_native_new_virtual (
+      seat_impl, CLUTTER_POINTER_DEVICE,
+      CLUTTER_INPUT_MODE_LOGICAL);
+  seat_impl->pointer_x = INITIAL_POINTER_X;
+  seat_impl->pointer_y = INITIAL_POINTER_Y;
+  meta_input_device_native_set_coords (META_INPUT_DEVICE_NATIVE (device),
+                                       seat_impl->pointer_x,
+                                       seat_impl->pointer_y);
+  seat_impl->core_pointer = device;
+
+  device = meta_input_device_native_new_virtual (
+      seat_impl, CLUTTER_KEYBOARD_DEVICE,
+      CLUTTER_INPUT_MODE_LOGICAL);
+  seat_impl->core_keyboard = device;
+
+  seat_impl->udev_client = g_udev_client_new ((const char *[]) { "input", NULL });
+
   if (G_OBJECT_CLASS (meta_seat_impl_parent_class)->constructed)
     G_OBJECT_CLASS (meta_seat_impl_parent_class)->constructed (object);
 }
@@ -2627,6 +2726,9 @@ meta_seat_impl_finalize (GObject *object)
   MetaSeatImpl *seat_impl = META_SEAT_IMPL (object);
   GSList *iter;
 
+  g_main_loop_quit (seat_impl->input_loop);
+  g_thread_join (seat_impl->input_thread);
+
   for (iter = seat_impl->devices; iter; iter = g_slist_next (iter))
     {
       ClutterInputDevice *device = iter->data;
@@ -2645,7 +2747,7 @@ meta_seat_impl_finalize (GObject *object)
 
   xkb_state_unref (seat_impl->xkb);
 
-  meta_seat_impl_clear_repeat_timer (seat_impl);
+  meta_seat_impl_clear_repeat_source (seat_impl);
 
   g_free (seat_impl->seat_id);
 
@@ -2771,6 +2873,12 @@ meta_seat_impl_query_state (MetaSeatImpl         *seat_impl,
   return retval;
 }
 
+static void
+meta_seat_impl_initable_iface_init (GInitableIface *iface)
+{
+  iface->init = meta_seat_impl_initable_init;
+}
+
 static void
 meta_seat_impl_class_init (MetaSeatImplClass *klass)
 {
@@ -2845,6 +2953,9 @@ meta_seat_impl_init (MetaSeatImpl *seat_impl)
   seat_impl->repeat_delay = 250;     /* ms */
   seat_impl->repeat_interval = 33;   /* ms */
 
+  g_mutex_init (&seat_impl->init_mutex);
+  g_cond_init (&seat_impl->init_cond);
+
   seat_impl->barrier_manager = meta_barrier_manager_native_new ();
 }
 
@@ -3279,10 +3390,11 @@ MetaSeatImpl *
 meta_seat_impl_new (MetaSeatNative *seat_native,
                     const char     *seat_id)
 {
-  return g_object_new (META_TYPE_SEAT_IMPL,
-                       "seat", seat_native,
-                       "seat-id", seat_id,
-                       NULL);
+  return g_initable_new (META_TYPE_SEAT_IMPL,
+                         NULL, NULL,
+                         "seat", seat_native,
+                         "seat-id", seat_id,
+                         NULL);
 }
 
 void
@@ -3291,12 +3403,18 @@ meta_seat_impl_notify_kbd_a11y_flags_changed (MetaSeatImpl          *seat_impl,
                                               MetaKeyboardA11yFlags  what_changed)
 {
   MetaInputSettings *input_settings;
+  GValue values[] = { G_VALUE_INIT, G_VALUE_INIT };
 
   input_settings = seat_impl->input_settings;
   meta_input_settings_notify_kbd_a11y_change (input_settings,
                                               new_flags, what_changed);
-  g_signal_emit (seat_impl, signals[KBD_A11Y_FLAGS_CHANGED], 0,
-                 new_flags, what_changed);
+  g_value_init (&values[0], G_TYPE_UINT);
+  g_value_set_uint (&values[0], new_flags);
+  g_value_init (&values[1], G_TYPE_UINT);
+  g_value_set_uint (&values[1], what_changed);
+
+  emit_signal (seat_impl, signals[KBD_A11Y_FLAGS_CHANGED],
+               values, G_N_ELEMENTS (values));
 }
 
 void
@@ -3304,14 +3422,21 @@ meta_seat_impl_notify_kbd_a11y_mods_state_changed (MetaSeatImpl   *seat_impl,
                                                    xkb_mod_mask_t  new_latched_mods,
                                                    xkb_mod_mask_t  new_locked_mods)
 {
-  g_signal_emit (seat_impl, signals[KBD_A11Y_MODS_STATE_CHANGED], 0,
-                 new_latched_mods, new_locked_mods);
+  GValue values[] = { G_VALUE_INIT, G_VALUE_INIT };
+
+  g_value_init (&values[0], G_TYPE_UINT);
+  g_value_set_uint (&values[0], new_latched_mods);
+  g_value_init (&values[1], G_TYPE_UINT);
+  g_value_set_uint (&values[1], new_locked_mods);
+
+  emit_signal (seat_impl, signals[KBD_A11Y_MODS_STATE_CHANGED],
+               values, G_N_ELEMENTS (values));
 }
 
 void
 meta_seat_impl_notify_bell (MetaSeatImpl *seat_impl)
 {
-  g_signal_emit (seat_impl, signals[BELL], 0);
+  emit_signal (seat_impl, signals[BELL], NULL, 0);
 }
 
 MetaInputSettings *
diff --git a/src/backends/native/meta-seat-impl.h b/src/backends/native/meta-seat-impl.h
index 3dddcd5056..05edb35db1 100644
--- a/src/backends/native/meta-seat-impl.h
+++ b/src/backends/native/meta-seat-impl.h
@@ -54,7 +54,13 @@ struct _MetaSeatImpl
 {
   GObject parent_instance;
 
+  GMainContext *main_context;
   GMainContext *input_context;
+  GMainLoop *input_loop;
+  GThread *input_thread;
+  GMutex init_mutex;
+  GCond init_cond;
+
   MetaSeatNative *seat_native;
   char *seat_id;
   MetaEventSource *event_source;
@@ -91,6 +97,7 @@ struct _MetaSeatImpl
   gboolean has_touchscreen;
   gboolean has_tablet_switch;
   gboolean touch_mode;
+  gboolean input_thread_initialized;
 
   /* keyboard repeat */
   gboolean repeat;
@@ -98,8 +105,8 @@ struct _MetaSeatImpl
   uint32_t repeat_interval;
   uint32_t repeat_key;
   uint32_t repeat_count;
-  uint32_t repeat_timer;
   ClutterInputDevice *repeat_device;
+  GSource *repeat_source;
 
   float pointer_x;
   float pointer_y;


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