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.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1403>
This commit is contained in:
Carlos Garnacho 2020-08-12 18:04:34 +02:00 committed by Marge Bot
parent 321b971a96
commit 820262e537
4 changed files with 256 additions and 101 deletions

View File

@ -48,7 +48,7 @@ typedef struct _SlowKeysEventPending
{ {
MetaInputDeviceNative *device; MetaInputDeviceNative *device;
ClutterEvent *event; ClutterEvent *event;
guint timer; GSource *timer;
} SlowKeysEventPending; } SlowKeysEventPending;
typedef struct _PadFeature PadFeature; typedef struct _PadFeature PadFeature;
@ -207,7 +207,7 @@ meta_input_device_native_free_pending_slow_key (gpointer data)
SlowKeysEventPending *slow_keys_event = data; SlowKeysEventPending *slow_keys_event = data;
clutter_event_free (slow_keys_event->event); 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); g_free (slow_keys_event);
} }
@ -264,6 +264,24 @@ find_pending_event_by_keycode (gconstpointer a,
return kb->hardware_keycode - ka->hardware_keycode; 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 static gboolean
start_slow_keys (ClutterEvent *event, start_slow_keys (ClutterEvent *event,
MetaInputDeviceNative *device) MetaInputDeviceNative *device)
@ -278,9 +296,10 @@ start_slow_keys (ClutterEvent *event,
slow_keys_event->device = device; slow_keys_event->device = device;
slow_keys_event->event = clutter_event_copy (event); slow_keys_event->event = clutter_event_copy (event);
slow_keys_event->timer = slow_keys_event->timer =
clutter_threads_add_timeout (get_slow_keys_delay (CLUTTER_INPUT_DEVICE (device)), timeout_source_new (device->seat_impl,
trigger_slow_keys, get_slow_keys_delay (CLUTTER_INPUT_DEVICE (device)),
slow_keys_event); trigger_slow_keys,
slow_keys_event);
device->slow_keys_list = g_list_append (device->slow_keys_list, 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) 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_key = ((ClutterKeyEvent *) event)->hardware_keycode;
device->debounce_timer = device->debounce_timer =
clutter_threads_add_timeout (get_debounce_delay (CLUTTER_INPUT_DEVICE (device)), timeout_source_new (device->seat_impl,
clear_bounce_keys, get_debounce_delay (CLUTTER_INPUT_DEVICE (device)),
device); clear_bounce_keys,
device);
} }
static void static void
stop_bounce_keys (MetaInputDeviceNative *device) 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 static void
@ -625,15 +645,16 @@ start_toggle_slowkeys (MetaInputDeviceNative *device)
return; return;
device->toggle_slowkeys_timer = device->toggle_slowkeys_timer =
clutter_threads_add_timeout (8 * 1000 /* 8 secs */, timeout_source_new (device->seat_impl,
trigger_toggle_slowkeys, 8 * 1000 /* 8 secs */,
device); trigger_toggle_slowkeys,
device);
} }
static void static void
stop_toggle_slowkeys (MetaInputDeviceNative *device) 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 static void
@ -892,18 +913,20 @@ trigger_mousekeys_move (gpointer data)
{ {
/* This is the first move, Secdule at mk_init_delay */ /* This is the first move, Secdule at mk_init_delay */
device->move_mousekeys_timer = device->move_mousekeys_timer =
clutter_threads_add_timeout (device->mousekeys_init_delay, timeout_source_new (device->seat_impl,
trigger_mousekeys_move, device->mousekeys_init_delay,
device); trigger_mousekeys_move,
device);
} }
else else
{ {
/* More moves, reschedule at mk_interval */ /* More moves, reschedule at mk_interval */
device->move_mousekeys_timer = device->move_mousekeys_timer =
clutter_threads_add_timeout (100, /* msec between mousekey events */ timeout_source_new (device->seat_impl,
trigger_mousekeys_move, 100, /* msec between mousekey events */
device); trigger_mousekeys_move,
device);
} }
/* Pointer motion */ /* Pointer motion */
@ -964,7 +987,7 @@ stop_mousekeys_move (MetaInputDeviceNative *device)
device->mousekeys_first_motion_time = 0; device->mousekeys_first_motion_time = 0;
device->mousekeys_last_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 static void

