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',