mirror of
https://github.com/brl/mutter.git
synced 2025-02-08 17:44:09 +00:00
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
This commit is contained in:
parent
cd1749a2a5
commit
d882366d11
@ -84,6 +84,9 @@ struct _ClutterDeviceManagerEvdevPrivate
|
|||||||
|
|
||||||
GArray *keys;
|
GArray *keys;
|
||||||
struct xkb_state *xkb; /* XKB state object */
|
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;
|
uint32_t button_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -189,6 +192,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
|
static void
|
||||||
notify_key_device (ClutterInputDevice *input_device,
|
notify_key_device (ClutterInputDevice *input_device,
|
||||||
guint32 time_,
|
guint32 time_,
|
||||||
@ -199,6 +226,7 @@ notify_key_device (ClutterInputDevice *input_device,
|
|||||||
ClutterDeviceManagerEvdev *manager_evdev;
|
ClutterDeviceManagerEvdev *manager_evdev;
|
||||||
ClutterStage *stage;
|
ClutterStage *stage;
|
||||||
ClutterEvent *event = NULL;
|
ClutterEvent *event = NULL;
|
||||||
|
enum xkb_state_component changed_state;
|
||||||
|
|
||||||
/* We can drop the event on the floor if no stage has been
|
/* We can drop the event on the floor if no stage has been
|
||||||
* associated with the device yet. */
|
* 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);
|
manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (input_device->device_manager);
|
||||||
|
|
||||||
/* if we have keyboard state, use it to generate the event */
|
event = _clutter_key_event_new_from_evdev (input_device,
|
||||||
if (manager_evdev->priv->xkb)
|
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 =
|
changed_state = xkb_state_update_key (manager_evdev->priv->xkb, event->key.hardware_keycode, state ? XKB_KEY_DOWN : XKB_KEY_UP);
|
||||||
_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
|
if (update_keys)
|
||||||
confused and locks the modifiers */
|
|
||||||
if (state != AUTOREPEAT_VALUE)
|
|
||||||
{
|
{
|
||||||
xkb_state_update_key (manager_evdev->priv->xkb, event->key.hardware_keycode, state ? XKB_KEY_DOWN : XKB_KEY_UP);
|
if (state)
|
||||||
|
add_key (manager_evdev->priv->keys, event->key.hardware_keycode);
|
||||||
if (update_keys)
|
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
|
static void
|
||||||
@ -649,7 +677,7 @@ clutter_event_source_new (ClutterInputDeviceEvdev *input_device)
|
|||||||
if (open_callback)
|
if (open_callback)
|
||||||
{
|
{
|
||||||
error = NULL;
|
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)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
@ -660,7 +688,7 @@ clutter_event_source_new (ClutterInputDeviceEvdev *input_device)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fd = open (node_path, O_RDONLY | O_NONBLOCK);
|
fd = open (node_path, O_RDWR | O_NONBLOCK);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
g_warning ("Could not open device %s: %s", node_path, strerror (errno));
|
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;
|
ClutterDeviceManagerEvdev *manager_evdev;
|
||||||
ClutterDeviceManagerEvdevPrivate *priv;
|
ClutterDeviceManagerEvdevPrivate *priv;
|
||||||
ClutterInputDevice *device;
|
ClutterInputDevice *device;
|
||||||
|
struct xkb_context *ctx;
|
||||||
|
struct xkb_keymap *keymap;
|
||||||
|
struct xkb_rule_names names;
|
||||||
|
|
||||||
manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (gobject);
|
manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (gobject);
|
||||||
priv = manager_evdev->priv;
|
priv = manager_evdev->priv;
|
||||||
@ -1045,10 +1076,28 @@ clutter_device_manager_evdev_constructed (GObject *gobject)
|
|||||||
priv->core_keyboard = device;
|
priv->core_keyboard = device;
|
||||||
|
|
||||||
priv->keys = g_array_new (FALSE, FALSE, sizeof (guint32));
|
priv->keys = g_array_new (FALSE, FALSE, sizeof (guint32));
|
||||||
priv->xkb = _clutter_xkb_state_new (NULL,
|
|
||||||
option_xkb_layout,
|
ctx = xkb_context_new(0);
|
||||||
option_xkb_variant,
|
g_assert (ctx);
|
||||||
option_xkb_options);
|
|
||||||
|
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);
|
priv->udev_client = g_udev_client_new (subsystems);
|
||||||
|
|
||||||
@ -1450,8 +1499,14 @@ clutter_evdev_set_keyboard_map (ClutterDeviceManager *evdev,
|
|||||||
xkb_state_unref (priv->xkb);
|
xkb_state_unref (priv->xkb);
|
||||||
priv->xkb = xkb_state_new (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);
|
||||||
|
|
||||||
for (i = 0; i < priv->keys->len; i++)
|
for (i = 0; i < priv->keys->len; i++)
|
||||||
xkb_state_update_key (priv->xkb, g_array_index (priv->keys, guint32, i), XKB_KEY_DOWN);
|
xkb_state_update_key (priv->xkb, g_array_index (priv->keys, guint32, i), XKB_KEY_DOWN);
|
||||||
|
|
||||||
|
sync_leds (manager_evdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,49 +99,6 @@ _clutter_key_event_new_from_evdev (ClutterInputDevice *device,
|
|||||||
return event;
|
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
|
void
|
||||||
_clutter_xkb_translate_state (ClutterEvent *event,
|
_clutter_xkb_translate_state (ClutterEvent *event,
|
||||||
struct xkb_state *state,
|
struct xkb_state *state,
|
||||||
|
@ -39,10 +39,6 @@ ClutterEvent * _clutter_key_event_new_from_evdev (ClutterInputDevice *device,
|
|||||||
uint32_t _time,
|
uint32_t _time,
|
||||||
uint32_t key,
|
uint32_t key,
|
||||||
uint32_t state);
|
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,
|
void _clutter_xkb_translate_state (ClutterEvent *event,
|
||||||
struct xkb_state *xkb_state,
|
struct xkb_state *xkb_state,
|
||||||
uint32_t button_state);
|
uint32_t button_state);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user