From e158500ef02a9f94da416b656536a75fa681e83d Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Fri, 9 Aug 2013 17:28:41 +0200 Subject: [PATCH] MetaWaylandKeyboard: use the new clutter-evdev support for xkbcommon We need to track the full xkb_state to have the necessary information to send to the clients, otherwise they may get confused and lock or invert the modifiers. In the evdev backend, we just retrieve the same state object that clutter is using, while in the other backends we fake the state using what clutter is providing (which is a subset of what X11 provides, which would be necessary to have full state) https://bugzilla.gnome.org/show_bug.cgi?id=705862 --- src/wayland/meta-wayland-keyboard.c | 105 +++++++++++++++++++++------- src/wayland/meta-wayland-keyboard.h | 3 +- src/wayland/meta-wayland-pointer.c | 8 +-- src/wayland/meta-wayland-private.h | 20 +++--- src/wayland/meta-wayland-seat.c | 5 +- src/wayland/meta-wayland-seat.h | 3 +- src/wayland/meta-wayland.c | 3 +- 7 files changed, 104 insertions(+), 43 deletions(-) diff --git a/src/wayland/meta-wayland-keyboard.c b/src/wayland/meta-wayland-keyboard.c index c43de914e..70d29b261 100644 --- a/src/wayland/meta-wayland-keyboard.c +++ b/src/wayland/meta-wayland-keyboard.c @@ -56,6 +56,7 @@ #include #include #include +#include #include "meta-wayland-keyboard.h" @@ -258,12 +259,11 @@ default_grab_modifiers (MetaWaylandKeyboardGrab *grab, uint32_t serial, pointer->focus); if (pr) { - wl_keyboard_send_modifiers (pr, - serial, - keyboard->modifiers.mods_depressed, - keyboard->modifiers.mods_latched, - keyboard->modifiers.mods_locked, - keyboard->modifiers.group); + wl_keyboard_send_modifiers (pr, serial, + mods_depressed, + mods_latched, + mods_locked, + group); } } } @@ -276,8 +276,11 @@ static const MetaWaylandKeyboardGrabInterface gboolean meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard, - struct wl_display *display) + struct wl_display *display, + gboolean is_evdev) { + ClutterDeviceManager *manager; + memset (keyboard, 0, sizeof *keyboard); wl_list_init (&keyboard->resource_list); @@ -293,8 +296,22 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard, keyboard->xkb_context = xkb_context_new (0 /* flags */); meta_wayland_keyboard_build_global_keymap (keyboard->xkb_context, - &keyboard->xkb_names, - &keyboard->xkb_info); + &keyboard->xkb_names, + &keyboard->xkb_info); + + keyboard->is_evdev = is_evdev; + if (is_evdev) + { + manager = clutter_device_manager_get_default (); + + clutter_evdev_set_keyboard_map (manager, keyboard->xkb_info.keymap); + keyboard->xkb_state = clutter_evdev_get_keyboard_state (manager); + xkb_state_ref (keyboard->xkb_state); + } + else + { + keyboard->xkb_state = xkb_state_new (keyboard->xkb_info.keymap); + } return TRUE; } @@ -312,17 +329,12 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info) } static void -set_modifiers (MetaWaylandKeyboard *keyboard, - guint32 serial, - ClutterModifierType modifier_state) +update_state_from_clutter (MetaWaylandKeyboard *keyboard, + ClutterModifierType modifier_state) { - MetaWaylandKeyboardGrab *grab = keyboard->grab; uint32_t depressed_mods = 0; uint32_t locked_mods = 0; - if (keyboard->last_modifier_state == modifier_state) - return; - if ((modifier_state & CLUTTER_SHIFT_MASK) && keyboard->xkb_info.shift_mod != XKB_MOD_INVALID) depressed_mods |= (1 << keyboard->xkb_info.shift_mod); @@ -355,14 +367,56 @@ set_modifiers (MetaWaylandKeyboard *keyboard, keyboard->xkb_info.mod5_mod != XKB_MOD_INVALID) depressed_mods |= (1 << keyboard->xkb_info.mod5_mod); - keyboard->last_modifier_state = modifier_state; + xkb_state_update_mask (keyboard->xkb_state, + depressed_mods, + 0, + locked_mods, + 0, 0, 0); +} + +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 +set_modifiers (MetaWaylandKeyboard *keyboard, + guint32 serial, + ClutterModifierType modifier_state) +{ + MetaWaylandKeyboardGrab *grab = keyboard->grab; + MetaWaylandXkbState new_state; + + /* In the evdev case, the state is shared with the clutter backend, so + we don't need to update it */ + if (!keyboard->is_evdev) + update_state_from_clutter (keyboard, modifier_state); + + new_state.mods_depressed = xkb_state_serialize_mods (keyboard->xkb_state, + XKB_STATE_MODS_DEPRESSED); + new_state.mods_latched = xkb_state_serialize_mods (keyboard->xkb_state, + XKB_STATE_MODS_LATCHED); + new_state.mods_locked = xkb_state_serialize_mods (keyboard->xkb_state, + XKB_STATE_MODS_LOCKED); + new_state.group = xkb_state_serialize_layout (keyboard->xkb_state, + XKB_STATE_LAYOUT_EFFECTIVE); + + if (state_equal (&keyboard->modifier_state, &new_state)) + return; + + keyboard->modifier_state = new_state; grab->interface->modifiers (grab, serial, - depressed_mods, - 0, /* latched_modes */ - locked_mods, - 0 /* group */); + new_state.mods_depressed, + new_state.mods_latched, + new_state.mods_locked, + new_state.group); } void @@ -462,10 +516,10 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard, display = wl_client_get_display (client); serial = wl_display_next_serial (display); wl_keyboard_send_modifiers (resource, serial, - keyboard->modifiers.mods_depressed, - keyboard->modifiers.mods_latched, - keyboard->modifiers.mods_locked, - keyboard->modifiers.group); + keyboard->modifier_state.mods_depressed, + keyboard->modifier_state.mods_latched, + keyboard->modifier_state.mods_locked, + keyboard->modifier_state.group); wl_keyboard_send_enter (resource, serial, surface->resource, &keyboard->keys); wl_resource_add_destroy_listener (resource, &keyboard->focus_listener); @@ -504,6 +558,7 @@ meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard) meta_wayland_xkb_info_destroy (&keyboard->xkb_info); xkb_context_unref (keyboard->xkb_context); + xkb_state_unref (keyboard->xkb_state); /* XXX: What about keyboard->resource_list? */ if (keyboard->focus_resource) diff --git a/src/wayland/meta-wayland-keyboard.h b/src/wayland/meta-wayland-keyboard.h index fd0d0b3c0..e092366b9 100644 --- a/src/wayland/meta-wayland-keyboard.h +++ b/src/wayland/meta-wayland-keyboard.h @@ -52,7 +52,8 @@ gboolean meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard, - struct wl_display *display); + struct wl_display *display, + gboolean is_evdev); void meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard, diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c index fd0efed2f..3ef13118d 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c @@ -192,10 +192,10 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, { wl_keyboard_send_modifiers (kr, serial, - kbd->modifiers.mods_depressed, - kbd->modifiers.mods_latched, - kbd->modifiers.mods_locked, - kbd->modifiers.group); + kbd->modifier_state.mods_depressed, + kbd->modifier_state.mods_latched, + kbd->modifier_state.mods_locked, + kbd->modifier_state.group); } } wl_pointer_send_enter (resource, serial, surface->resource, sx, sy); diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h index 7f99493c9..1d5b8845b 100644 --- a/src/wayland/meta-wayland-private.h +++ b/src/wayland/meta-wayland-private.h @@ -256,6 +256,14 @@ typedef struct xkb_mod_index_t mod5_mod; } MetaWaylandXkbInfo; +typedef struct +{ + uint32_t mods_depressed; + uint32_t mods_latched; + uint32_t mods_locked; + uint32_t group; +} MetaWaylandXkbState; + struct _MetaWaylandKeyboard { struct wl_list resource_list; @@ -273,25 +281,19 @@ struct _MetaWaylandKeyboard struct wl_array keys; - struct - { - uint32_t mods_depressed; - uint32_t mods_latched; - uint32_t mods_locked; - uint32_t group; - } modifiers; + MetaWaylandXkbState modifier_state; struct wl_display *display; struct xkb_context *xkb_context; + struct xkb_state *xkb_state; + gboolean is_evdev; MetaWaylandXkbInfo xkb_info; struct xkb_rule_names xkb_names; MetaWaylandKeyboardGrab input_method_grab; struct wl_resource *input_method_resource; - - ClutterModifierType last_modifier_state; }; struct _MetaWaylandDataOffer diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c index 9fb285abf..e519d758c 100644 --- a/src/wayland/meta-wayland-seat.c +++ b/src/wayland/meta-wayland-seat.c @@ -258,7 +258,8 @@ pointer_handle_sprite_destroy (struct wl_listener *listener, void *data) } MetaWaylandSeat * -meta_wayland_seat_new (struct wl_display *display) +meta_wayland_seat_new (struct wl_display *display, + gboolean is_native) { MetaWaylandSeat *seat = g_new0 (MetaWaylandSeat, 1); @@ -272,7 +273,7 @@ meta_wayland_seat_new (struct wl_display *display) meta_wayland_pointer_init (&seat->pointer); - meta_wayland_keyboard_init (&seat->keyboard, display); + meta_wayland_keyboard_init (&seat->keyboard, display, is_native); seat->display = display; diff --git a/src/wayland/meta-wayland-seat.h b/src/wayland/meta-wayland-seat.h index 89bcd76cc..d5a05976f 100644 --- a/src/wayland/meta-wayland-seat.h +++ b/src/wayland/meta-wayland-seat.h @@ -30,7 +30,8 @@ #include "meta-wayland-private.h" MetaWaylandSeat * -meta_wayland_seat_new (struct wl_display *display); +meta_wayland_seat_new (struct wl_display *display, + gboolean is_native); void meta_wayland_seat_handle_event (MetaWaylandSeat *seat, diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index 8e716f298..50d3a27d2 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -1554,7 +1554,8 @@ meta_wayland_init (void) meta_wayland_data_device_manager_init (compositor->wayland_display); - compositor->seat = meta_wayland_seat_new (compositor->wayland_display); + compositor->seat = meta_wayland_seat_new (compositor->wayland_display, + compositor->drm_fd >= 0); g_signal_connect (compositor->stage, "captured-event",