View File

@ -85,12 +85,12 @@ struct _MetaInputDeviceNative
/* Keyboard a11y */ /* Keyboard a11y */
MetaKeyboardA11yFlags a11y_flags; MetaKeyboardA11yFlags a11y_flags;
GList *slow_keys_list; GList *slow_keys_list;
guint debounce_timer; GSource *debounce_timer;
uint16_t debounce_key; uint16_t debounce_key;
xkb_mod_mask_t stickykeys_depressed_mask; xkb_mod_mask_t stickykeys_depressed_mask;
xkb_mod_mask_t stickykeys_latched_mask; xkb_mod_mask_t stickykeys_latched_mask;
xkb_mod_mask_t stickykeys_locked_mask; xkb_mod_mask_t stickykeys_locked_mask;
guint toggle_slowkeys_timer; GSource *toggle_slowkeys_timer;
uint16_t shift_count; uint16_t shift_count;
uint32_t last_shift_time; uint32_t last_shift_time;
int mousekeys_btn; int mousekeys_btn;
@ -101,7 +101,7 @@ struct _MetaInputDeviceNative
guint mousekeys_accel_time; guint mousekeys_accel_time;
guint mousekeys_max_speed; guint mousekeys_max_speed;
double mousekeys_curve_factor; double mousekeys_curve_factor;
guint move_mousekeys_timer; GSource *move_mousekeys_timer;
uint16_t last_mousekeys_key; uint16_t last_mousekeys_key;
}; };

View File

