summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiovanni Campagna <gcampagn@redhat.com>2013-09-06 16:56:55 +0200
committerGiovanni Campagna <gcampagn@redhat.com>2013-09-09 13:24:23 +0200
commitd882366d11bb430966d1b0d32b4ba1936ad68ec9 (patch)
tree687dc1c8510629445fcd9ae1a83f7cd51e47258d
parentcd1749a2a55b4a0d8ba016d00265686909b4bbd9 (diff)
downloadclutter-d882366d11bb430966d1b0d32b4ba1936ad68ec9.tar.gz
evdev: implement setting leds
When the leds are changed in the keyboard state, propagate the change to the actual devices. https://bugzilla.gnome.org/show_bug.cgi?id=706494
-rw-r--r--clutter/evdev/clutter-device-manager-evdev.c115
-rw-r--r--clutter/evdev/clutter-xkb-utils.c43
-rw-r--r--clutter/evdev/clutter-xkb-utils.h4
3 files changed, 85 insertions, 77 deletions
diff --git a/clutter/evdev/clutter-device-manager-evdev.c b/clutter/evdev/clutter-device-manager-evdev.c
index 5ca7ffbea..6b8bf4f69 100644
--- a/clutter/evdev/clutter-device-manager-evdev.c
+++ b/clutter/evdev/clutter-device-manager-evdev.c
@@ -84,6 +84,9 @@ struct _ClutterDeviceManagerEvdevPrivate
GArray *keys;
struct xkb_state *xkb; /* XKB state object */
+ xkb_led_index_t caps_lock_led;
+ xkb_led_index_t num_lock_led;
+ xkb_led_index_t scroll_lock_led;
uint32_t button_state;
};
@@ -190,6 +193,30 @@ remove_key (GArray *keys,
}
static void
+sync_leds (ClutterDeviceManagerEvdev *manager_evdev)
+{
+ ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
+ GSList *iter;
+ int caps_lock, num_lock, scroll_lock;
+
+ caps_lock = xkb_state_led_index_is_active (priv->xkb, priv->caps_lock_led);
+ num_lock = xkb_state_led_index_is_active (priv->xkb, priv->num_lock_led);
+ scroll_lock = xkb_state_led_index_is_active (priv->xkb, priv->scroll_lock_led);
+
+ for (iter = priv->event_sources; iter; iter = iter->next)
+ {
+ ClutterEventSource *source = iter->data;
+
+ if (libevdev_has_event_type (source->dev, EV_LED))
+ libevdev_kernel_set_led_values (source->dev,
+ LED_CAPSL, caps_lock == 1 ? LIBEVDEV_LED_ON : LIBEVDEV_LED_OFF,
+ LED_NUML, num_lock == 1 ? LIBEVDEV_LED_ON : LIBEVDEV_LED_OFF,
+ LED_SCROLLL, scroll_lock == 1 ? LIBEVDEV_LED_ON : LIBEVDEV_LED_OFF,
+ -1);
+ }
+}
+
+static void
notify_key_device (ClutterInputDevice *input_device,
guint32 time_,
guint32 key,
@@ -199,6 +226,7 @@ notify_key_device (ClutterInputDevice *input_device,
ClutterDeviceManagerEvdev *manager_evdev;
ClutterStage *stage;
ClutterEvent *event = NULL;
+ enum xkb_state_component changed_state;
/* We can drop the event on the floor if no stage has been
* associated with the device yet. */
@@ -208,34 +236,34 @@ notify_key_device (ClutterInputDevice *input_device,
manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (input_device->device_manager);
- /* if we have keyboard state, use it to generate the event */
- if (manager_evdev->priv->xkb)
+ event = _clutter_key_event_new_from_evdev (input_device,
+ manager_evdev->priv->core_keyboard,
+ stage,
+ manager_evdev->priv->xkb,
+ manager_evdev->priv->button_state,
+ time_, key, state);
+
+ /* We must be careful and not pass multiple releases to xkb, otherwise it gets
+ confused and locks the modifiers */
+ if (state != AUTOREPEAT_VALUE)
{
- event =
- _clutter_key_event_new_from_evdev (input_device,
- manager_evdev->priv->core_keyboard,
- stage,
- manager_evdev->priv->xkb,
- manager_evdev->priv->button_state,
- time_, key, state);
-
- /* We must be careful and not pass multiple releases to xkb, otherwise it gets
- confused and locks the modifiers */
- if (state != AUTOREPEAT_VALUE)
+ changed_state = xkb_state_update_key (manager_evdev->priv->xkb, event->key.hardware_keycode, state ? XKB_KEY_DOWN : XKB_KEY_UP);
+
+ if (update_keys)
{
- xkb_state_update_key (manager_evdev->priv->xkb, event->key.hardware_keycode, state ? XKB_KEY_DOWN : XKB_KEY_UP);
-
- if (update_keys)
- {
- if (state)
- add_key (manager_evdev->priv->keys, event->key.hardware_keycode);
- else
- remove_key (manager_evdev->priv->keys, event->key.hardware_keycode);
- }
+ if (state)
+ add_key (manager_evdev->priv->keys, event->key.hardware_keycode);
+ else
+ remove_key (manager_evdev->priv->keys, event->key.hardware_keycode);
}
-
- queue_event (event);
}
+ else
+ changed_state = 0;
+
+ queue_event (event);
+
+ if (update_keys && (changed_state & XKB_STATE_LEDS))
+ sync_leds (manager_evdev);
}
static void
@@ -649,7 +677,7 @@ clutter_event_source_new (ClutterInputDeviceEvdev *input_device)
if (open_callback)
{
error = NULL;
- fd = open_callback (node_path, O_RDONLY | O_NONBLOCK, open_callback_data, &error);
+ fd = open_callback (node_path, O_RDWR | O_NONBLOCK, open_callback_data, &error);
if (fd < 0)
{
@@ -660,7 +688,7 @@ clutter_event_source_new (ClutterInputDeviceEvdev *input_device)
}
else
{
- fd = open (node_path, O_RDONLY | O_NONBLOCK);
+ fd = open (node_path, O_RDWR | O_NONBLOCK);
if (fd < 0)
{
g_warning ("Could not open device %s: %s", node_path, strerror (errno));
@@ -1016,6 +1044,9 @@ clutter_device_manager_evdev_constructed (GObject *gobject)
ClutterDeviceManagerEvdev *manager_evdev;
ClutterDeviceManagerEvdevPrivate *priv;
ClutterInputDevice *device;
+ struct xkb_context *ctx;
+ struct xkb_keymap *keymap;
+ struct xkb_rule_names names;
manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (gobject);
priv = manager_evdev->priv;
@@ -1045,10 +1076,28 @@ clutter_device_manager_evdev_constructed (GObject *gobject)
priv->core_keyboard = device;
priv->keys = g_array_new (FALSE, FALSE, sizeof (guint32));
- priv->xkb = _clutter_xkb_state_new (NULL,
- option_xkb_layout,
- option_xkb_variant,
- option_xkb_options);
+
+ ctx = xkb_context_new(0);
+ g_assert (ctx);
+
+ names.rules = "evdev";
+ names.model = "pc105";
+ names.layout = option_xkb_layout;
+ names.variant = option_xkb_variant;
+ names.options = option_xkb_options;
+
+ keymap = xkb_keymap_new_from_names (ctx, &names, 0);
+ xkb_context_unref(ctx);
+ if (keymap)
+ {
+ priv->xkb = xkb_state_new (keymap);
+
+ priv->caps_lock_led = xkb_keymap_led_get_index (keymap, XKB_LED_NAME_CAPS);
+ priv->num_lock_led = xkb_keymap_led_get_index (keymap, XKB_LED_NAME_NUM);
+ priv->scroll_lock_led = xkb_keymap_led_get_index (keymap, XKB_LED_NAME_SCROLL);
+
+ xkb_keymap_unref (keymap);
+ }
priv->udev_client = g_udev_client_new (subsystems);
@@ -1450,8 +1499,14 @@ clutter_evdev_set_keyboard_map (ClutterDeviceManager *evdev,
xkb_state_unref (priv->xkb);
priv->xkb = xkb_state_new (keymap);
+ priv->caps_lock_led = xkb_keymap_led_get_index (keymap, XKB_LED_NAME_CAPS);
+ priv->num_lock_led = xkb_keymap_led_get_index (keymap, XKB_LED_NAME_NUM);
+ priv->scroll_lock_led = xkb_keymap_led_get_index (keymap, XKB_LED_NAME_SCROLL);
+
for (i = 0; i < priv->keys->len; i++)
xkb_state_update_key (priv->xkb, g_array_index (priv->keys, guint32, i), XKB_KEY_DOWN);
+
+ sync_leds (manager_evdev);
}
/**
diff --git a/clutter/evdev/clutter-xkb-utils.c b/clutter/evdev/clutter-xkb-utils.c
index eb84bf7b6..fd6e0f121 100644
--- a/clutter/evdev/clutter-xkb-utils.c
+++ b/clutter/evdev/clutter-xkb-utils.c
@@ -99,49 +99,6 @@ _clutter_key_event_new_from_evdev (ClutterInputDevice *device,
return event;
}
-/*
- * _clutter_xkb_state_new:
- *
- * Create a new xkbcommon keymap and state object.
- *
- * FIXME: We need a way to override the layout here, a fixed or runtime
- * detected layout is provided by the backend calling _clutter_xkb_state_new();
- */
-struct xkb_state *
-_clutter_xkb_state_new (const gchar *model,
- const gchar *layout,
- const gchar *variant,
- const gchar *options)
-{
- struct xkb_context *ctx;
- struct xkb_keymap *keymap;
- struct xkb_state *state;
- struct xkb_rule_names names;
-
- ctx = xkb_context_new(0);
- if (!ctx)
- return NULL;
-
- names.rules = "evdev";
- if (model)
- names.model = model;
- else
- names.model = "pc105";
- names.layout = layout;
- names.variant = variant;
- names.options = options;
-
- keymap = xkb_map_new_from_names(ctx, &names, 0);
- xkb_context_unref(ctx);
- if (!keymap)
- return NULL;
-
- state = xkb_state_new(keymap);
- xkb_map_unref(keymap);
-
- return state;
-}
-
void
_clutter_xkb_translate_state (ClutterEvent *event,
struct xkb_state *state,
diff --git a/clutter/evdev/clutter-xkb-utils.h b/clutter/evdev/clutter-xkb-utils.h
index ee3a66934..ae057dd6f 100644
--- a/clutter/evdev/clutter-xkb-utils.h
+++ b/clutter/evdev/clutter-xkb-utils.h
@@ -39,10 +39,6 @@ ClutterEvent * _clutter_key_event_new_from_evdev (ClutterInputDevice *device,
uint32_t _time,
uint32_t key,
uint32_t state);
-struct xkb_state * _clutter_xkb_state_new (const gchar *model,
- const gchar *layout,
- const gchar *variant,
- const gchar *options);
void _clutter_xkb_translate_state (ClutterEvent *event,
struct xkb_state *xkb_state,
uint32_t button_state);