wayland-keyboard: Make sure we send an updated modifiers event

Any given clutter event carries the modifier state as it was before it
occured but, for the wayland modifiers event, we want the state
including the current event.

To fix this, we'll keep our xkb_state instance around instead of the
serialized mods.

https://bugzilla.gnome.org/show_bug.cgi?id=722847
This commit is contained in:
Rui Matos 2014-03-06 14:41:45 +01:00
parent ae8f21a3dc
commit 5cc6becb63
2 changed files with 26 additions and 49 deletions

View File

@ -138,10 +138,12 @@ meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
return; return;
} }
if (xkb_info->keymap)
xkb_keymap_unref (xkb_info->keymap); xkb_keymap_unref (xkb_info->keymap);
xkb_info->keymap = keymap; xkb_info->keymap = keymap;
xkb_state_unref (xkb_info->state);
xkb_info->state = xkb_state_new (keymap);
keymap_str = xkb_map_get_as_string (xkb_info->keymap); keymap_str = xkb_map_get_as_string (xkb_info->keymap);
if (keymap_str == NULL) if (keymap_str == NULL)
{ {
@ -316,8 +318,8 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
static void static void
meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info) meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
{ {
if (xkb_info->keymap) xkb_keymap_unref (xkb_info->keymap);
xkb_map_unref (xkb_info->keymap); xkb_state_unref (xkb_info->state);
if (xkb_info->keymap_area) if (xkb_info->keymap_area)
munmap (xkb_info->keymap_area, xkb_info->keymap_size); munmap (xkb_info->keymap_area, xkb_info->keymap_size);
@ -325,44 +327,27 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
close (xkb_info->keymap_fd); close (xkb_info->keymap_fd);
} }
static gboolean
state_equal (MetaWaylandXkbState *one,
MetaWaylandXkbState *two)
{
return one->mods_depressed == two->mods_depressed &&
one->mods_latched == two->mods_latched &&
one->mods_locked == two->mods_locked &&
one->group == two->group;
}
static void static void
set_modifiers (MetaWaylandKeyboard *keyboard, set_modifiers (MetaWaylandKeyboard *keyboard,
guint32 serial, guint32 serial,
ClutterEvent *event) const ClutterKeyEvent *event)
{ {
MetaWaylandKeyboardGrab *grab = keyboard->grab; MetaWaylandKeyboardGrab *grab = keyboard->grab;
MetaWaylandXkbState new_state; struct xkb_state *state = keyboard->xkb_info.state;
guint effective_state; enum xkb_state_component changed_state;
clutter_event_get_state_full (event, changed_state = xkb_state_update_key (state,
NULL, event->hardware_keycode,
&new_state.mods_depressed, event->type == CLUTTER_KEY_PRESS ? XKB_KEY_DOWN : XKB_KEY_UP);
&new_state.mods_latched, if (changed_state == 0)
&new_state.mods_locked,
&effective_state);
new_state.group = (effective_state >> 13) & 0x3;
if (state_equal (&keyboard->modifier_state, &new_state))
return; return;
keyboard->modifier_state = new_state;
grab->interface->modifiers (grab, grab->interface->modifiers (grab,
serial, serial,
new_state.mods_depressed, xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
new_state.mods_latched, xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
new_state.mods_locked, xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
new_state.group); xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
} }
static void static void
@ -432,7 +417,7 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
serial = wl_display_next_serial (keyboard->display); serial = wl_display_next_serial (keyboard->display);
set_modifiers (keyboard, serial, (ClutterEvent*)event); set_modifiers (keyboard, serial, event);
handled = keyboard->grab->interface->key (keyboard->grab, handled = keyboard->grab->interface->key (keyboard->grab,
event->time, event->time,
@ -484,13 +469,14 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
{ {
struct wl_client *client = wl_resource_get_client (keyboard->focus_resource); struct wl_client *client = wl_resource_get_client (keyboard->focus_resource);
struct wl_display *display = wl_client_get_display (client); struct wl_display *display = wl_client_get_display (client);
struct xkb_state *state = keyboard->xkb_info.state;
uint32_t serial = wl_display_next_serial (display); uint32_t serial = wl_display_next_serial (display);
wl_keyboard_send_modifiers (keyboard->focus_resource, serial, wl_keyboard_send_modifiers (keyboard->focus_resource, serial,
keyboard->modifier_state.mods_depressed, xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
keyboard->modifier_state.mods_latched, xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
keyboard->modifier_state.mods_locked, xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
keyboard->modifier_state.group); xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource, wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource,
&keyboard->keys); &keyboard->keys);

View File

@ -69,19 +69,12 @@ struct _MetaWaylandKeyboardGrab
typedef struct typedef struct
{ {
struct xkb_keymap *keymap; struct xkb_keymap *keymap;
struct xkb_state *state;
int keymap_fd; int keymap_fd;
size_t keymap_size; size_t keymap_size;
char *keymap_area; char *keymap_area;
} MetaWaylandXkbInfo; } MetaWaylandXkbInfo;
typedef struct
{
uint32_t mods_depressed;
uint32_t mods_latched;
uint32_t mods_locked;
uint32_t group;
} MetaWaylandXkbState;
struct _MetaWaylandKeyboard struct _MetaWaylandKeyboard
{ {
struct wl_list resource_list; struct wl_list resource_list;
@ -100,8 +93,6 @@ struct _MetaWaylandKeyboard
struct wl_array keys; struct wl_array keys;
MetaWaylandXkbState modifier_state;
struct wl_display *display; struct wl_display *display;
struct xkb_context *xkb_context; struct xkb_context *xkb_context;