This adds a function weston_keyboard_set_leds() which can be used
to change the state of the num lock and the caps lock leds.
Currently works only with compositor-x11 and evdev.
---

I think some protocol is needed for the wayland backend, to tell the parent
compositor to turn them on/off.

 src/compositor-x11.c | 34 ++++++++++++++++++++++++++++++++++
 src/compositor.h     |  3 +++
 src/input.c          | 41 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+)

diff --git a/src/compositor-x11.c b/src/compositor-x11.c
index b81dac0..2f983be 100644
--- a/src/compositor-x11.c
+++ b/src/compositor-x11.c
@@ -43,6 +43,8 @@
 
 #include <X11/Xlib.h>
 #include <X11/Xlib-xcb.h>
+#include <X11/XKBlib.h>
+
 
 #include <xkbcommon/xkbcommon.h>
 
@@ -281,6 +283,9 @@ x11_compositor_setup_xkb(struct x11_compositor *c)
                              0,
                              state_reply->group);
 
+       notify_modifiers(&c->core_seat,
+                        wl_display_next_serial(c->base.wl_display));
+
        free(state_reply);
 
        xcb_change_window_attributes(c->conn, c->screen->root,
@@ -306,6 +311,33 @@ update_xkb_keymap(struct x11_compositor *c)
 }
 #endif
 
+static void
+x11_compositor_led_update(struct weston_seat *seat, enum weston_led leds)
+{
+       struct x11_compositor *c = container_of(seat->compositor, struct 
x11_compositor, base);
+       unsigned int mask, mask_on, mod, i;
+
+       static const struct {
+               enum weston_led weston;
+               int x11;
+       } map[] = {
+               { LED_NUM_LOCK, XK_Num_Lock },
+               { LED_CAPS_LOCK, XK_Caps_Lock },
+               { LED_SCROLL_LOCK, XK_Scroll_Lock },
+       };
+
+       mask = 0;
+       mask_on = 0;
+       for (i = 0; i < ARRAY_LENGTH(map); i++) {
+               mod = XkbKeysymToModifiers(c->dpy, map[i].x11);
+               mask |= mod;
+               if (leds & map[i].weston)
+                       mask_on |= mod;
+       }
+
+       XkbLockModifiers(c->dpy, XkbUseCoreKbd, mask, mask_on);
+}
+
 static int
 x11_input_create(struct x11_compositor *c, int no_input)
 {
@@ -1582,6 +1614,8 @@ x11_compositor_create(struct wl_display *display,
                                     x11_compositor_handle_event, c);
        wl_event_source_check(c->xcb_source);
 
+       c->core_seat.led_update = x11_compositor_led_update;
+
        return &c->base;
 
 err_x11_input:
diff --git a/src/compositor.h b/src/compositor.h
index b6bf78d..676963b 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -385,6 +385,9 @@ weston_keyboard_start_grab(struct weston_keyboard *device,
                           struct weston_keyboard_grab *grab);
 void
 weston_keyboard_end_grab(struct weston_keyboard *keyboard);
+void
+weston_keyboard_set_leds(struct weston_keyboard *keyboard,
+                        enum weston_led leds, enum weston_led active);
 
 struct weston_touch *
 weston_touch_create(void);
diff --git a/src/input.c b/src/input.c
index f4944b6..8e7139e 100644
--- a/src/input.c
+++ b/src/input.c
@@ -994,6 +994,47 @@ notify_axis(struct weston_seat *seat, uint32_t time, 
uint32_t axis,
                                     value);
 }
 
+WL_EXPORT void
+weston_keyboard_set_leds(struct weston_keyboard *keyboard,
+                        enum weston_led leds, enum weston_led active)
+{
+       /* We don't want the leds to go out of sync with the actual state
+        * so if the backend has no way to change the leds don't try to
+        * change the state */
+       if (!keyboard->seat->led_update)
+               return;
+
+       uint32_t mods_depressed, mods_latched, mods_locked, group;
+       uint32_t serial;
+       int num, caps;
+       mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
+                                               XKB_STATE_DEPRESSED);
+       mods_latched = xkb_state_serialize_mods(keyboard->xkb_state.state,
+                                               XKB_STATE_LATCHED);
+       mods_locked = xkb_state_serialize_mods(keyboard->xkb_state.state,
+                                               XKB_STATE_LOCKED);
+       group = xkb_state_serialize_group(keyboard->xkb_state.state,
+                                      XKB_STATE_EFFECTIVE);
+
+       num = (1 << keyboard->xkb_info->mod2_mod);
+       caps = (1 << keyboard->xkb_info->caps_mod);
+       if (leds & LED_NUM_LOCK)
+               mods_locked = (active & LED_NUM_LOCK) ? mods_locked | num
+                                                     : mods_locked & ~num;
+       if (leds & LED_CAPS_LOCK)
+               mods_locked = (active & LED_CAPS_LOCK) ? mods_locked | caps
+                                                      : mods_locked & ~caps;
+       if (leds & LED_SCROLL_LOCK)
+               weston_log("Changing the LED_SCROLL_LOCK value is not 
supported.");
+
+       xkb_state_update_mask(keyboard->xkb_state.state, mods_depressed,
+                             mods_latched, mods_locked, 0, 0, group);
+
+       serial = wl_display_next_serial(
+                               keyboard->seat->compositor->wl_display);
+       notify_modifiers(keyboard->seat, serial);
+}
+
 #ifdef ENABLE_XKBCOMMON
 WL_EXPORT void
 notify_modifiers(struct weston_seat *seat, uint32_t serial)
-- 
1.8.5.1

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to