@ -119,7 +119,11 @@ enum
static guint signals[N_SIGNALS] = { 0 }; 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); static void process_events (MetaSeatImpl *seat_impl);
void meta_seat_impl_constrain_pointer (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 y,
float *dx, float *dx,
float *dy); float *dy);
void meta_seat_impl_clear_repeat_timer (MetaSeatImpl *seat_impl); void meta_seat_impl_clear_repeat_source (MetaSeatImpl *seat_impl);
void void
meta_seat_impl_run_input_task (MetaSeatImpl *seat_impl, meta_seat_impl_run_input_task (MetaSeatImpl *seat_impl,
@ -238,11 +242,11 @@ meta_seat_impl_release_touch_state (MetaSeatImpl *seat_impl,
} }
void 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); g_clear_object (&seat_impl->repeat_device);
} }
} }
@ -258,20 +262,18 @@ static gboolean
keyboard_repeat (gpointer data) keyboard_repeat (gpointer data)
{ {
MetaSeatImpl *seat_impl = data; MetaSeatImpl *seat_impl = data;
GSource *source;
/* There might be events queued in libinput that could cancel the /* There might be events queued in libinput that could cancel the
repeat timer. */ repeat timer. */
dispatch_libinput (seat_impl); dispatch_libinput (seat_impl);
if (!seat_impl->repeat_timer) if (!seat_impl->repeat_source)
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
g_return_val_if_fail (seat_impl->repeat_device != NULL, 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, meta_seat_impl_notify_key (seat_impl,
seat_impl->repeat_device, seat_impl->repeat_device,
g_source_get_time (source), g_source_get_time (seat_impl->repeat_source),
seat_impl->repeat_key, seat_impl->repeat_key,
AUTOREPEAT_VALUE, AUTOREPEAT_VALUE,
FALSE); 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 void
meta_seat_impl_notify_key (MetaSeatImpl *seat_impl, meta_seat_impl_notify_key (MetaSeatImpl *seat_impl,
ClutterInputDevice *device, ClutterInputDevice *device,
@ -369,7 +430,7 @@ meta_seat_impl_notify_key (MetaSeatImpl *seat_impl,
MetaInputDeviceNative *keyboard_native; MetaInputDeviceNative *keyboard_native;
gboolean numlock_active; gboolean numlock_active;
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); meta_seat_impl_sync_leds (seat_impl);
numlock_active = numlock_active =
@ -388,7 +449,8 @@ meta_seat_impl_notify_key (MetaSeatImpl *seat_impl,
!xkb_keymap_key_repeats (xkb_state_get_keymap (seat_impl->xkb), !xkb_keymap_key_repeats (xkb_state_get_keymap (seat_impl->xkb),
keycode)) keycode))
{ {
meta_seat_impl_clear_repeat_timer (seat_impl); seat_impl->repeat_count = 0;
meta_seat_impl_clear_repeat_source (seat_impl);
return; return;
} }
@ -405,7 +467,7 @@ meta_seat_impl_notify_key (MetaSeatImpl *seat_impl,
{ {
uint32_t interval; 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); seat_impl->repeat_device = g_object_ref (device);
if (seat_impl->repeat_count == 1) if (seat_impl->repeat_count == 1)
@ -413,12 +475,11 @@ meta_seat_impl_notify_key (MetaSeatImpl *seat_impl,
else else
interval = seat_impl->repeat_interval; interval = seat_impl->repeat_interval;
seat_impl->repeat_timer = seat_impl->repeat_source = g_timeout_source_new (interval);
clutter_threads_add_timeout_full (CLUTTER_PRIORITY_EVENTS, g_source_set_priority (seat_impl->repeat_source, CLUTTER_PRIORITY_EVENTS);
interval, g_source_set_callback (seat_impl->repeat_source,
keyboard_repeat, keyboard_repeat, seat_impl, NULL);
seat_impl, g_source_attach (seat_impl->repeat_source, seat_impl->input_context);
NULL);
return; return;
} }
default: default:
@ -887,26 +948,13 @@ meta_seat_impl_notify_touch_event (MetaSeatImpl *seat_impl,
/* /*
* MetaEventSource for reading input devices * 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 static gboolean
meta_event_check (GSource *source) meta_event_check (GSource *source)
{ {
MetaEventSource *event_source = (MetaEventSource *) source; MetaEventSource *event_source = (MetaEventSource *) source;
gboolean retval; gboolean retval;
retval = ((event_source->event_poll_fd.revents & G_IO_IN) || retval = !!(event_source->event_poll_fd.revents & G_IO_IN);
clutter_events_pending ());
return retval; return retval;
} }
@ -1384,19 +1432,13 @@ meta_event_dispatch (GSource *g_source,
seat_impl = source->seat_impl; 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); dispatch_libinput (seat_impl);
queue_event:
return TRUE; return TRUE;
} }
static GSourceFuncs event_funcs = { static GSourceFuncs event_funcs = {
meta_event_prepare, NULL,
meta_event_check, meta_event_check,
meta_event_dispatch, meta_event_dispatch,
NULL NULL
@ -1423,7 +1465,7 @@ meta_event_source_new (MetaSeatImpl *seat_impl)
g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS); g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS);
g_source_add_poll (source, &event_source->event_poll_fd); g_source_add_poll (source, &event_source->event_poll_fd);
g_source_set_can_recurse (source, TRUE); g_source_set_can_recurse (source, TRUE);
g_source_attach (source, NULL); g_source_attach (source, seat_impl->input_context);
return event_source; return event_source;
} }
@ -1506,8 +1548,13 @@ update_touch_mode (MetaSeatImpl *seat_impl)
if (seat_impl->touch_mode != touch_mode) 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; 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);
} }
} }
@ -1564,8 +1611,8 @@ evdev_remove_device (MetaSeatImpl *seat_impl,
if (is_touchscreen || is_tablet_switch) if (is_touchscreen || is_tablet_switch)
update_touch_mode (seat_impl); update_touch_mode (seat_impl);
if (seat_impl->repeat_timer && seat_impl->repeat_device == device) if (seat_impl->repeat_source && seat_impl->repeat_device == device)
meta_seat_impl_clear_repeat_timer (seat_impl); meta_seat_impl_clear_repeat_source (seat_impl);
g_object_unref (device); g_object_unref (device);
} }
@ -2535,35 +2582,21 @@ meta_seat_impl_set_keyboard_numlock (MetaSeatImpl *seat_impl,
meta_keymap_native_update (seat_impl->keymap); meta_keymap_native_update (seat_impl->keymap);
} }
static void static gpointer
meta_seat_impl_constructed (GObject *object) input_thread (MetaSeatImpl *seat_impl)
{ {
MetaSeatImpl *seat_impl = META_SEAT_IMPL (object);
ClutterInputDevice *device;
MetaEventSource *source; MetaEventSource *source;
struct udev *udev; struct udev *udev;
struct xkb_keymap *xkb_keymap; struct xkb_keymap *xkb_keymap;
device = meta_input_device_native_new_virtual ( g_main_context_push_thread_default (seat_impl->input_context);
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;
udev = udev_new (); udev = udev_new ();
if (G_UNLIKELY (udev == NULL)) if (G_UNLIKELY (udev == NULL))
{ {
g_warning ("Failed to create udev object"); 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, seat_impl->libinput = libinput_udev_create_context (&libinput_interface,
@ -2571,7 +2604,8 @@ meta_seat_impl_constructed (GObject *object)
if (seat_impl->libinput == NULL) if (seat_impl->libinput == NULL)
{ {
g_critical ("Failed to create the libinput object."); 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) if (libinput_udev_assign_seat (seat_impl->libinput, seat_impl->seat_id) == -1)
@ -2579,7 +2613,8 @@ meta_seat_impl_constructed (GObject *object)
g_critical ("Failed to assign a seat to the libinput object."); g_critical ("Failed to assign a seat to the libinput object.");
libinput_unref (seat_impl->libinput); libinput_unref (seat_impl->libinput);
seat_impl->libinput = NULL; seat_impl->libinput = NULL;
return; seat_impl->input_thread_initialized = TRUE;
return NULL;
} }
udev_unref (udev); udev_unref (udev);
@ -2588,12 +2623,11 @@ meta_seat_impl_constructed (GObject *object)
g_signal_connect_object (seat_impl->input_settings, "kbd-a11y-changed", g_signal_connect_object (seat_impl->input_settings, "kbd-a11y-changed",
G_CALLBACK (kbd_a11y_changed_cb), seat_impl, 0); 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); source = meta_event_source_new (seat_impl);
seat_impl->event_source = source; seat_impl->event_source = source;
seat_impl->keymap = g_object_new (META_TYPE_KEYMAP_NATIVE, NULL); seat_impl->keymap = g_object_new (META_TYPE_KEYMAP_NATIVE, NULL);
xkb_keymap = meta_keymap_native_get_keyboard_map (seat_impl->keymap); xkb_keymap = meta_keymap_native_get_keyboard_map (seat_impl->keymap);
if (xkb_keymap) if (xkb_keymap)
@ -2615,6 +2649,71 @@ meta_seat_impl_constructed (GObject *object)
seat_impl->has_tablet_switch = has_tablet_switch (seat_impl); seat_impl->has_tablet_switch = has_tablet_switch (seat_impl);
update_touch_mode (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) if (G_OBJECT_CLASS (meta_seat_impl_parent_class)->constructed)
G_OBJECT_CLASS (meta_seat_impl_parent_class)->constructed (object); G_OBJECT_CLASS (meta_seat_impl_parent_class)->constructed (object);
} }
@ -2682,6 +2781,9 @@ meta_seat_impl_finalize (GObject *object)
gboolean numlock_active; gboolean numlock_active;
GSList *iter; 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)) for (iter = seat_impl->devices; iter; iter = g_slist_next (iter))
{ {
ClutterInputDevice *device = iter->data; ClutterInputDevice *device = iter->data;
@ -2707,7 +2809,7 @@ meta_seat_impl_finalize (GObject *object)
xkb_state_unref (seat_impl->xkb); 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); g_free (seat_impl->seat_id);
@ -2833,6 +2935,12 @@ meta_seat_impl_query_state (MetaSeatImpl *seat_impl,
return retval; return retval;
} }
static void
meta_seat_impl_initable_iface_init (GInitableIface *iface)
{
iface->init = meta_seat_impl_initable_init;
}
static void static void
meta_seat_impl_class_init (MetaSeatImplClass *klass) meta_seat_impl_class_init (MetaSeatImplClass *klass)
{ {
@ -2907,6 +3015,9 @@ meta_seat_impl_init (MetaSeatImpl *seat_impl)
seat_impl->repeat_delay = 250; /* ms */ seat_impl->repeat_delay = 250; /* ms */
seat_impl->repeat_interval = 33; /* 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 (); seat_impl->barrier_manager = meta_barrier_manager_native_new ();
} }
@ -3269,10 +3380,11 @@ MetaSeatImpl *
meta_seat_impl_new (MetaSeatNative *seat_native, meta_seat_impl_new (MetaSeatNative *seat_native,
const char *seat_id) const char *seat_id)
{ {
return g_object_new (META_TYPE_SEAT_IMPL, return g_initable_new (META_TYPE_SEAT_IMPL,
"seat", seat_native, NULL, NULL,
"seat-id", seat_id, "seat", seat_native,
NULL); "seat-id", seat_id,
NULL);
} }
void void
@ -3281,12 +3393,18 @@ meta_seat_impl_notify_kbd_a11y_flags_changed (MetaSeatImpl *seat_impl,
MetaKeyboardA11yFlags what_changed) MetaKeyboardA11yFlags what_changed)
{ {
MetaInputSettings *input_settings; MetaInputSettings *input_settings;
GValue values[] = { G_VALUE_INIT, G_VALUE_INIT };
input_settings = seat_impl->input_settings; input_settings = seat_impl->input_settings;
meta_input_settings_notify_kbd_a11y_change (input_settings, meta_input_settings_notify_kbd_a11y_change (input_settings,
new_flags, what_changed); new_flags, what_changed);
g_signal_emit (seat_impl, signals[KBD_A11Y_FLAGS_CHANGED], 0, g_value_init (&values[0], G_TYPE_UINT);
new_flags, what_changed); 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 void
@ -3294,14 +3412,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_latched_mods,
xkb_mod_mask_t new_locked_mods) xkb_mod_mask_t new_locked_mods)
{ {
g_signal_emit (seat_impl, signals[KBD_A11Y_MODS_STATE_CHANGED], 0, GValue values[] = { G_VALUE_INIT, G_VALUE_INIT };
new_latched_mods, new_locked_mods);
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 void
meta_seat_impl_notify_bell (MetaSeatImpl *seat_impl) 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 * MetaInputSettings *

View File

@ -54,7 +54,13 @@ struct _MetaSeatImpl
{ {
GObject parent_instance; GObject parent_instance;
GMainContext *main_context;
GMainContext *input_context; GMainContext *input_context;
GMainLoop *input_loop;
GThread *input_thread;
GMutex init_mutex;
GCond init_cond;
MetaSeatNative *seat_native; MetaSeatNative *seat_native;
char *seat_id; char *seat_id;
MetaEventSource *event_source; MetaEventSource *event_source;
@ -91,6 +97,7 @@ struct _MetaSeatImpl
gboolean has_touchscreen; gboolean has_touchscreen;
gboolean has_tablet_switch; gboolean has_tablet_switch;
gboolean touch_mode; gboolean touch_mode;
gboolean input_thread_initialized;
/* keyboard repeat */ /* keyboard repeat */
gboolean repeat; gboolean repeat;
@ -98,8 +105,8 @@ struct _MetaSeatImpl
uint32_t repeat_interval; uint32_t repeat_interval;
uint32_t repeat_key; uint32_t repeat_key;
uint32_t repeat_count; uint32_t repeat_count;
uint32_t repeat_timer;
ClutterInputDevice *repeat_device; ClutterInputDevice *repeat_device;
GSource *repeat_source;
float pointer_x; float pointer_x;
float pointer_y; float pointer_y;