[clutter/clutter-1.16] evdev: implement setting leds



commit d882366d11bb430966d1b0d32b4ba1936ad68ec9
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Fri Sep 6 16:56:55 2013 +0200

    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

 clutter/evdev/clutter-device-manager-evdev.c |  115 +++++++++++++++++++-------
 clutter/evdev/clutter-xkb-utils.c            |   43 ----------
 clutter/evdev/clutter-xkb-utils.h            |    4 -
 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 5ca7ffb..6b8bf4f 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 eb84bf7..fd6e0f1 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 ee3a669..ae057dd 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);


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