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
This commit is contained in:
Giovanni Campagna 2013-08-09 17:28:41 +02:00
parent 0cceddab75
commit 519a06b93d
7 changed files with 104 additions and 43 deletions

View File

@ -56,6 +56,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <clutter/evdev/clutter-evdev.h>
#include "meta-wayland-keyboard.h" #include "meta-wayland-keyboard.h"
@ -258,12 +259,11 @@ default_grab_modifiers (MetaWaylandKeyboardGrab *grab, uint32_t serial,
pointer->focus); pointer->focus);
if (pr) if (pr)
{ {
wl_keyboard_send_modifiers (pr, wl_keyboard_send_modifiers (pr, serial,
serial, mods_depressed,
keyboard->modifiers.mods_depressed, mods_latched,
keyboard->modifiers.mods_latched, mods_locked,
keyboard->modifiers.mods_locked, group);
keyboard->modifiers.group);
} }
} }
} }
@ -276,8 +276,11 @@ static const MetaWaylandKeyboardGrabInterface
gboolean gboolean
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard, meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
struct wl_display *display) struct wl_display *display,
gboolean is_evdev)
{ {
ClutterDeviceManager *manager;
memset (keyboard, 0, sizeof *keyboard); memset (keyboard, 0, sizeof *keyboard);
wl_list_init (&keyboard->resource_list); wl_list_init (&keyboard->resource_list);
@ -293,8 +296,22 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
keyboard->xkb_context = xkb_context_new (0 /* flags */); keyboard->xkb_context = xkb_context_new (0 /* flags */);
meta_wayland_keyboard_build_global_keymap (keyboard->xkb_context, meta_wayland_keyboard_build_global_keymap (keyboard->xkb_context,
&keyboard->xkb_names, &keyboard->xkb_names,
&keyboard->xkb_info); &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; return TRUE;
} }
@ -312,17 +329,12 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
} }
static void static void
set_modifiers (MetaWaylandKeyboard *keyboard, update_state_from_clutter (MetaWaylandKeyboard *keyboard,
guint32 serial, ClutterModifierType modifier_state)
ClutterModifierType modifier_state)
{ {
MetaWaylandKeyboardGrab *grab = keyboard->grab;
uint32_t depressed_mods = 0; uint32_t depressed_mods = 0;
uint32_t locked_mods = 0; uint32_t locked_mods = 0;
if (keyboard->last_modifier_state == modifier_state)
return;
if ((modifier_state & CLUTTER_SHIFT_MASK) && if ((modifier_state & CLUTTER_SHIFT_MASK) &&
keyboard->xkb_info.shift_mod != XKB_MOD_INVALID) keyboard->xkb_info.shift_mod != XKB_MOD_INVALID)
depressed_mods |= (1 << keyboard->xkb_info.shift_mod); depressed_mods |= (1 << keyboard->xkb_info.shift_mod);
@ -355,14 +367,56 @@ set_modifiers (MetaWaylandKeyboard *keyboard,
keyboard->xkb_info.mod5_mod != XKB_MOD_INVALID) keyboard->xkb_info.mod5_mod != XKB_MOD_INVALID)
depressed_mods |= (1 << keyboard->xkb_info.mod5_mod); 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, grab->interface->modifiers (grab,
serial, serial,
depressed_mods, new_state.mods_depressed,
0, /* latched_modes */ new_state.mods_latched,
locked_mods, new_state.mods_locked,
0 /* group */); new_state.group);
} }
void void
@ -462,10 +516,10 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
display = wl_client_get_display (client); display = wl_client_get_display (client);
serial = wl_display_next_serial (display); serial = wl_display_next_serial (display);
wl_keyboard_send_modifiers (resource, serial, wl_keyboard_send_modifiers (resource, serial,
keyboard->modifiers.mods_depressed, keyboard->modifier_state.mods_depressed,
keyboard->modifiers.mods_latched, keyboard->modifier_state.mods_latched,
keyboard->modifiers.mods_locked, keyboard->modifier_state.mods_locked,
keyboard->modifiers.group); keyboard->modifier_state.group);
wl_keyboard_send_enter (resource, serial, surface->resource, wl_keyboard_send_enter (resource, serial, surface->resource,
&keyboard->keys); &keyboard->keys);
wl_resource_add_destroy_listener (resource, &keyboard->focus_listener); 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); meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
xkb_context_unref (keyboard->xkb_context); xkb_context_unref (keyboard->xkb_context);
xkb_state_unref (keyboard->xkb_state);
/* XXX: What about keyboard->resource_list? */ /* XXX: What about keyboard->resource_list? */
if (keyboard->focus_resource) if (keyboard->focus_resource)

View File

@ -52,7 +52,8 @@
gboolean gboolean
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard, meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
struct wl_display *display); struct wl_display *display,
gboolean is_evdev);
void void
meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard, meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,

View File

@ -194,10 +194,10 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
{ {
wl_keyboard_send_modifiers (kr, wl_keyboard_send_modifiers (kr,
serial, serial,
kbd->modifiers.mods_depressed, kbd->modifier_state.mods_depressed,
kbd->modifiers.mods_latched, kbd->modifier_state.mods_latched,
kbd->modifiers.mods_locked, kbd->modifier_state.mods_locked,
kbd->modifiers.group); kbd->modifier_state.group);
} }
} }
wl_pointer_send_enter (resource, serial, surface->resource, sx, sy); wl_pointer_send_enter (resource, serial, surface->resource, sx, sy);

View File

@ -234,6 +234,14 @@ typedef struct
xkb_mod_index_t mod5_mod; xkb_mod_index_t mod5_mod;
} 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;
@ -251,25 +259,19 @@ struct _MetaWaylandKeyboard
struct wl_array keys; struct wl_array keys;
struct MetaWaylandXkbState modifier_state;
{
uint32_t mods_depressed;
uint32_t mods_latched;
uint32_t mods_locked;
uint32_t group;
} modifiers;
struct wl_display *display; struct wl_display *display;
struct xkb_context *xkb_context; struct xkb_context *xkb_context;
struct xkb_state *xkb_state;
gboolean is_evdev;
MetaWaylandXkbInfo xkb_info; MetaWaylandXkbInfo xkb_info;
struct xkb_rule_names xkb_names; struct xkb_rule_names xkb_names;
MetaWaylandKeyboardGrab input_method_grab; MetaWaylandKeyboardGrab input_method_grab;
struct wl_resource *input_method_resource; struct wl_resource *input_method_resource;
ClutterModifierType last_modifier_state;
}; };
struct _MetaWaylandDataOffer struct _MetaWaylandDataOffer

View File

@ -271,7 +271,8 @@ pointer_handle_sprite_destroy (struct wl_listener *listener, void *data)
} }
MetaWaylandSeat * 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); 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_pointer_init (&seat->pointer);
meta_wayland_keyboard_init (&seat->keyboard, display); meta_wayland_keyboard_init (&seat->keyboard, display, is_native);
seat->display = display; seat->display = display;

View File

@ -30,7 +30,8 @@
#include "meta-wayland-private.h" #include "meta-wayland-private.h"
MetaWaylandSeat * MetaWaylandSeat *
meta_wayland_seat_new (struct wl_display *display); meta_wayland_seat_new (struct wl_display *display,
gboolean is_native);
void void
meta_wayland_seat_handle_event (MetaWaylandSeat *seat, meta_wayland_seat_handle_event (MetaWaylandSeat *seat,

View File

@ -1584,7 +1584,8 @@ meta_wayland_init (void)
meta_wayland_data_device_manager_init (compositor->wayland_display); 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, g_signal_connect (compositor->stage,
"captured-event", "captured-event",