wayland: Add MetaWaylandKeyboardGrab and keyboard grab API

This will be useful during DnD, where mutter is expected to consume
keyboard events for either allowing changes in the selected DnD action,
or misc a11y features like keyboard-driven DnD.

Currently, the vtable contains 2 functions, key() will be used on every
key event we get from Clutter, modifiers() will notify of changes in the
keyboard modifiers (mouse buttons will never be set in the modifier mask)

https://bugzilla.gnome.org/show_bug.cgi?id=760805
This commit is contained in:
Carlos Garnacho 2015-04-07 15:54:41 +02:00
parent 6b88420465
commit ec9abaf1ef
3 changed files with 105 additions and 15 deletions

View File

@ -68,6 +68,7 @@
static void meta_wayland_keyboard_update_xkb_state (MetaWaylandKeyboard *keyboard);
static void notify_modifiers (MetaWaylandKeyboard *keyboard);
static guint evdev_code (const ClutterKeyEvent *event);
static void
unbind_resource (struct wl_resource *resource)
@ -245,8 +246,10 @@ keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
}
static gboolean
notify_key (MetaWaylandKeyboard *keyboard,
uint32_t time, uint32_t key, uint32_t state)
meta_wayland_keyboard_broadcast_key (MetaWaylandKeyboard *keyboard,
uint32_t time,
uint32_t key,
uint32_t state)
{
struct wl_resource *resource;
struct wl_list *l;
@ -269,8 +272,15 @@ notify_key (MetaWaylandKeyboard *keyboard,
return (keyboard->focus_surface != NULL);
}
static gboolean
notify_key (MetaWaylandKeyboard *keyboard,
const ClutterEvent *event)
{
return keyboard->grab->interface->key (keyboard->grab, event);
}
static void
notify_modifiers (MetaWaylandKeyboard *keyboard)
meta_wayland_keyboard_broadcast_modifiers (MetaWaylandKeyboard *keyboard)
{
struct xkb_state *state;
struct wl_resource *resource;
@ -295,6 +305,16 @@ notify_modifiers (MetaWaylandKeyboard *keyboard)
}
}
static void
notify_modifiers (MetaWaylandKeyboard *keyboard)
{
struct xkb_state *state;
state = keyboard->xkb_info.state;
keyboard->grab->interface->modifiers (keyboard->grab,
xkb_state_serialize_mods (state, XKB_STATE_MODS_EFFECTIVE));
}
static void
meta_wayland_keyboard_update_xkb_state (MetaWaylandKeyboard *keyboard)
{
@ -374,6 +394,45 @@ settings_changed (GSettings *settings,
notify_key_repeat (keyboard);
}
static gboolean
default_grab_key (MetaWaylandKeyboardGrab *grab,
const ClutterEvent *event)
{
MetaWaylandKeyboard *keyboard = grab->keyboard;
gboolean is_press = event->type == CLUTTER_KEY_PRESS;
guint32 code;
#ifdef HAVE_NATIVE_BACKEND
MetaBackend *backend = meta_get_backend ();
#endif
/* Synthetic key events are for autorepeat. Ignore those, as
* autorepeat in Wayland is done on the client side. */
if (event->key.flags & CLUTTER_EVENT_FLAG_SYNTHETIC)
return FALSE;
#ifdef HAVE_NATIVE_BACKEND
if (META_IS_BACKEND_NATIVE (backend))
code = clutter_evdev_event_get_event_code (event);
else
#endif
code = evdev_code (&event->key);
return meta_wayland_keyboard_broadcast_key (keyboard, event->key.time,
code, is_press);
}
static void
default_grab_modifiers (MetaWaylandKeyboardGrab *grab,
ClutterModifierType modifiers)
{
meta_wayland_keyboard_broadcast_modifiers (grab->keyboard);
}
static const MetaWaylandKeyboardGrabInterface default_keyboard_grab_interface = {
default_grab_key,
default_grab_modifiers
};
void
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
struct wl_display *display)
@ -391,6 +450,10 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
keyboard->xkb_info.keymap_fd = -1;
keyboard->default_grab.interface = &default_keyboard_grab_interface;
keyboard->default_grab.keyboard = keyboard;
keyboard->grab = &keyboard->default_grab;
keyboard->settings = g_settings_new ("org.gnome.desktop.peripherals.keyboard");
g_signal_connect (keyboard->settings, "changed",
G_CALLBACK (settings_changed), keyboard);
@ -457,10 +520,6 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
{
gboolean is_press = event->type == CLUTTER_KEY_PRESS;
gboolean handled;
guint32 code;
#ifdef HAVE_NATIVE_BACKEND
MetaBackend *backend = meta_get_backend ();
#endif
/* Synthetic key events are for autorepeat. Ignore those, as
* autorepeat in Wayland is done on the client side. */
@ -471,14 +530,7 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
is_press ? "press" : "release",
event->hardware_keycode);
#ifdef HAVE_NATIVE_BACKEND
if (META_IS_BACKEND_NATIVE (backend))
code = clutter_evdev_event_get_event_code ((const ClutterEvent *) event);
else
#endif
code = evdev_code (event);
handled = notify_key (keyboard, event->time, code, is_press);
handled = notify_key (keyboard, (const ClutterEvent *) event);
if (handled)
meta_verbose ("Sent event to wayland client\n");
@ -696,3 +748,18 @@ meta_wayland_keyboard_can_popup (MetaWaylandKeyboard *keyboard,
{
return keyboard->key_serial == serial;
}
void
meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *keyboard,
MetaWaylandKeyboardGrab *grab)
{
meta_wayland_keyboard_set_focus (keyboard, NULL);
keyboard->grab = grab;
grab->keyboard = keyboard;
}
void
meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard)
{
keyboard->grab = &keyboard->default_grab;
}

