[PATCH weston 2/3] compositor: add a way to change the keyboard leds

Giulio Camuffo giuliocamuffo at gmail.com
Sat Dec 14 10:05:39 PST 2013


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



More information about the wayland-devel mailing list