x11: Use XKB detectable auto-repeat
If we have XKB support then we should be using it to turn on the detectable auto-repeat; this allows avoiding the peeking trick that emulates it inside the event handling code.
This commit is contained in:
parent
bea657d3d5
commit
bf2f8d670d
@ -91,6 +91,9 @@ struct _ClutterBackendX11
|
||||
Window xsettings_xwin;
|
||||
|
||||
ClutterKeymapX11 *keymap;
|
||||
int xkb_event_base;
|
||||
gboolean use_xkb;
|
||||
gboolean have_xkb_autorepeat;
|
||||
};
|
||||
|
||||
struct _ClutterBackendX11Class
|
||||
|
@ -329,9 +329,9 @@ convert_xdevicekey_to_xkey (XDeviceKeyEvent *xkev,
|
||||
#endif /* HAVE_XINPUT */
|
||||
|
||||
static void
|
||||
translate_key_event (ClutterBackend *backend,
|
||||
ClutterEvent *event,
|
||||
XEvent *xevent)
|
||||
translate_key_event (ClutterBackendX11 *backend_x11,
|
||||
ClutterEvent *event,
|
||||
XEvent *xevent)
|
||||
{
|
||||
ClutterEventX11 *event_x11;
|
||||
char buffer[256 + 1];
|
||||
@ -355,7 +355,8 @@ translate_key_event (ClutterBackend *backend,
|
||||
0);
|
||||
|
||||
event_x11->key_group =
|
||||
_clutter_keymap_x11_get_key_group (event->key.modifier_state);
|
||||
_clutter_keymap_x11_get_key_group (backend_x11->keymap,
|
||||
event->key.modifier_state);
|
||||
|
||||
/* unicode_value is the printable representation */
|
||||
n = XLookupString (&xevent->xkey, buffer, sizeof (buffer) - 1, NULL, NULL);
|
||||
@ -712,7 +713,7 @@ event_translate (ClutterBackend *backend,
|
||||
clutter_device_manager_get_core_device (manager,
|
||||
CLUTTER_KEYBOARD_DEVICE);
|
||||
|
||||
translate_key_event (backend, event, xevent);
|
||||
translate_key_event (backend_x11, event, xevent);
|
||||
|
||||
set_user_time (backend_x11, &xwindow, xevent->xkey.time);
|
||||
break;
|
||||
@ -728,8 +729,11 @@ event_translate (ClutterBackend *backend,
|
||||
* the next event and check if it's a KeyPress for the same key
|
||||
* and timestamp - and then ignore it if it matches the
|
||||
* KeyRelease
|
||||
*
|
||||
* if we have XKB, and autorepeat is enabled, then this becomes
|
||||
* a no-op
|
||||
*/
|
||||
if (XPending (xevent->xkey.display))
|
||||
if (!backend_x11->have_xkb_autorepeat && XPending (xevent->xkey.display))
|
||||
{
|
||||
XEvent next_event;
|
||||
|
||||
@ -749,7 +753,7 @@ event_translate (ClutterBackend *backend,
|
||||
clutter_device_manager_get_core_device (manager,
|
||||
CLUTTER_KEYBOARD_DEVICE);
|
||||
|
||||
translate_key_event (backend, event, xevent);
|
||||
translate_key_event (backend_x11, event, xevent);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1029,7 +1033,7 @@ event_translate (ClutterBackend *backend,
|
||||
? CLUTTER_KEY_PRESS
|
||||
: CLUTTER_KEY_RELEASE;
|
||||
|
||||
translate_key_event (backend, event, &xevent_converted);
|
||||
translate_key_event (backend_x11, event, &xevent_converted);
|
||||
|
||||
if (xevent->type == key_press)
|
||||
set_user_time (backend_x11, &xwindow, xkev->time);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#endif
|
||||
|
||||
#include "clutter-keymap-x11.h"
|
||||
#include "clutter-backend-x11.h"
|
||||
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-private.h"
|
||||
@ -47,6 +48,17 @@ struct _ClutterKeymapX11
|
||||
GObject parent_instance;
|
||||
|
||||
ClutterBackend *backend;
|
||||
|
||||
gint min_keycode;
|
||||
gint max_keycode;
|
||||
|
||||
ClutterModifierType modmap[8];
|
||||
|
||||
ClutterModifierType num_lock_mask;
|
||||
|
||||
#ifdef HAVE_XKB
|
||||
XkbDescPtr xkb_desc;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _ClutterKeymapX11Class
|
||||
@ -63,6 +75,143 @@ enum
|
||||
|
||||
G_DEFINE_TYPE (ClutterKeymapX11, clutter_keymap_x11, G_TYPE_OBJECT);
|
||||
|
||||
#ifdef HAVE_XKB
|
||||
|
||||
/* code adapted from gdk/x11/gdkkeys-x11.c - update_modmap */
|
||||
static void
|
||||
update_modmap (Display *display,
|
||||
ClutterKeymapX11 *keymap_x11)
|
||||
{
|
||||
static struct {
|
||||
const gchar *name;
|
||||
Atom atom;
|
||||
ClutterModifierType mask;
|
||||
} vmods[] = {
|
||||
{ "Meta", 0, CLUTTER_META_MASK },
|
||||
{ "Super", 0, CLUTTER_SUPER_MASK },
|
||||
{ "Hyper", 0, CLUTTER_HYPER_MASK },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
int i, j, k;
|
||||
|
||||
if (vmods[0].atom == 0)
|
||||
for (i = 0; vmods[i].name; i++)
|
||||
vmods[i].atom = XInternAtom (display, vmods[i].name, FALSE);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
keymap_x11->modmap[i] = 1 << i;
|
||||
|
||||
for (i = 0; i < XkbNumVirtualMods; i++)
|
||||
{
|
||||
for (j = 0; vmods[j].atom; j++)
|
||||
{
|
||||
if (keymap_x11->xkb_desc->names->vmods[i] == vmods[j].atom)
|
||||
{
|
||||
for (k = 0; k < 8; k++)
|
||||
{
|
||||
if (keymap_x11->xkb_desc->server->vmods[i] & (1 << k))
|
||||
keymap_x11->modmap[k] |= vmods[j].mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static XkbDescPtr
|
||||
get_xkb (ClutterKeymapX11 *keymap_x11)
|
||||
{
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (keymap_x11->backend);
|
||||
|
||||
if (keymap_x11->max_keycode == 0)
|
||||
XDisplayKeycodes (backend_x11->xdpy,
|
||||
&keymap_x11->min_keycode,
|
||||
&keymap_x11->max_keycode);
|
||||
|
||||
if (keymap_x11->xkb_desc == NULL)
|
||||
{
|
||||
int flags = XkbKeySymsMask
|
||||
| XkbKeyTypesMask
|
||||
| XkbModifierMapMask
|
||||
| XkbVirtualModsMask;
|
||||
|
||||
keymap_x11->xkb_desc = XkbGetMap (backend_x11->xdpy, flags, XkbUseCoreKbd);
|
||||
if (G_UNLIKELY (keymap_x11->xkb_desc == NULL))
|
||||
{
|
||||
g_error ("Failed to get the keymap from XKB");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flags = XkbGroupNamesMask | XkbVirtualModNamesMask;
|
||||
XkbGetNames (backend_x11->xdpy, flags, keymap_x11->xkb_desc);
|
||||
|
||||
update_modmap (backend_x11->xdpy, keymap_x11);
|
||||
}
|
||||
|
||||
if (keymap_x11->num_lock_mask == 0)
|
||||
keymap_x11->num_lock_mask = XkbKeysymToModifiers (backend_x11->xdpy,
|
||||
XK_Num_Lock);
|
||||
|
||||
return keymap_x11->xkb_desc;
|
||||
}
|
||||
#endif /* HAVE_XKB */
|
||||
|
||||
static void
|
||||
clutter_keymap_x11_constructed (GObject *gobject)
|
||||
{
|
||||
ClutterKeymapX11 *keymap_x11 = CLUTTER_KEYMAP_X11 (gobject);
|
||||
ClutterBackendX11 *backend_x11;
|
||||
|
||||
g_assert (keymap_x11->backend != NULL);
|
||||
backend_x11 = CLUTTER_BACKEND_X11 (keymap_x11->backend);
|
||||
|
||||
#if HAVE_XKB
|
||||
{
|
||||
gint xkb_major = XkbMajorVersion;
|
||||
gint xkb_minor = XkbMinorVersion;
|
||||
|
||||
if (XkbLibraryVersion (&xkb_major, &xkb_minor))
|
||||
{
|
||||
xkb_major = XkbMajorVersion;
|
||||
xkb_minor = XkbMinorVersion;
|
||||
|
||||
if (XkbQueryExtension (backend_x11->xdpy,
|
||||
NULL, &backend_x11->xkb_event_base, NULL,
|
||||
&xkb_major, &xkb_minor))
|
||||
{
|
||||
Bool detectable_autorepeat_supported;
|
||||
|
||||
backend_x11->use_xkb = TRUE;
|
||||
|
||||
#if 0
|
||||
/* XXX - enable when we handle keymap-related events */
|
||||
XkbSelectEvents (backend_x11->xdpy,
|
||||
XkbUseCoreKbd,
|
||||
XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask,
|
||||
XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask);
|
||||
|
||||
XkbSelectEventDetails (backend_x11->xdpy,
|
||||
XkbUseCoreKbd, XkbStateNotify,
|
||||
XkbAllStateComponentsMask,
|
||||
XkbGroupLockMask|XkbModifierLockMask);
|
||||
#endif
|
||||
|
||||
/* enable XKB autorepeat */
|
||||
XkbSetDetectableAutoRepeat (backend_x11->xdpy,
|
||||
True,
|
||||
&detectable_autorepeat_supported);
|
||||
|
||||
backend_x11->have_xkb_autorepeat = detectable_autorepeat_supported;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Detectable autorepeat: %s",
|
||||
backend_x11->have_xkb_autorepeat ? "supported"
|
||||
: "not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_XKB */
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_keymap_x11_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
@ -95,6 +244,7 @@ clutter_keymap_x11_class_init (ClutterKeymapX11Class *klass)
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
gobject_class->constructed = clutter_keymap_x11_constructed;
|
||||
gobject_class->set_property = clutter_keymap_x11_set_property;
|
||||
gobject_class->finalize = clutter_keymap_x11_finalize;
|
||||
|
||||
@ -113,9 +263,12 @@ clutter_keymap_x11_init (ClutterKeymapX11 *keymap)
|
||||
}
|
||||
|
||||
gint
|
||||
_clutter_keymap_x11_get_key_group (ClutterModifierType state)
|
||||
_clutter_keymap_x11_get_key_group (ClutterKeymapX11 *keymap,
|
||||
ClutterModifierType state)
|
||||
{
|
||||
#ifdef HAVE_XKB
|
||||
(void) get_xkb (keymap);
|
||||
|
||||
return XkbGroupForCoreState (state);
|
||||
#else
|
||||
return 0;
|
||||
|
@ -37,7 +37,8 @@ typedef struct _ClutterKeymapX11 ClutterKeymapX11;
|
||||
|
||||
GType clutter_keymap_x11_get_type (void) G_GNUC_CONST;
|
||||
|
||||
gint _clutter_keymap_x11_get_key_group (ClutterModifierType state);
|
||||
gint _clutter_keymap_x11_get_key_group (ClutterKeymapX11 *keymap,
|
||||
ClutterModifierType state);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user