From 6de81b0513b825d5503f1a239dc8c6ae70510342 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Thu, 10 Jan 2019 16:13:20 +0100 Subject: [PATCH] evdev: Implement ClutterKeymap Just move the minimal bits to this ClutterKeymapEvdev object. Much of the functionality of a keymap is spread along ClutterSeatEvdev, ClutterDeviceManagerEvdev and ClutterVirtualInputDevice. Future refactors are due here. Also, ideally keymaps are per-seat objects (at least keyboard state is). We don't expose much info about seats altogether outside the evdev device manager implementation. We just poke the main seat at places, but eventually seats should be public. --- clutter/clutter/clutter-backend-private.h | 3 + clutter/clutter/clutter-backend.c | 13 ++ .../evdev/clutter-device-manager-evdev.c | 72 ++++------ .../evdev/clutter-device-manager-evdev.h | 4 +- clutter/clutter/evdev/clutter-keymap-evdev.c | 128 ++++++++++++++++++ clutter/clutter/evdev/clutter-keymap-evdev.h | 32 +++++ clutter/clutter/evdev/clutter-seat-evdev.c | 26 ++-- .../clutter-virtual-input-device-evdev.c | 7 +- clutter/clutter/meson.build | 2 + 9 files changed, 232 insertions(+), 55 deletions(-) create mode 100644 clutter/clutter/evdev/clutter-keymap-evdev.c create mode 100644 clutter/clutter/evdev/clutter-keymap-evdev.h diff --git a/clutter/clutter/clutter-backend-private.h b/clutter/clutter/clutter-backend-private.h index 631fb8d55..42d122890 100644 --- a/clutter/clutter/clutter-backend-private.h +++ b/clutter/clutter/clutter-backend-private.h @@ -24,6 +24,7 @@ #include #include +#include #include #include "clutter-event-translator.h" @@ -60,6 +61,8 @@ struct _ClutterBackend GList *event_translators; ClutterInputMethod *input_method; + + ClutterKeymap *keymap; }; struct _ClutterBackendClass diff --git a/clutter/clutter/clutter-backend.c b/clutter/clutter/clutter-backend.c index 1f80cbf21..7f3d182c2 100644 --- a/clutter/clutter/clutter-backend.c +++ b/clutter/clutter/clutter-backend.c @@ -577,6 +577,18 @@ clutter_backend_real_get_device_manager (ClutterBackend *backend) return backend->device_manager; } +static ClutterKeymap * +clutter_backend_real_get_keymap (ClutterBackend *backend) +{ + if (G_UNLIKELY (backend->keymap == NULL)) + { + g_critical ("No keymap available, expect broken keyboard input"); + return NULL; + } + + return backend->keymap; +} + static gboolean clutter_backend_real_translate_event (ClutterBackend *backend, gpointer native, @@ -675,6 +687,7 @@ clutter_backend_class_init (ClutterBackendClass *klass) klass->translate_event = clutter_backend_real_translate_event; klass->create_context = clutter_backend_real_create_context; klass->get_features = clutter_backend_real_get_features; + klass->get_keymap = clutter_backend_real_get_keymap; } static void diff --git a/clutter/clutter/evdev/clutter-device-manager-evdev.c b/clutter/clutter/evdev/clutter-device-manager-evdev.c index ff7202186..dc14bfc20 100644 --- a/clutter/clutter/evdev/clutter-device-manager-evdev.c +++ b/clutter/clutter/evdev/clutter-device-manager-evdev.c @@ -44,6 +44,7 @@ #include "clutter-device-manager-private.h" #include "clutter-event-private.h" #include "clutter-input-device-evdev.h" +#include "clutter-keymap-evdev.h" #include "clutter-seat-evdev.h" #include "clutter-virtual-input-device-evdev.h" #include "clutter-main.h" @@ -91,7 +92,6 @@ struct _ClutterDeviceManagerEvdevPrivate GSList *seats; ClutterSeatEvdev *main_seat; - struct xkb_keymap *keymap; ClutterPointerConstrainCallback constrain_callback; gpointer constrain_data; @@ -147,10 +147,6 @@ static const char *device_type_str[] = { * appear and disappear from the system. */ -static const char *option_xkb_layout = "us"; -static const char *option_xkb_variant = ""; -static const char *option_xkb_options = ""; - static void clutter_device_manager_evdev_copy_event_data (ClutterEventExtender *event_extender, const ClutterEvent *src, @@ -1933,8 +1929,6 @@ clutter_device_manager_evdev_constructed (GObject *gobject) ClutterDeviceManagerEvdevPrivate *priv; ClutterEventSource *source; struct udev *udev; - struct xkb_context *ctx; - struct xkb_rule_names names; udev = udev_new (); if (G_UNLIKELY (udev == NULL)) @@ -1966,17 +1960,6 @@ clutter_device_manager_evdev_constructed (GObject *gobject) udev_unref (udev); - names.rules = "evdev"; - names.model = "pc105"; - names.layout = option_xkb_layout; - names.variant = option_xkb_variant; - names.options = option_xkb_options; - - ctx = xkb_context_new (0); - g_assert (ctx); - priv->keymap = xkb_keymap_new_from_names (ctx, &names, 0); - xkb_context_unref (ctx); - priv->main_seat = clutter_seat_evdev_new (manager_evdev); priv->seats = g_slist_append (priv->seats, priv->main_seat); @@ -2030,9 +2013,6 @@ clutter_device_manager_evdev_finalize (GObject *object) g_slist_free_full (priv->seats, (GDestroyNotify) clutter_seat_evdev_free); g_slist_free (priv->devices); - if (priv->keymap) - xkb_keymap_unref (priv->keymap); - if (priv->event_source != NULL) clutter_event_source_free (priv->event_source); @@ -2159,6 +2139,7 @@ _clutter_events_evdev_init (ClutterBackend *backend) backend->device_manager = g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_EVDEV, "backend", backend, NULL); + backend->keymap = g_object_new (CLUTTER_TYPE_KEYMAP_EVDEV, NULL); } void @@ -2218,14 +2199,6 @@ _clutter_device_manager_evdev_release_device_id (ClutterDeviceManagerEvdev *mana compare_ids); } -struct xkb_keymap * -_clutter_device_manager_evdev_get_keymap (ClutterDeviceManagerEvdev *manager_evdev) -{ - ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv; - - return priv->keymap; -} - ClutterStage * _clutter_device_manager_evdev_get_stage (ClutterDeviceManagerEvdev *manager_evdev) { @@ -2288,6 +2261,11 @@ clutter_evdev_update_xkb_state (ClutterDeviceManagerEvdev *manager_evdev) ClutterSeatEvdev *seat; xkb_mod_mask_t latched_mods; xkb_mod_mask_t locked_mods; + struct xkb_keymap *xkb_keymap; + ClutterKeymap *keymap; + + keymap = clutter_backend_get_keymap (clutter_get_default_backend ()); + xkb_keymap = clutter_keymap_evdev_get_keyboard_map (CLUTTER_KEYMAP_EVDEV (keymap)); priv = manager_evdev->priv; @@ -2300,7 +2278,7 @@ clutter_evdev_update_xkb_state (ClutterDeviceManagerEvdev *manager_evdev) locked_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_LOCKED); xkb_state_unref (seat->xkb); - seat->xkb = xkb_state_new (priv->keymap); + seat->xkb = xkb_state_new (xkb_keymap); xkb_state_update_mask (seat->xkb, 0, /* depressed */ @@ -2308,9 +2286,9 @@ clutter_evdev_update_xkb_state (ClutterDeviceManagerEvdev *manager_evdev) locked_mods, 0, 0, seat->layout_idx); - seat->caps_lock_led = xkb_keymap_led_get_index (priv->keymap, XKB_LED_NAME_CAPS); - seat->num_lock_led = xkb_keymap_led_get_index (priv->keymap, XKB_LED_NAME_NUM); - seat->scroll_lock_led = xkb_keymap_led_get_index (priv->keymap, XKB_LED_NAME_SCROLL); + seat->caps_lock_led = xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_CAPS); + seat->num_lock_led = xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_NUM); + seat->scroll_lock_led = xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_SCROLL); clutter_seat_evdev_sync_leds (seat); } @@ -2395,20 +2373,18 @@ clutter_evdev_set_device_callbacks (ClutterOpenDeviceCallback open_callback, */ void clutter_evdev_set_keyboard_map (ClutterDeviceManager *evdev, - struct xkb_keymap *keymap) + struct xkb_keymap *xkb_keymap) { ClutterDeviceManagerEvdev *manager_evdev; - ClutterDeviceManagerEvdevPrivate *priv; + ClutterKeymap *keymap; g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev)); + keymap = clutter_backend_get_keymap (clutter_get_default_backend ()); + clutter_keymap_evdev_set_keyboard_map (CLUTTER_KEYMAP_EVDEV (keymap), + xkb_keymap); + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev); - priv = manager_evdev->priv; - - if (priv->keymap) - xkb_keymap_unref (priv->keymap); - - priv->keymap = xkb_keymap_ref (keymap); clutter_evdev_update_xkb_state (manager_evdev); } @@ -2503,12 +2479,18 @@ clutter_evdev_set_keyboard_numlock (ClutterDeviceManager *evdev, ClutterDeviceManagerEvdevPrivate *priv; GSList *iter; xkb_mod_mask_t numlock; + struct xkb_keymap *xkb_keymap; + ClutterKeymap *keymap; g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev)); manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev); priv = manager_evdev->priv; - numlock = (1 << xkb_keymap_mod_get_index(priv->keymap, "Mod2")); + + keymap = clutter_backend_get_keymap (clutter_get_default_backend ()); + xkb_keymap = clutter_keymap_evdev_get_keyboard_map (CLUTTER_KEYMAP_EVDEV (keymap)); + + numlock = (1 << xkb_keymap_mod_get_index (xkb_keymap, "Mod2")); for (iter = priv->seats; iter; iter = iter->next) { @@ -2759,3 +2741,9 @@ clutter_evdev_set_seat_id (const gchar *seat_id) g_free (evdev_seat_id); evdev_seat_id = g_strdup (seat_id); } + +struct xkb_state * +_clutter_device_manager_evdev_get_xkb_state (ClutterDeviceManagerEvdev *manager_evdev) +{ + return manager_evdev->priv->main_seat->xkb; +} diff --git a/clutter/clutter/evdev/clutter-device-manager-evdev.h b/clutter/clutter/evdev/clutter-device-manager-evdev.h index 2b87a444a..092895ed7 100644 --- a/clutter/clutter/evdev/clutter-device-manager-evdev.h +++ b/clutter/clutter/evdev/clutter-device-manager-evdev.h @@ -64,8 +64,6 @@ gint _clutter_device_manager_evdev_acquire_device_id (ClutterDeviceManagerEvdev void _clutter_device_manager_evdev_release_device_id (ClutterDeviceManagerEvdev *manager_evdev, ClutterInputDevice *device); -struct xkb_keymap * _clutter_device_manager_evdev_get_keymap (ClutterDeviceManagerEvdev *manager_evdev); - ClutterStage * _clutter_device_manager_evdev_get_stage (ClutterDeviceManagerEvdev *manager_evdev); void _clutter_device_manager_evdev_constrain_pointer (ClutterDeviceManagerEvdev *manager_evdev, @@ -85,6 +83,8 @@ void _clutter_device_manager_evdev_filter_relative_motion (ClutterDeviceManagerE void _clutter_device_manager_evdev_dispatch (ClutterDeviceManagerEvdev *manager_evdev); +struct xkb_state * _clutter_device_manager_evdev_get_xkb_state (ClutterDeviceManagerEvdev *manager_evdev); + static inline guint64 us (guint64 us) { diff --git a/clutter/clutter/evdev/clutter-keymap-evdev.c b/clutter/clutter/evdev/clutter-keymap-evdev.c new file mode 100644 index 000000000..7f67bf2a3 --- /dev/null +++ b/clutter/clutter/evdev/clutter-keymap-evdev.c @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2018 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Author: Carlos Garnacho + */ + +#include "clutter-build-config.h" + +#include "clutter-device-manager-evdev.h" +#include "clutter-keymap-evdev.h" + +static const char *option_xkb_layout = "us"; +static const char *option_xkb_variant = ""; +static const char *option_xkb_options = ""; + +typedef struct _ClutterKeymapEvdev ClutterKeymapEvdev; + +struct _ClutterKeymapEvdev +{ + ClutterKeymap parent_instance; + + struct xkb_keymap *keymap; +}; + +G_DEFINE_TYPE (ClutterKeymapEvdev, clutter_keymap_evdev, + CLUTTER_TYPE_KEYMAP) + +static void +clutter_keymap_evdev_finalize (GObject *object) +{ + ClutterKeymapEvdev *keymap = CLUTTER_KEYMAP_EVDEV (object); + + xkb_keymap_unref (keymap->keymap); + + G_OBJECT_CLASS (clutter_keymap_evdev_parent_class)->finalize (object); +} + +static gboolean +clutter_keymap_evdev_get_num_lock_state (ClutterKeymap *keymap) +{ + ClutterDeviceManagerEvdev *device_manager; + struct xkb_state *xkb_state; + + device_manager = + CLUTTER_DEVICE_MANAGER_EVDEV (clutter_device_manager_get_default ()); + xkb_state = _clutter_device_manager_evdev_get_xkb_state (device_manager); + + return xkb_state_mod_name_is_active (xkb_state, + XKB_MOD_NAME_NUM, + XKB_STATE_MODS_LATCHED || + XKB_STATE_MODS_LOCKED); +} + +static gboolean +clutter_keymap_evdev_get_caps_lock_state (ClutterKeymap *keymap) +{ + ClutterDeviceManagerEvdev *device_manager; + struct xkb_state *xkb_state; + + device_manager = + CLUTTER_DEVICE_MANAGER_EVDEV (clutter_device_manager_get_default ()); + xkb_state = _clutter_device_manager_evdev_get_xkb_state (device_manager); + + return xkb_state_mod_name_is_active (xkb_state, + XKB_MOD_NAME_CAPS, + XKB_STATE_MODS_LATCHED || + XKB_STATE_MODS_LOCKED); +} + +static void +clutter_keymap_evdev_class_init (ClutterKeymapEvdevClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + ClutterKeymapClass *keymap_class = CLUTTER_KEYMAP_CLASS (klass); + + object_class->finalize = clutter_keymap_evdev_finalize; + + keymap_class->get_num_lock_state = clutter_keymap_evdev_get_num_lock_state; + keymap_class->get_caps_lock_state = clutter_keymap_evdev_get_caps_lock_state; +} + +static void +clutter_keymap_evdev_init (ClutterKeymapEvdev *keymap) +{ + struct xkb_context *ctx; + struct xkb_rule_names names; + + names.rules = "evdev"; + names.model = "pc105"; + names.layout = option_xkb_layout; + names.variant = option_xkb_variant; + names.options = option_xkb_options; + + ctx = xkb_context_new (0); + g_assert (ctx); + keymap->keymap = xkb_keymap_new_from_names (ctx, &names, 0); + xkb_context_unref (ctx); +} + +void +clutter_keymap_evdev_set_keyboard_map (ClutterKeymapEvdev *keymap, + struct xkb_keymap *xkb_keymap) +{ + if (keymap->keymap) + xkb_keymap_unref (keymap->keymap); + keymap->keymap = xkb_keymap_ref (xkb_keymap); +} + +struct xkb_keymap * +clutter_keymap_evdev_get_keyboard_map (ClutterKeymapEvdev *keymap) +{ + return keymap->keymap; +} diff --git a/clutter/clutter/evdev/clutter-keymap-evdev.h b/clutter/clutter/evdev/clutter-keymap-evdev.h new file mode 100644 index 000000000..f3424b775 --- /dev/null +++ b/clutter/clutter/evdev/clutter-keymap-evdev.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2018 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Author: Carlos Garnacho + */ + +#include "clutter-xkb-utils.h" +#include "clutter-keymap.h" + +#define CLUTTER_TYPE_KEYMAP_EVDEV (clutter_keymap_evdev_get_type ()) +G_DECLARE_FINAL_TYPE (ClutterKeymapEvdev, clutter_keymap_evdev, + CLUTTER, KEYMAP_EVDEV, + ClutterKeymap) + +void clutter_keymap_evdev_set_keyboard_map (ClutterKeymapEvdev *keymap, + struct xkb_keymap *xkb_keymap); +struct xkb_keymap * clutter_keymap_evdev_get_keyboard_map (ClutterKeymapEvdev *keymap); diff --git a/clutter/clutter/evdev/clutter-seat-evdev.c b/clutter/clutter/evdev/clutter-seat-evdev.c index 329a6d6fd..9e8e3ffb1 100644 --- a/clutter/clutter/evdev/clutter-seat-evdev.c +++ b/clutter/clutter/evdev/clutter-seat-evdev.c @@ -34,6 +34,7 @@ #include "clutter-event-private.h" #include "clutter-input-device-evdev.h" #include "clutter-input-device-tool-evdev.h" +#include "clutter-keymap-evdev.h" #include "clutter-main.h" /* Try to keep the pointer inside the stage. Hopefully no one is using @@ -152,7 +153,8 @@ clutter_seat_evdev_new (ClutterDeviceManagerEvdev *manager_evdev) ClutterSeatEvdev *seat; ClutterInputDevice *device; ClutterStage *stage; - struct xkb_keymap *keymap; + ClutterKeymap *keymap; + struct xkb_keymap *xkb_keymap; seat = g_new0 (ClutterSeatEvdev, 1); if (!seat) @@ -183,17 +185,19 @@ clutter_seat_evdev_new (ClutterDeviceManagerEvdev *manager_evdev) seat->repeat_delay = 250; /* ms */ seat->repeat_interval = 33; /* ms */ - keymap = _clutter_device_manager_evdev_get_keymap (manager_evdev); - if (keymap) + keymap = clutter_backend_get_keymap (clutter_get_default_backend ()); + xkb_keymap = clutter_keymap_evdev_get_keyboard_map (CLUTTER_KEYMAP_EVDEV (keymap)); + + if (xkb_keymap) { - seat->xkb = xkb_state_new (keymap); + seat->xkb = xkb_state_new (xkb_keymap); seat->caps_lock_led = - xkb_keymap_led_get_index (keymap, XKB_LED_NAME_CAPS); + xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_CAPS); seat->num_lock_led = - xkb_keymap_led_get_index (keymap, XKB_LED_NAME_NUM); + xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_NUM); seat->scroll_lock_led = - xkb_keymap_led_get_index (keymap, XKB_LED_NAME_SCROLL); + xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_SCROLL); } return seat; @@ -316,7 +320,13 @@ clutter_seat_evdev_notify_key (ClutterSeatEvdev *seat, queue_event (event); if (update_keys && (changed_state & XKB_STATE_LEDS)) - clutter_seat_evdev_sync_leds (seat); + { + ClutterBackend *backend; + + backend = clutter_get_default_backend (); + g_signal_emit_by_name (clutter_backend_get_keymap (backend), "state-changed"); + clutter_seat_evdev_sync_leds (seat); + } if (state == 0 || /* key release */ !seat->repeat || diff --git a/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c b/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c index d1980f0ad..c365810ed 100644 --- a/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c +++ b/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c @@ -29,6 +29,7 @@ #include "clutter-private.h" #include "clutter-virtual-input-device.h" #include "evdev/clutter-input-device-evdev.h" +#include "evdev/clutter-keymap-evdev.h" #include "evdev/clutter-seat-evdev.h" #include "evdev/clutter-virtual-input-device-evdev.h" @@ -286,14 +287,14 @@ pick_keycode_for_keyval_in_current_group (ClutterVirtualInputDevice *virtual_dev { ClutterVirtualInputDeviceEvdev *virtual_evdev = CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device); - ClutterDeviceManager *manager; + ClutterKeymap *keymap; struct xkb_keymap *xkb_keymap; struct xkb_state *state; guint keycode, layout; xkb_keycode_t min_keycode, max_keycode; - manager = clutter_virtual_input_device_get_manager (virtual_device); - xkb_keymap = _clutter_device_manager_evdev_get_keymap (CLUTTER_DEVICE_MANAGER_EVDEV (manager)); + keymap = clutter_backend_get_keymap (clutter_get_default_backend ()); + xkb_keymap = clutter_keymap_evdev_get_keyboard_map (CLUTTER_KEYMAP_EVDEV (keymap)); state = virtual_evdev->seat->xkb; layout = xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE); diff --git a/clutter/clutter/meson.build b/clutter/clutter/meson.build index 56cc03d98..d8387bfde 100644 --- a/clutter/clutter/meson.build +++ b/clutter/clutter/meson.build @@ -358,6 +358,7 @@ if have_native_backend 'evdev/clutter-event-evdev.c', 'evdev/clutter-input-device-evdev.c', 'evdev/clutter-input-device-tool-evdev.c', + 'evdev/clutter-keymap-evdev.c', 'evdev/clutter-seat-evdev.c', 'evdev/clutter-virtual-input-device-evdev.c', 'evdev/clutter-xkb-utils.c', @@ -369,6 +370,7 @@ if have_native_backend 'evdev/clutter-device-manager-evdev.h', 'evdev/clutter-input-device-evdev.h', 'evdev/clutter-input-device-tool-evdev.h', + 'evdev/clutter-keymap-evdev.h', 'evdev/clutter-seat-evdev.h', 'evdev/clutter-virtual-input-device-evdev.h', 'evdev/clutter-xkb-utils.h',