mirror of
https://github.com/brl/mutter.git
synced 2025-02-19 06:34:09 +00:00
backends: Add methods to handle keymaps
These methods allow us to set and get xkbcommon keymaps as well as locking a specific layout in a layout group. With this, we introduce dependencies on xkeyboard-config, xkbfile, xkbcommon-x11 and a libX11 new enough to have xcb support. https://bugzilla.gnome.org/show_bug.cgi?id=734301
This commit is contained in:
parent
6af48de0b8
commit
101b215d6b
@ -87,6 +87,9 @@ MUTTER_PC_MODULES="
|
|||||||
wayland-server >= 1.5.90
|
wayland-server >= 1.5.90
|
||||||
upower-glib >= 0.99.0
|
upower-glib >= 0.99.0
|
||||||
gnome-desktop-3.0
|
gnome-desktop-3.0
|
||||||
|
xkbfile
|
||||||
|
xkeyboard-config
|
||||||
|
xkbcommon-x11
|
||||||
"
|
"
|
||||||
|
|
||||||
GLIB_GSETTINGS
|
GLIB_GSETTINGS
|
||||||
@ -235,6 +238,9 @@ if test x$have_xinerama = xno; then
|
|||||||
AC_MSG_ERROR([Xinerama extension was not found])
|
AC_MSG_ERROR([Xinerama extension was not found])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_DEFINE_UNQUOTED([XKB_BASE], ["`$PKG_CONFIG --variable xkb_base xkeyboard-config`"],
|
||||||
|
[XKB base dir])
|
||||||
|
|
||||||
RANDR_LIBS=
|
RANDR_LIBS=
|
||||||
found_randr=no
|
found_randr=no
|
||||||
AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration,
|
AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration,
|
||||||
|
@ -30,6 +30,9 @@
|
|||||||
|
|
||||||
#include "meta-backend.h"
|
#include "meta-backend.h"
|
||||||
|
|
||||||
|
#define DEFAULT_XKB_RULES_FILE "evdev"
|
||||||
|
#define DEFAULT_XKB_MODEL "pc105+inet"
|
||||||
|
|
||||||
#define META_TYPE_BACKEND (meta_backend_get_type ())
|
#define META_TYPE_BACKEND (meta_backend_get_type ())
|
||||||
#define META_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND, MetaBackend))
|
#define META_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND, MetaBackend))
|
||||||
#define META_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BACKEND, MetaBackendClass))
|
#define META_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BACKEND, MetaBackendClass))
|
||||||
@ -66,6 +69,16 @@ struct _MetaBackendClass
|
|||||||
void (* warp_pointer) (MetaBackend *backend,
|
void (* warp_pointer) (MetaBackend *backend,
|
||||||
int x,
|
int x,
|
||||||
int y);
|
int y);
|
||||||
|
|
||||||
|
void (* set_keymap) (MetaBackend *backend,
|
||||||
|
const char *layouts,
|
||||||
|
const char *variants,
|
||||||
|
const char *options);
|
||||||
|
|
||||||
|
struct xkb_keymap * (* get_keymap) (MetaBackend *backend);
|
||||||
|
|
||||||
|
void (* lock_layout_group) (MetaBackend *backend,
|
||||||
|
guint idx);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* META_BACKEND_PRIVATE_H */
|
#endif /* META_BACKEND_PRIVATE_H */
|
||||||
|
@ -200,6 +200,29 @@ meta_backend_warp_pointer (MetaBackend *backend,
|
|||||||
META_BACKEND_GET_CLASS (backend)->warp_pointer (backend, x, y);
|
META_BACKEND_GET_CLASS (backend)->warp_pointer (backend, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_backend_set_keymap (MetaBackend *backend,
|
||||||
|
const char *layouts,
|
||||||
|
const char *variants,
|
||||||
|
const char *options)
|
||||||
|
{
|
||||||
|
META_BACKEND_GET_CLASS (backend)->set_keymap (backend, layouts, variants, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct xkb_keymap *
|
||||||
|
meta_backend_get_keymap (MetaBackend *backend)
|
||||||
|
|
||||||
|
{
|
||||||
|
return META_BACKEND_GET_CLASS (backend)->get_keymap (backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_backend_lock_layout_group (MetaBackend *backend,
|
||||||
|
guint idx)
|
||||||
|
{
|
||||||
|
META_BACKEND_GET_CLASS (backend)->lock_layout_group (backend, idx);
|
||||||
|
}
|
||||||
|
|
||||||
static GType
|
static GType
|
||||||
get_backend_type (void)
|
get_backend_type (void)
|
||||||
{
|
{
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
#include <meta/meta-idle-monitor.h>
|
#include <meta/meta-idle-monitor.h>
|
||||||
#include "meta-monitor-manager.h"
|
#include "meta-monitor-manager.h"
|
||||||
#include "meta-cursor-renderer.h"
|
#include "meta-cursor-renderer.h"
|
||||||
@ -54,6 +56,16 @@ void meta_backend_warp_pointer (MetaBackend *backend,
|
|||||||
int x,
|
int x,
|
||||||
int y);
|
int y);
|
||||||
|
|
||||||
|
void meta_backend_set_keymap (MetaBackend *backend,
|
||||||
|
const char *layouts,
|
||||||
|
const char *variants,
|
||||||
|
const char *options);
|
||||||
|
|
||||||
|
struct xkb_keymap * meta_backend_get_keymap (MetaBackend *backend);
|
||||||
|
|
||||||
|
void meta_backend_lock_layout_group (MetaBackend *backend,
|
||||||
|
guint idx);
|
||||||
|
|
||||||
void meta_clutter_init (void);
|
void meta_clutter_init (void);
|
||||||
|
|
||||||
#endif /* META_BACKEND_H */
|
#endif /* META_BACKEND_H */
|
||||||
|
@ -188,6 +188,49 @@ meta_backend_native_warp_pointer (MetaBackend *backend,
|
|||||||
clutter_evdev_warp_pointer (device, time_, x, y);
|
clutter_evdev_warp_pointer (device, time_, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_backend_native_set_keymap (MetaBackend *backend,
|
||||||
|
const char *layouts,
|
||||||
|
const char *variants,
|
||||||
|
const char *options)
|
||||||
|
{
|
||||||
|
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||||
|
struct xkb_rule_names names;
|
||||||
|
struct xkb_keymap *keymap;
|
||||||
|
struct xkb_context *context;
|
||||||
|
|
||||||
|
names.rules = DEFAULT_XKB_RULES_FILE;
|
||||||
|
names.model = DEFAULT_XKB_MODEL;
|
||||||
|
names.layout = layouts;
|
||||||
|
names.variant = variants;
|
||||||
|
names.options = options;
|
||||||
|
|
||||||
|
context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
|
||||||
|
keymap = xkb_keymap_new_from_names (context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
xkb_context_unref (context);
|
||||||
|
|
||||||
|
clutter_evdev_set_keyboard_map (manager, keymap);
|
||||||
|
|
||||||
|
/* FIXME: emit keymap changed signal */
|
||||||
|
|
||||||
|
xkb_keymap_unref (keymap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct xkb_keymap *
|
||||||
|
meta_backend_native_get_keymap (MetaBackend *backend)
|
||||||
|
{
|
||||||
|
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||||
|
return clutter_evdev_get_keyboard_map (manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_backend_native_lock_layout_group (MetaBackend *backend,
|
||||||
|
guint idx)
|
||||||
|
{
|
||||||
|
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||||
|
clutter_evdev_set_keyboard_layout_index (manager, idx);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_backend_native_class_init (MetaBackendNativeClass *klass)
|
meta_backend_native_class_init (MetaBackendNativeClass *klass)
|
||||||
{
|
{
|
||||||
@ -199,6 +242,9 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
|
|||||||
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
|
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
|
||||||
|
|
||||||
backend_class->warp_pointer = meta_backend_native_warp_pointer;
|
backend_class->warp_pointer = meta_backend_native_warp_pointer;
|
||||||
|
backend_class->set_keymap = meta_backend_native_set_keymap;
|
||||||
|
backend_class->get_keymap = meta_backend_native_get_keymap;
|
||||||
|
backend_class->lock_layout_group = meta_backend_native_lock_layout_group;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -24,11 +24,18 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "meta-backend-x11.h"
|
#include "meta-backend-x11.h"
|
||||||
|
|
||||||
#include <clutter/x11/clutter-x11.h>
|
#include <clutter/x11/clutter-x11.h>
|
||||||
|
|
||||||
#include <X11/extensions/sync.h>
|
#include <X11/extensions/sync.h>
|
||||||
|
#include <X11/XKBlib.h>
|
||||||
|
#include <X11/extensions/XKBrules.h>
|
||||||
|
#include <X11/Xlib-xcb.h>
|
||||||
|
#include <xkbcommon/xkbcommon-x11.h>
|
||||||
|
|
||||||
#include "meta-idle-monitor-xsync.h"
|
#include "meta-idle-monitor-xsync.h"
|
||||||
#include "meta-monitor-manager-xrandr.h"
|
#include "meta-monitor-manager-xrandr.h"
|
||||||
@ -43,6 +50,7 @@ struct _MetaBackendX11Private
|
|||||||
{
|
{
|
||||||
/* The host X11 display */
|
/* The host X11 display */
|
||||||
Display *xdisplay;
|
Display *xdisplay;
|
||||||
|
xcb_connection_t *xcb;
|
||||||
GSource *source;
|
GSource *source;
|
||||||
|
|
||||||
int xsync_event_base;
|
int xsync_event_base;
|
||||||
@ -52,6 +60,9 @@ struct _MetaBackendX11Private
|
|||||||
int xinput_event_base;
|
int xinput_event_base;
|
||||||
int xinput_error_base;
|
int xinput_error_base;
|
||||||
Time latest_evtime;
|
Time latest_evtime;
|
||||||
|
|
||||||
|
uint8_t xkb_event_base;
|
||||||
|
uint8_t xkb_error_base;
|
||||||
};
|
};
|
||||||
typedef struct _MetaBackendX11Private MetaBackendX11Private;
|
typedef struct _MetaBackendX11Private MetaBackendX11Private;
|
||||||
|
|
||||||
@ -320,6 +331,17 @@ meta_backend_x11_post_init (MetaBackend *backend)
|
|||||||
|
|
||||||
take_touch_grab (backend);
|
take_touch_grab (backend);
|
||||||
|
|
||||||
|
priv->xcb = XGetXCBConnection (priv->xdisplay);
|
||||||
|
if (!xkb_x11_setup_xkb_extension (priv->xcb,
|
||||||
|
XKB_X11_MIN_MAJOR_XKB_VERSION,
|
||||||
|
XKB_X11_MIN_MINOR_XKB_VERSION,
|
||||||
|
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS,
|
||||||
|
NULL, NULL,
|
||||||
|
&priv->xkb_event_base,
|
||||||
|
&priv->xkb_error_base))
|
||||||
|
meta_fatal ("X server doesn't have the XKB extension, version %d.%d or newer\n",
|
||||||
|
XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION);
|
||||||
|
|
||||||
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
|
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,6 +435,163 @@ meta_backend_x11_warp_pointer (MetaBackend *backend,
|
|||||||
x, y);
|
x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_xkbrf_var_defs (Display *xdisplay,
|
||||||
|
const char *layouts,
|
||||||
|
const char *variants,
|
||||||
|
const char *options,
|
||||||
|
char **rules_p,
|
||||||
|
XkbRF_VarDefsRec *var_defs)
|
||||||
|
{
|
||||||
|
char *rules = NULL;
|
||||||
|
|
||||||
|
/* Get it from the X property or fallback on defaults */
|
||||||
|
if (!XkbRF_GetNamesProp (xdisplay, &rules, var_defs) || !rules)
|
||||||
|
{
|
||||||
|
rules = strdup (DEFAULT_XKB_RULES_FILE);
|
||||||
|
var_defs->model = strdup (DEFAULT_XKB_MODEL);
|
||||||
|
var_defs->layout = NULL;
|
||||||
|
var_defs->variant = NULL;
|
||||||
|
var_defs->options = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Swap in our new options... */
|
||||||
|
free (var_defs->layout);
|
||||||
|
var_defs->layout = strdup (layouts);
|
||||||
|
free (var_defs->variant);
|
||||||
|
var_defs->variant = strdup (variants);
|
||||||
|
free (var_defs->options);
|
||||||
|
var_defs->options = strdup (options);
|
||||||
|
|
||||||
|
/* Sometimes, the property is a file path, and sometimes it's
|
||||||
|
not. Normalize it so it's always a file path. */
|
||||||
|
if (rules[0] == '/')
|
||||||
|
*rules_p = g_strdup (rules);
|
||||||
|
else
|
||||||
|
*rules_p = g_build_filename (XKB_BASE, "rules", rules, NULL);
|
||||||
|
|
||||||
|
free (rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_xkbrf_var_defs (XkbRF_VarDefsRec *var_defs)
|
||||||
|
{
|
||||||
|
free (var_defs->model);
|
||||||
|
free (var_defs->layout);
|
||||||
|
free (var_defs->variant);
|
||||||
|
free (var_defs->options);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_xkb_component_names (XkbComponentNamesRec *p)
|
||||||
|
{
|
||||||
|
free (p->keymap);
|
||||||
|
free (p->keycodes);
|
||||||
|
free (p->types);
|
||||||
|
free (p->compat);
|
||||||
|
free (p->symbols);
|
||||||
|
free (p->geometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
upload_xkb_description (Display *xdisplay,
|
||||||
|
const gchar *rules_file_path,
|
||||||
|
XkbRF_VarDefsRec *var_defs,
|
||||||
|
XkbComponentNamesRec *comp_names)
|
||||||
|
{
|
||||||
|
XkbDescRec *xkb_desc;
|
||||||
|
gchar *rules_file;
|
||||||
|
|
||||||
|
/* Upload it to the X server using the same method as setxkbmap */
|
||||||
|
xkb_desc = XkbGetKeyboardByName (xdisplay,
|
||||||
|
XkbUseCoreKbd,
|
||||||
|
comp_names,
|
||||||
|
XkbGBN_AllComponentsMask,
|
||||||
|
XkbGBN_AllComponentsMask &
|
||||||
|
(~XkbGBN_GeometryMask), True);
|
||||||
|
if (!xkb_desc)
|
||||||
|
{
|
||||||
|
g_warning ("Couldn't upload new XKB keyboard description");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
XkbFreeKeyboard (xkb_desc, 0, True);
|
||||||
|
|
||||||
|
rules_file = g_path_get_basename (rules_file_path);
|
||||||
|
|
||||||
|
if (!XkbRF_SetNamesProp (xdisplay, rules_file, var_defs))
|
||||||
|
g_warning ("Couldn't update the XKB root window property");
|
||||||
|
|
||||||
|
g_free (rules_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_backend_x11_set_keymap (MetaBackend *backend,
|
||||||
|
const char *layouts,
|
||||||
|
const char *variants,
|
||||||
|
const char *options)
|
||||||
|
{
|
||||||
|
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||||
|
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||||
|
XkbRF_RulesRec *xkb_rules;
|
||||||
|
XkbRF_VarDefsRec xkb_var_defs = { 0 };
|
||||||
|
gchar *rules_file_path;
|
||||||
|
|
||||||
|
get_xkbrf_var_defs (priv->xdisplay,
|
||||||
|
layouts,
|
||||||
|
variants,
|
||||||
|
options,
|
||||||
|
&rules_file_path,
|
||||||
|
&xkb_var_defs);
|
||||||
|
|
||||||
|
xkb_rules = XkbRF_Load (rules_file_path, NULL, True, True);
|
||||||
|
if (xkb_rules)
|
||||||
|
{
|
||||||
|
XkbComponentNamesRec xkb_comp_names = { 0 };
|
||||||
|
|
||||||
|
XkbRF_GetComponents (xkb_rules, &xkb_var_defs, &xkb_comp_names);
|
||||||
|
upload_xkb_description (priv->xdisplay, rules_file_path, &xkb_var_defs, &xkb_comp_names);
|
||||||
|
|
||||||
|
free_xkb_component_names (&xkb_comp_names);
|
||||||
|
XkbRF_Free (xkb_rules, True);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_warning ("Couldn't load XKB rules");
|
||||||
|
}
|
||||||
|
|
||||||
|
free_xkbrf_var_defs (&xkb_var_defs);
|
||||||
|
g_free (rules_file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct xkb_keymap *
|
||||||
|
meta_backend_x11_get_keymap (MetaBackend *backend)
|
||||||
|
{
|
||||||
|
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||||
|
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||||
|
struct xkb_keymap *keymap;
|
||||||
|
struct xkb_context *context;
|
||||||
|
|
||||||
|
context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
|
||||||
|
keymap = xkb_x11_keymap_new_from_device (context,
|
||||||
|
priv->xcb,
|
||||||
|
xkb_x11_get_core_keyboard_device_id (priv->xcb),
|
||||||
|
XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
xkb_context_unref (context);
|
||||||
|
|
||||||
|
return keymap;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_backend_x11_lock_layout_group (MetaBackend *backend,
|
||||||
|
guint idx)
|
||||||
|
{
|
||||||
|
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||||
|
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||||
|
|
||||||
|
XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, idx);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
||||||
{
|
{
|
||||||
@ -426,6 +605,9 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
|||||||
backend_class->grab_device = meta_backend_x11_grab_device;
|
backend_class->grab_device = meta_backend_x11_grab_device;
|
||||||
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
|
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
|
||||||
backend_class->warp_pointer = meta_backend_x11_warp_pointer;
|
backend_class->warp_pointer = meta_backend_x11_warp_pointer;
|
||||||
|
backend_class->set_keymap = meta_backend_x11_set_keymap;
|
||||||
|
backend_class->get_keymap = meta_backend_x11_get_keymap;
|
||||||
|
backend_class->lock_layout_group = meta_backend_x11_lock_layout_group;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
x
Reference in New Issue
Block a user