wayland: Update keyboard state unconditionally

In particular we need to know about all key events to keep the xkb
state reliable even if the event is then consumed by a global shortcut
or grab and never reaches any wayland client.

We also need to keep track of all pressed keys at all times so that we
can send an updated set or pressed keys to the focused client when a
grab ends.

https://bugzilla.gnome.org/show_bug.cgi?id=722847
This commit is contained in:
Rui Matos 2014-03-18 18:00:48 +01:00
parent 3502cfba34
commit b3364cad3e
5 changed files with 72 additions and 43 deletions

View File

@ -327,29 +327,6 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
close (xkb_info->keymap_fd);
}
static void
set_modifiers (MetaWaylandKeyboard *keyboard,
guint32 serial,
const ClutterKeyEvent *event)
{
MetaWaylandKeyboardGrab *grab = keyboard->grab;
struct xkb_state *state = keyboard->xkb_info.state;
enum xkb_state_component changed_state;
changed_state = xkb_state_update_key (state,
event->hardware_keycode,
event->type == CLUTTER_KEY_PRESS ? XKB_KEY_DOWN : XKB_KEY_UP);
if (changed_state == 0)
return;
grab->interface->modifiers (grab,
serial,
xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
}
static void
update_pressed_keys (MetaWaylandKeyboard *keyboard,
uint32_t evdev_code,
@ -397,12 +374,36 @@ evdev_code (const ClutterKeyEvent *event)
return event->hardware_keycode - 8;
}
void
meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard,
const ClutterKeyEvent *event)
{
MetaWaylandKeyboardGrab *grab = keyboard->grab;
gboolean is_press = event->type == CLUTTER_KEY_PRESS;
struct xkb_state *state = keyboard->xkb_info.state;
enum xkb_state_component changed_state;
update_pressed_keys (keyboard, evdev_code (event), is_press);
changed_state = xkb_state_update_key (state,
event->hardware_keycode,
is_press ? XKB_KEY_DOWN : XKB_KEY_UP);
if (changed_state == 0)
return;
grab->interface->modifiers (grab,
wl_display_next_serial (keyboard->display),
xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
}
gboolean
meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
const ClutterKeyEvent *event)
{
gboolean is_press = event->type == CLUTTER_KEY_PRESS;
uint32_t serial;
gboolean handled;
/* Synthetic key events are for autorepeat. Ignore those, as
@ -414,12 +415,6 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
is_press ? "press" : "release",
event->hardware_keycode);
update_pressed_keys (keyboard, evdev_code, is_press);
serial = wl_display_next_serial (keyboard->display);
set_modifiers (keyboard, serial, event);
handled = keyboard->grab->interface->key (keyboard->grab,
event->time,
evdev_code (event),

View File

@ -136,4 +136,8 @@ meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard);
void
meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard);
void
meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard,
const ClutterKeyEvent *event);
#endif /* __META_WAYLAND_KEYBOARD_H__ */

View File

@ -347,7 +347,7 @@ count_buttons (const ClutterEvent *event)
return count;
}
void
static void
meta_wayland_seat_update_pointer (MetaWaylandSeat *seat,
const ClutterEvent *event)
{
@ -370,6 +370,27 @@ meta_wayland_seat_update_pointer (MetaWaylandSeat *seat,
}
}
void
meta_wayland_seat_update (MetaWaylandSeat *seat,
const ClutterEvent *event)
{
switch (event->type)
{
case CLUTTER_MOTION:
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
case CLUTTER_SCROLL:
meta_wayland_seat_update_pointer (seat, event);
break;
case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE:
meta_wayland_keyboard_update (&seat->keyboard, (const ClutterKeyEvent *) event);
break;
default:
break;
}
}
gboolean
meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
const ClutterEvent *event)

View File

@ -71,8 +71,8 @@ MetaWaylandSeat *
meta_wayland_seat_new (struct wl_display *display);
void
meta_wayland_seat_update_pointer (MetaWaylandSeat *seat,
const ClutterEvent *event);
meta_wayland_seat_update (MetaWaylandSeat *seat,
const ClutterEvent *event);
gboolean
meta_wayland_seat_handle_event (MetaWaylandSeat *seat,

View File

@ -508,6 +508,15 @@ stage_destroy_cb (void)
meta_quit (META_EXIT_SUCCESS);
}
/**
* meta_wayland_compositor_update:
* @compositor: the #MetaWaylandCompositor instance
* @event: the #ClutterEvent used to update @seat's state
*
* This is used to update display server state like updating cursor
* position and keeping track of buttons and keys pressed. It must be
* called for all input events coming from the underlying devices.
*/
void
meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
const ClutterEvent *event)
@ -536,18 +545,18 @@ meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
meta_idle_monitor_reset_idletime (device_monitor);
}
switch (event->type)
{
case CLUTTER_MOTION:
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
case CLUTTER_SCROLL:
meta_wayland_seat_update_pointer (compositor->seat, event);
default:
break;
}
meta_wayland_seat_update (compositor->seat, event);
}
/**
* meta_wayland_compositor_handle_event:
* @compositor: the #MetaWaylandCompositor instance
* @event: the #ClutterEvent to be sent
*
* This method sends events to the focused wayland client, if any.
*
* Return value: whether @event was sent to a wayland client.
*/
gboolean
meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
const ClutterEvent *event)