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 7564a5c37..49ac2ec98 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c @@ -194,10 +194,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 40fc88aee..190e6ad03 100644 --- a/src/wayland/meta-wayland-private.h +++ b/src/wayland/meta-wayland-private.h @@ -234,6 +234,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; @@ -251,25 +259,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 82dcb20b0..3720919d2 100644 --- a/src/wayland/meta-wayland-seat.c +++ b/src/wayland/meta-wayland-seat.c @@ -271,7 +271,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); @@ -285,7 +286,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 5908ed6a7..cd8b8659a 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -1584,7 +1584,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",