View File

@ -49,6 +49,20 @@
#include <wayland-server.h>
#include <xkbcommon/xkbcommon.h>
struct _MetaWaylandKeyboardGrabInterface
{
gboolean (*key) (MetaWaylandKeyboardGrab *grab,
const ClutterEvent *event);
void (*modifiers) (MetaWaylandKeyboardGrab *grab,
ClutterModifierType modifiers);
};
struct _MetaWaylandKeyboardGrab
{
const MetaWaylandKeyboardGrabInterface *interface;
MetaWaylandKeyboard *keyboard;
};
typedef struct
{
struct xkb_keymap *keymap;
@ -73,6 +87,9 @@ struct _MetaWaylandKeyboard
MetaWaylandXkbInfo xkb_info;
enum xkb_state_component mods_changed;
MetaWaylandKeyboardGrab *grab;
MetaWaylandKeyboardGrab default_grab;
GSettings *settings;
};
@ -104,4 +121,8 @@ void meta_wayland_keyboard_create_new_resource (MetaWaylandKeyboard *keyboard,
gboolean meta_wayland_keyboard_can_popup (MetaWaylandKeyboard *keyboard,
uint32_t serial);
void meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *keyboard,
MetaWaylandKeyboardGrab *grab);
void meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard);
#endif /* META_WAYLAND_KEYBOARD_H */

View File

@ -29,6 +29,8 @@ typedef struct _MetaWaylandPointerGrabInterface MetaWaylandPointerGrabInterface;
typedef struct _MetaWaylandPopupGrab MetaWaylandPopupGrab;
typedef struct _MetaWaylandPopup MetaWaylandPopup;
typedef struct _MetaWaylandKeyboard MetaWaylandKeyboard;
typedef struct _MetaWaylandKeyboardGrab MetaWaylandKeyboardGrab;
typedef struct _MetaWaylandKeyboardGrabInterface MetaWaylandKeyboardGrabInterface;
typedef struct _MetaWaylandTouch MetaWaylandTouch;
typedef struct _MetaWaylandDragDestFuncs MetaWaylandDragDestFuncs;
typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;