[PATCH v2 1/4] input: Add core API to update the keymap

Rui Matos tiagomatos at gmail.com
Thu Oct 10 19:44:19 CEST 2013


How and when to update the keymap is left to each backend.

The new keymap only becomes effective when no keys are pressed and we
keep latched and locked modifiers from the previous state.

---
v2:
 - defer updating the keymap until no keys are pressed;

 - keep latched and locked modifiers state;

 - send the new keymap also to the focus_resource_list clients - not
   sure how I missed this in testing before;

 - send the new modifiers state to all keyboard clients if any bit is
   set since a new keymap means that they have to reset their state so
   we need to tell them if we are keeping some

 src/compositor.h |   3 ++
 src/input.c      | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 112 insertions(+)

diff --git a/src/compositor.h b/src/compositor.h
index a19d966..a4fedc3 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -486,6 +486,7 @@ struct weston_seat {
 		struct xkb_state *state;
 		enum weston_led leds;
 	} xkb_state;
+	struct xkb_keymap *pending_keymap;
 
 	struct input_method *input_method;
 	char *seat_name;
@@ -1115,6 +1116,8 @@ void
 weston_seat_init_touch(struct weston_seat *seat);
 void
 weston_seat_repick(struct weston_seat *seat);
+void
+weston_seat_update_keymap(struct weston_seat *seat, struct xkb_keymap *keymap);
 
 void
 weston_seat_release(struct weston_seat *seat);
diff --git a/src/input.c b/src/input.c
index 1313b52..539aba3 100644
--- a/src/input.c
+++ b/src/input.c
@@ -889,6 +889,86 @@ update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
 
 	notify_modifiers(seat, serial);
 }
+
+static void
+send_keymap(struct wl_resource *resource, struct weston_xkb_info *xkb_info)
+{
+	wl_keyboard_send_keymap(resource,
+				WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
+				xkb_info->keymap_fd,
+				xkb_info->keymap_size);
+}
+
+static void
+send_modifiers(struct wl_resource *resource, uint32_t serial, struct weston_keyboard *keyboard)
+{
+	wl_keyboard_send_modifiers(resource, serial,
+				   keyboard->modifiers.mods_depressed,
+				   keyboard->modifiers.mods_latched,
+				   keyboard->modifiers.mods_locked,
+				   keyboard->modifiers.group);
+}
+
+static struct weston_xkb_info *
+weston_xkb_info_create(struct xkb_keymap *keymap);
+static void
+weston_xkb_info_destroy(struct weston_xkb_info *xkb_info);
+
+static void
+update_keymap(struct weston_seat *seat)
+{
+	struct wl_resource *resource;
+	struct weston_xkb_info *xkb_info;
+	struct xkb_state *state;
+	xkb_mod_mask_t latched_mods;
+	xkb_mod_mask_t locked_mods;
+
+	xkb_info = weston_xkb_info_create(seat->pending_keymap);
+
+	xkb_keymap_unref(seat->pending_keymap);
+	seat->pending_keymap = NULL;
+
+	if (!xkb_info) {
+		weston_log("failed to create XKB info\n");
+		return;
+	}
+
+	state = xkb_state_new(xkb_info->keymap);
+	if (!state) {
+		weston_log("failed to initialise XKB state\n");
+		weston_xkb_info_destroy(xkb_info);
+		return;
+	}
+
+	latched_mods = xkb_state_serialize_mods(seat->xkb_state.state, XKB_STATE_MODS_LATCHED);
+	locked_mods = xkb_state_serialize_mods(seat->xkb_state.state, XKB_STATE_MODS_LOCKED);
+	xkb_state_update_mask(state,
+			      0, /* depressed */
+			      latched_mods,
+			      locked_mods,
+			      0, 0, 0);
+
+	weston_xkb_info_destroy(seat->xkb_info);
+	seat->xkb_info = xkb_info;
+
+	xkb_state_unref(seat->xkb_state.state);
+	seat->xkb_state.state = state;
+
+	wl_resource_for_each(resource, &seat->keyboard->resource_list)
+		send_keymap(resource, xkb_info);
+	wl_resource_for_each(resource, &seat->keyboard->focus_resource_list)
+		send_keymap(resource, xkb_info);
+
+	notify_modifiers(seat, wl_display_next_serial(seat->compositor->wl_display));
+
+	if (!latched_mods && !locked_mods)
+		return;
+
+	wl_resource_for_each(resource, &seat->keyboard->resource_list)
+		send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), seat->keyboard);
+	wl_resource_for_each(resource, &seat->keyboard->focus_resource_list)
+		send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), seat->keyboard);
+}
 #else
 WL_EXPORT void
 notify_modifiers(struct weston_seat *seat, uint32_t serial)
@@ -900,6 +980,11 @@ update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
 		      enum wl_keyboard_key_state state)
 {
 }
+
+static void
+update_keymap(struct weston_seat *seat)
+{
+}
 #endif
 
 WL_EXPORT void
@@ -950,6 +1035,10 @@ notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
 
 	grab->interface->key(grab, time, key, state);
 
+	if (seat->pending_keymap &&
+	    keyboard->keys.size == 0)
+		update_keymap(seat);
+
 	if (update_state == STATE_UPDATE_AUTOMATIC) {
 		update_modifier_state(seat,
 				      wl_display_get_serial(compositor->wl_display),
@@ -1623,6 +1712,24 @@ weston_compositor_xkb_destroy(struct weston_compositor *ec)
 }
 #endif
 
+WL_EXPORT void
+weston_seat_update_keymap(struct weston_seat *seat, struct xkb_keymap *keymap)
+{
+	if (!seat->keyboard || !keymap)
+		return;
+
+#ifdef ENABLE_XKBCOMMON
+	if (!seat->compositor->use_xkbcommon)
+		return;
+
+	xkb_keymap_unref(seat->pending_keymap);
+	seat->pending_keymap = xkb_keymap_ref(keymap);
+
+	if (seat->keyboard->keys.size == 0)
+		update_keymap(seat);
+#endif
+}
+
 WL_EXPORT int
 weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
 {
@@ -1742,6 +1849,8 @@ weston_seat_release(struct weston_seat *seat)
 			xkb_state_unref(seat->xkb_state.state);
 		if (seat->xkb_info)
 			weston_xkb_info_destroy(seat->xkb_info);
+		if (seat->pending_keymap)
+			xkb_keymap_unref (seat->pending_keymap);
 	}
 #endif
 
-- 
1.8.3.1



More information about the wayland-devel mailing list