x11: Refresh key mapping when notified by X11
Use both the MappingNotify event and the XKB XkbMapNotify event, if we're compiled with XKB support. This change is also useful for making ClutterKeymapX11 an event translator and let it deal with XKB events internally like we do for stage and input events. Based on a patch by: Damien Lespiau <damien.lespiau@intel.com> Signed-off by: Emmanuele Bassi <ebassi@linux.intel.com> http://bugzilla.clutter-project.org/show_bug.cgi?id=2525
This commit is contained in:
parent
4956152a11
commit
9090070a98
@ -106,9 +106,9 @@ struct _ClutterBackendX11
|
||||
Window xsettings_xwin;
|
||||
|
||||
ClutterKeymapX11 *keymap;
|
||||
int xkb_event_base;
|
||||
gboolean use_xkb;
|
||||
gboolean have_xkb_autorepeat;
|
||||
guint keymap_serial;
|
||||
|
||||
GList *event_translators;
|
||||
};
|
||||
|
@ -27,14 +27,11 @@
|
||||
#include "clutter-backend-x11.h"
|
||||
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-event-translator.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#ifdef HAVE_XINPUT
|
||||
#include <X11/extensions/XInput.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XKB
|
||||
#include <X11/XKBlib.h>
|
||||
#endif
|
||||
@ -56,6 +53,8 @@ struct _ClutterKeymapX11
|
||||
|
||||
#ifdef HAVE_XKB
|
||||
XkbDescPtr xkb_desc;
|
||||
int xkb_event_base;
|
||||
guint xkb_map_serial;
|
||||
#endif
|
||||
|
||||
guint caps_lock_state : 1;
|
||||
@ -76,11 +75,15 @@ enum
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST];
|
||||
static GParamSpec *obj_props[PROP_LAST] = { NULL, };
|
||||
|
||||
static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface);
|
||||
|
||||
#define clutter_keymap_x11_get_type _clutter_keymap_x11_get_type
|
||||
|
||||
G_DEFINE_TYPE (ClutterKeymapX11, clutter_keymap_x11, G_TYPE_OBJECT);
|
||||
G_DEFINE_TYPE_WITH_CODE (ClutterKeymapX11, clutter_keymap_x11, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_TRANSLATOR,
|
||||
clutter_event_translator_iface_init));
|
||||
|
||||
#ifdef HAVE_XKB
|
||||
|
||||
@ -154,6 +157,24 @@ get_xkb (ClutterKeymapX11 *keymap_x11)
|
||||
|
||||
update_modmap (backend_x11->xdpy, keymap_x11);
|
||||
}
|
||||
else if (keymap_x11->xkb_map_serial != backend_x11->keymap_serial)
|
||||
{
|
||||
int flags = XkbKeySymsMask
|
||||
| XkbKeyTypesMask
|
||||
| XkbModifierMapMask
|
||||
| XkbVirtualModsMask;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Updating XKB keymap");
|
||||
|
||||
XkbGetUpdatedMap (backend_x11->xdpy, flags, keymap_x11->xkb_desc);
|
||||
|
||||
flags = XkbGroupNamesMask | XkbVirtualModNamesMask;
|
||||
XkbGetNames (backend_x11->xdpy, flags, keymap_x11->xkb_desc);
|
||||
|
||||
update_modmap (backend_x11->xdpy, keymap_x11);
|
||||
|
||||
keymap_x11->xkb_map_serial = backend_x11->keymap_serial;
|
||||
}
|
||||
|
||||
if (keymap_x11->num_lock_mask == 0)
|
||||
keymap_x11->num_lock_mask = XkbKeysymToModifiers (backend_x11->xdpy,
|
||||
@ -187,40 +208,6 @@ update_locked_mods (ClutterKeymapX11 *keymap_x11,
|
||||
g_signal_emit_by_name (keymap_x11->backend, "key-lock-changed");
|
||||
#endif
|
||||
}
|
||||
|
||||
static ClutterX11FilterReturn
|
||||
xkb_filter (XEvent *xevent,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterBackendX11 *backend_x11 = data;
|
||||
ClutterKeymapX11 *keymap_x11 = backend_x11->keymap;
|
||||
|
||||
g_assert (keymap_x11 != NULL);
|
||||
|
||||
if (!backend_x11->use_xkb)
|
||||
return CLUTTER_X11_FILTER_CONTINUE;
|
||||
|
||||
if (xevent->type == backend_x11->xkb_event_base)
|
||||
{
|
||||
XkbEvent *xkb_event = (XkbEvent *) xevent;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Received XKB event [%d]",
|
||||
xkb_event->any.xkb_type);
|
||||
|
||||
switch (xkb_event->any.xkb_type)
|
||||
{
|
||||
case XkbStateNotify:
|
||||
update_locked_mods (keymap_x11, xkb_event->state.locked_mods);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CLUTTER_X11_FILTER_CONTINUE;
|
||||
}
|
||||
#endif /* HAVE_XKB */
|
||||
|
||||
static void
|
||||
@ -232,7 +219,7 @@ clutter_keymap_x11_constructed (GObject *gobject)
|
||||
g_assert (keymap_x11->backend != NULL);
|
||||
backend_x11 = CLUTTER_BACKEND_X11 (keymap_x11->backend);
|
||||
|
||||
#if HAVE_XKB
|
||||
#ifdef HAVE_XKB
|
||||
{
|
||||
gint xkb_major = XkbMajorVersion;
|
||||
gint xkb_minor = XkbMinorVersion;
|
||||
@ -243,10 +230,13 @@ clutter_keymap_x11_constructed (GObject *gobject)
|
||||
xkb_minor = XkbMinorVersion;
|
||||
|
||||
if (XkbQueryExtension (backend_x11->xdpy,
|
||||
NULL, &backend_x11->xkb_event_base, NULL,
|
||||
NULL,
|
||||
&keymap_x11->xkb_event_base,
|
||||
NULL,
|
||||
&xkb_major, &xkb_minor))
|
||||
{
|
||||
Bool detectable_autorepeat_supported;
|
||||
ClutterEventTranslator *t;
|
||||
|
||||
backend_x11->use_xkb = TRUE;
|
||||
|
||||
@ -260,7 +250,9 @@ clutter_keymap_x11_constructed (GObject *gobject)
|
||||
XkbAllStateComponentsMask,
|
||||
XkbGroupLockMask | XkbModifierLockMask);
|
||||
|
||||
clutter_x11_add_filter (xkb_filter, backend_x11);
|
||||
/* add ourselves as an event translator for XKB events */
|
||||
t = CLUTTER_EVENT_TRANSLATOR (keymap_x11);
|
||||
_clutter_backend_x11_add_event_translator (backend_x11, t);
|
||||
|
||||
/* enable XKB autorepeat */
|
||||
XkbSetDetectableAutoRepeat (backend_x11->xdpy,
|
||||
@ -302,10 +294,16 @@ static void
|
||||
clutter_keymap_x11_finalize (GObject *gobject)
|
||||
{
|
||||
ClutterKeymapX11 *keymap;
|
||||
ClutterBackendX11 *backend;
|
||||
ClutterEventTranslator *translator;
|
||||
|
||||
keymap = CLUTTER_KEYMAP_X11 (gobject);
|
||||
backend = CLUTTER_BACKEND_X11 (keymap->backend);
|
||||
translator = CLUTTER_EVENT_TRANSLATOR (keymap);
|
||||
|
||||
#ifdef HAVE_XKB
|
||||
_clutter_backend_x11_remove_event_translator (backend, translator);
|
||||
|
||||
if (keymap->xkb_desc != NULL)
|
||||
XkbFreeKeyboard (keymap->xkb_desc, XkbAllComponentsMask, True);
|
||||
#endif
|
||||
@ -319,18 +317,17 @@ clutter_keymap_x11_class_init (ClutterKeymapX11Class *klass)
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
obj_props[PROP_BACKEND] =
|
||||
g_param_spec_object ("backend",
|
||||
P_("Backend"),
|
||||
P_("The Clutter backend"),
|
||||
CLUTTER_TYPE_BACKEND,
|
||||
CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
gobject_class->constructed = clutter_keymap_x11_constructed;
|
||||
gobject_class->set_property = clutter_keymap_x11_set_property;
|
||||
gobject_class->finalize = clutter_keymap_x11_finalize;
|
||||
|
||||
pspec = g_param_spec_object ("backend",
|
||||
"Backend",
|
||||
"The Clutter backend",
|
||||
CLUTTER_TYPE_BACKEND,
|
||||
CLUTTER_PARAM_WRITABLE |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
obj_props[PROP_BACKEND] = pspec;
|
||||
g_object_class_install_property (gobject_class, PROP_BACKEND, pspec);
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -338,6 +335,59 @@ clutter_keymap_x11_init (ClutterKeymapX11 *keymap)
|
||||
{
|
||||
}
|
||||
|
||||
static ClutterTranslateReturn
|
||||
clutter_keymap_x11_translate_event (ClutterEventTranslator *translator,
|
||||
gpointer native,
|
||||
ClutterEvent *event)
|
||||
{
|
||||
ClutterKeymapX11 *keymap_x11 = CLUTTER_KEYMAP_X11 (translator);
|
||||
ClutterBackendX11 *backend_x11;
|
||||
ClutterTranslateReturn retval;
|
||||
XEvent *xevent;
|
||||
|
||||
backend_x11 = CLUTTER_BACKEND_X11 (keymap_x11->backend);
|
||||
if (!backend_x11->use_xkb)
|
||||
return CLUTTER_TRANSLATE_CONTINUE;
|
||||
|
||||
xevent = native;
|
||||
|
||||
retval = CLUTTER_TRANSLATE_CONTINUE;
|
||||
|
||||
#ifdef HAVE_XKB
|
||||
if (xevent->type == keymap_x11->xkb_event_base)
|
||||
{
|
||||
XkbEvent *xkb_event = (XkbEvent *) xevent;
|
||||
|
||||
switch (xkb_event->any.xkb_type)
|
||||
{
|
||||
case XkbStateNotify:
|
||||
CLUTTER_NOTE (EVENT, "Updating locked modifiers");
|
||||
update_locked_mods (keymap_x11, xkb_event->state.locked_mods);
|
||||
retval = CLUTTER_TRANSLATE_REMOVE;
|
||||
break;
|
||||
|
||||
case XkbMapNotify:
|
||||
CLUTTER_NOTE (EVENT, "Updating keyboard mapping");
|
||||
XkbRefreshKeyboardMapping (&xkb_event->map);
|
||||
backend_x11->keymap_serial += 1;
|
||||
retval = CLUTTER_TRANSLATE_REMOVE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_XKB */
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface)
|
||||
{
|
||||
iface->translate_event = clutter_keymap_x11_translate_event;
|
||||
}
|
||||
|
||||
gint
|
||||
_clutter_keymap_x11_get_key_group (ClutterKeymapX11 *keymap,
|
||||
ClutterModifierType state)
|
||||
|
@ -1082,6 +1082,13 @@ clutter_stage_x11_translate_event (ClutterEventTranslator *translator,
|
||||
}
|
||||
break;
|
||||
|
||||
case MappingNotify:
|
||||
CLUTTER_NOTE (EVENT, "Refresh keyboard mapping");
|
||||
XRefreshKeyboardMapping (&xevent->xmapping);
|
||||
backend_x11->keymap_serial += 1;
|
||||
res = CLUTTER_TRANSLATE_REMOVE;
|
||||
break;
|
||||
|
||||
default:
|
||||
res = CLUTTER_TRANSLATE_CONTINUE;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user