input: Add core API to update the keymap

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.
This commit is contained in:
Rui Matos 2013-10-10 19:44:19 +02:00 committed by Kristian Høgsberg
parent a7af70436b
commit 65196bc0b9
2 changed files with 112 additions and 0 deletions

View File

@ -485,6 +485,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;
@ -1179,6 +1180,8 @@ void
weston_seat_release_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);

View File

@ -901,6 +901,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)
@ -912,6 +992,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
@ -961,6 +1046,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),
@ -1636,6 +1725,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)
{
@ -1808,6 +1915,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