Borrow XKB keyboard mapping change logic from Caribou.
This commit is contained in:
@ -179,6 +179,8 @@ main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
client = eekboard_client_new (connection);
|
client = eekboard_client_new (connection);
|
||||||
|
g_object_unref (connection);
|
||||||
|
|
||||||
if (client == NULL) {
|
if (client == NULL) {
|
||||||
g_printerr ("Can't create a client\n");
|
g_printerr ("Can't create a client\n");
|
||||||
exit (1);
|
exit (1);
|
||||||
@ -198,6 +200,7 @@ main (int argc, char **argv)
|
|||||||
else {
|
else {
|
||||||
g_printerr ("Unknown focus listener \"%s\". "
|
g_printerr ("Unknown focus listener \"%s\". "
|
||||||
"Try \"atspi\" or \"ibus\"\n", focus_listener);
|
"Try \"atspi\" or \"ibus\"\n", focus_listener);
|
||||||
|
g_object_unref (client);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -212,22 +215,26 @@ main (int argc, char **argv)
|
|||||||
if (accessibility_enabled) {
|
if (accessibility_enabled) {
|
||||||
if (atspi_init () != 0) {
|
if (atspi_init () != 0) {
|
||||||
g_printerr ("Can't init AT-SPI 2\n");
|
g_printerr ("Can't init AT-SPI 2\n");
|
||||||
|
g_object_unref (client);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (focus == FOCUS_ATSPI &&
|
if (focus == FOCUS_ATSPI &&
|
||||||
!eekboard_client_enable_atspi_focus (client)) {
|
!eekboard_client_enable_atspi_focus (client)) {
|
||||||
g_printerr ("Can't register AT-SPI focus change event listeners\n");
|
g_printerr ("Can't register AT-SPI focus change event listeners\n");
|
||||||
|
g_object_unref (client);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt_keystroke &&
|
if (opt_keystroke &&
|
||||||
!eekboard_client_enable_atspi_keystroke (client)) {
|
!eekboard_client_enable_atspi_keystroke (client)) {
|
||||||
g_printerr ("Can't register AT-SPI keystroke event listeners\n");
|
g_printerr ("Can't register AT-SPI keystroke event listeners\n");
|
||||||
|
g_object_unref (client);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g_printerr ("Desktop accessibility support is disabled\n");
|
g_printerr ("Desktop accessibility support is disabled\n");
|
||||||
|
g_object_unref (client);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,6 +247,7 @@ main (int argc, char **argv)
|
|||||||
if (focus == FOCUS_IBUS &&
|
if (focus == FOCUS_IBUS &&
|
||||||
!eekboard_client_enable_ibus_focus (client)) {
|
!eekboard_client_enable_ibus_focus (client)) {
|
||||||
g_printerr ("Can't register IBus focus change event listeners\n");
|
g_printerr ("Can't register IBus focus change event listeners\n");
|
||||||
|
g_object_unref (client);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -247,24 +255,28 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
if (opt_use_system_layout && (opt_keyboard || opt_model || opt_layouts || opt_options)) {
|
if (opt_use_system_layout && (opt_keyboard || opt_model || opt_layouts || opt_options)) {
|
||||||
g_printerr ("Can't use --use-system-layout option with keyboard options\n");
|
g_printerr ("Can't use --use-system-layout option with keyboard options\n");
|
||||||
|
g_object_unref (client);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt_use_system_layout) {
|
if (!eekboard_client_enable_xkl (client)) {
|
||||||
if (!eekboard_client_enable_xkl (client)) {
|
g_printerr ("Can't register xklavier event listeners\n");
|
||||||
g_printerr ("Can't register xklavier event listeners\n");
|
g_object_unref (client);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
} else if (opt_model || opt_layouts || opt_options) {
|
|
||||||
if (!eekboard_client_set_xkl_config (client,
|
if (opt_use_system_layout || opt_model || opt_layouts || opt_options) {
|
||||||
opt_model,
|
if (!eekboard_client_load_keyboard_from_xkl (client,
|
||||||
opt_layouts,
|
opt_model,
|
||||||
opt_options)) {
|
opt_layouts,
|
||||||
g_printerr ("Can't set xklavier config\n");
|
opt_options)) {
|
||||||
|
g_printerr ("Can't load keyboard from xklavier config\n");
|
||||||
|
g_object_unref (client);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
gchar *file;
|
gchar *file;
|
||||||
|
gboolean success;
|
||||||
|
|
||||||
if (!opt_keyboard)
|
if (!opt_keyboard)
|
||||||
opt_keyboard = DEFAULT_LAYOUT;
|
opt_keyboard = DEFAULT_LAYOUT;
|
||||||
@ -273,17 +285,19 @@ main (int argc, char **argv)
|
|||||||
file = g_strdup (opt_keyboard);
|
file = g_strdup (opt_keyboard);
|
||||||
else
|
else
|
||||||
file = g_strdup_printf ("%s/%s.xml", KEYBOARDDIR, opt_keyboard);
|
file = g_strdup_printf ("%s/%s.xml", KEYBOARDDIR, opt_keyboard);
|
||||||
if (!eekboard_client_load_keyboard_from_file (client, file)) {
|
success = eekboard_client_load_keyboard_from_file (client, file);
|
||||||
|
g_free (file);
|
||||||
|
if (!success) {
|
||||||
g_printerr ("Can't load keyboard file %s\n", file);
|
g_printerr ("Can't load keyboard file %s\n", file);
|
||||||
g_free (file);
|
g_object_unref (client);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
g_free (file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_XTEST
|
#ifdef HAVE_XTEST
|
||||||
if (!eekboard_client_enable_xtest (client)) {
|
if (!eekboard_client_enable_xtest (client)) {
|
||||||
g_printerr ("Can't init xtest\n");
|
g_printerr ("Can't init xtest\n");
|
||||||
|
g_object_unref (client);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_XTEST */
|
#endif /* HAVE_XTEST */
|
||||||
@ -310,6 +324,7 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
g_main_loop_run (loop);
|
g_main_loop_run (loop);
|
||||||
g_main_loop_unref (loop);
|
g_main_loop_unref (loop);
|
||||||
|
g_object_unref (client);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
262
src/client.c
262
src/client.c
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#ifdef HAVE_XTEST
|
#ifdef HAVE_XTEST
|
||||||
#include <X11/extensions/XTest.h>
|
#include <X11/extensions/XTest.h>
|
||||||
|
#include <X11/XKBlib.h>
|
||||||
#endif /* HAVE_XTEST */
|
#endif /* HAVE_XTEST */
|
||||||
|
|
||||||
#ifdef HAVE_IBUS
|
#ifdef HAVE_IBUS
|
||||||
@ -67,6 +68,8 @@ struct _EekboardClient {
|
|||||||
GdkDisplay *display;
|
GdkDisplay *display;
|
||||||
XklEngine *xkl_engine;
|
XklEngine *xkl_engine;
|
||||||
XklConfigRegistry *xkl_config_registry;
|
XklConfigRegistry *xkl_config_registry;
|
||||||
|
gboolean use_xkl_layout;
|
||||||
|
gint group;
|
||||||
|
|
||||||
gulong xkl_config_changed_handler;
|
gulong xkl_config_changed_handler;
|
||||||
gulong xkl_state_changed_handler;
|
gulong xkl_state_changed_handler;
|
||||||
@ -88,6 +91,9 @@ struct _EekboardClient {
|
|||||||
|
|
||||||
#ifdef HAVE_XTEST
|
#ifdef HAVE_XTEST
|
||||||
KeyCode modifier_keycodes[8];
|
KeyCode modifier_keycodes[8];
|
||||||
|
KeyCode reserved_keycode;
|
||||||
|
KeySym reserved_keysym;
|
||||||
|
XkbDescRec *xkb;
|
||||||
#endif /* HAVE_XTEST */
|
#endif /* HAVE_XTEST */
|
||||||
|
|
||||||
GSettings *settings;
|
GSettings *settings;
|
||||||
@ -121,14 +127,24 @@ static gboolean keystroke_listener_cb (const AtspiDeviceEvent *stroke,
|
|||||||
static gboolean set_keyboard (EekboardClient *client,
|
static gboolean set_keyboard (EekboardClient *client,
|
||||||
gboolean show,
|
gboolean show,
|
||||||
EekLayout *layout);
|
EekLayout *layout);
|
||||||
static gboolean set_xkl_keyboard (EekboardClient *client,
|
static gboolean set_keyboard_from_xkl (EekboardClient *client,
|
||||||
gboolean show,
|
gboolean show,
|
||||||
const gchar *model,
|
const gchar *model,
|
||||||
const gchar *layouts,
|
const gchar *layouts,
|
||||||
const gchar *options);
|
const gchar *options);
|
||||||
#ifdef HAVE_XTEST
|
#ifdef HAVE_XTEST
|
||||||
static void update_modifier_keycodes
|
static void update_modifier_keycodes
|
||||||
(EekboardClient *client);
|
(EekboardClient *client);
|
||||||
|
static gboolean get_keycode_for_keysym
|
||||||
|
(EekboardClient *client,
|
||||||
|
guint keysym,
|
||||||
|
guint *keycode,
|
||||||
|
guint *modifiers);
|
||||||
|
static gboolean get_keycode_for_keysym_replace
|
||||||
|
(EekboardClient *client,
|
||||||
|
guint keysym,
|
||||||
|
guint *keycode,
|
||||||
|
guint *modifiers);
|
||||||
#endif /* HAVE_XTEST */
|
#endif /* HAVE_XTEST */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -311,23 +327,25 @@ eekboard_client_init (EekboardClient *client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
eekboard_client_set_xkl_config (EekboardClient *client,
|
eekboard_client_load_keyboard_from_xkl (EekboardClient *client,
|
||||||
const gchar *model,
|
const gchar *model,
|
||||||
const gchar *layouts,
|
const gchar *layouts,
|
||||||
const gchar *options)
|
const gchar *options)
|
||||||
{
|
{
|
||||||
|
client->use_xkl_layout = TRUE;
|
||||||
|
|
||||||
#if ENABLE_FOCUS_LISTENER
|
#if ENABLE_FOCUS_LISTENER
|
||||||
return set_xkl_keyboard (client,
|
return set_keyboard_from_xkl (client,
|
||||||
!client->follows_focus,
|
!client->follows_focus,
|
||||||
model,
|
model,
|
||||||
layouts,
|
layouts,
|
||||||
options);
|
options);
|
||||||
#else /* ENABLE_FOCUS_LISTENER */
|
#else /* ENABLE_FOCUS_LISTENER */
|
||||||
return set_xkl_keyboard (client,
|
return set_keyboard_from_xkl (client,
|
||||||
TRUE,
|
TRUE,
|
||||||
model,
|
model,
|
||||||
layouts,
|
layouts,
|
||||||
options);
|
options);
|
||||||
#endif /* !ENABLE_FOCUS_LISTENER */
|
#endif /* !ENABLE_FOCUS_LISTENER */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,22 +383,18 @@ eekboard_client_enable_xkl (EekboardClient *client)
|
|||||||
(GdkFilterFunc) filter_xkl_event,
|
(GdkFilterFunc) filter_xkl_event,
|
||||||
client);
|
client);
|
||||||
|
|
||||||
|
client->use_xkl_layout = FALSE;
|
||||||
|
|
||||||
xkl_engine_start_listen (client->xkl_engine, XKLL_TRACK_KEYBOARD_STATE);
|
xkl_engine_start_listen (client->xkl_engine, XKLL_TRACK_KEYBOARD_STATE);
|
||||||
|
|
||||||
#if ENABLE_FOCUS_LISTENER
|
return TRUE;
|
||||||
return set_xkl_keyboard (client,
|
|
||||||
!client->follows_focus,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
#else /* ENABLE_FOCUS_LISTENER */
|
|
||||||
return set_xkl_keyboard (client, TRUE, NULL, NULL, NULL);
|
|
||||||
#endif /* !ENABLE_FOCUS_LISTENER */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
eekboard_client_disable_xkl (EekboardClient *client)
|
eekboard_client_disable_xkl (EekboardClient *client)
|
||||||
{
|
{
|
||||||
|
client->use_xkl_layout = FALSE;
|
||||||
|
|
||||||
if (client->xkl_engine)
|
if (client->xkl_engine)
|
||||||
xkl_engine_stop_listen (client->xkl_engine, XKLL_TRACK_KEYBOARD_STATE);
|
xkl_engine_stop_listen (client->xkl_engine, XKLL_TRACK_KEYBOARD_STATE);
|
||||||
if (g_signal_handler_is_connected (client->xkl_engine,
|
if (g_signal_handler_is_connected (client->xkl_engine,
|
||||||
@ -665,8 +679,8 @@ EekboardClient *
|
|||||||
eekboard_client_new (GDBusConnection *connection)
|
eekboard_client_new (GDBusConnection *connection)
|
||||||
{
|
{
|
||||||
EekboardClient *client = g_object_new (EEKBOARD_TYPE_CLIENT,
|
EekboardClient *client = g_object_new (EEKBOARD_TYPE_CLIENT,
|
||||||
"connection", connection,
|
"connection", connection,
|
||||||
NULL);
|
NULL);
|
||||||
if (client->context)
|
if (client->context)
|
||||||
return client;
|
return client;
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -691,12 +705,14 @@ on_xkl_config_changed (XklEngine *xklengine,
|
|||||||
EekboardClient *client = user_data;
|
EekboardClient *client = user_data;
|
||||||
gboolean retval;
|
gboolean retval;
|
||||||
|
|
||||||
retval = set_xkl_keyboard (client, FALSE, NULL, NULL, NULL);
|
if (client->use_xkl_layout) {
|
||||||
g_return_if_fail (retval);
|
retval = set_keyboard_from_xkl (client, FALSE, NULL, NULL, NULL);
|
||||||
|
g_return_if_fail (retval);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_FAKEKEY
|
#ifdef HAVE_XTEST
|
||||||
update_modifier_keycodes (client);
|
update_modifier_keycodes (client);
|
||||||
#endif /* HAVE_FAKEKEY */
|
#endif /* HAVE_XTEST */
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -726,11 +742,11 @@ set_keyboard (EekboardClient *client,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
set_xkl_keyboard (EekboardClient *client,
|
set_keyboard_from_xkl (EekboardClient *client,
|
||||||
gboolean show,
|
gboolean show,
|
||||||
const gchar *model,
|
const gchar *model,
|
||||||
const gchar *layouts,
|
const gchar *layouts,
|
||||||
const gchar *options)
|
const gchar *options)
|
||||||
{
|
{
|
||||||
EekLayout *layout;
|
EekLayout *layout;
|
||||||
gboolean retval;
|
gboolean retval;
|
||||||
@ -793,10 +809,13 @@ on_xkl_state_changed (XklEngine *xklengine,
|
|||||||
EekboardClient *client = user_data;
|
EekboardClient *client = user_data;
|
||||||
|
|
||||||
if (type == GROUP_CHANGED && client->keyboard) {
|
if (type == GROUP_CHANGED && client->keyboard) {
|
||||||
gint group = eek_element_get_group (EEK_ELEMENT(client->keyboard));
|
if (client->use_xkl_layout) {
|
||||||
if (group != value) {
|
gint group = eek_element_get_group (EEK_ELEMENT(client->keyboard));
|
||||||
eekboard_context_set_group (client->context, value, NULL);
|
if (group != value) {
|
||||||
|
eekboard_context_set_group (client->context, value, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
client->group = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -841,13 +860,20 @@ send_fake_key_event (EekboardClient *client,
|
|||||||
xkeysym = eek_keysym_get_xkeysym (EEK_KEYSYM(symbol));
|
xkeysym = eek_keysym_get_xkeysym (EEK_KEYSYM(symbol));
|
||||||
g_return_if_fail (xkeysym > 0);
|
g_return_if_fail (xkeysym > 0);
|
||||||
|
|
||||||
|
if (!get_keycode_for_keysym (client, xkeysym, &keycode, &modifiers)) {
|
||||||
|
g_warning ("failed to lookup X keysym %X", xkeysym);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
modifiers |= eek_keyboard_get_modifiers (client->keyboard);
|
||||||
|
|
||||||
|
send_fake_modifier_key_event (client, modifiers, is_pressed);
|
||||||
|
XSync (GDK_DISPLAY_XDISPLAY (client->display), False);
|
||||||
|
|
||||||
keycode = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (client->display),
|
keycode = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (client->display),
|
||||||
xkeysym);
|
xkeysym);
|
||||||
g_return_if_fail (keycode > 0);
|
g_return_if_fail (keycode > 0);
|
||||||
|
|
||||||
modifiers = eek_keyboard_get_modifiers (client->keyboard);
|
|
||||||
send_fake_modifier_key_event (client, modifiers, is_pressed);
|
|
||||||
|
|
||||||
XTestFakeKeyEvent (GDK_DISPLAY_XDISPLAY (client->display),
|
XTestFakeKeyEvent (GDK_DISPLAY_XDISPLAY (client->display),
|
||||||
keycode,
|
keycode,
|
||||||
is_pressed,
|
is_pressed,
|
||||||
@ -862,6 +888,7 @@ on_key_pressed (EekKeyboard *keyboard,
|
|||||||
{
|
{
|
||||||
EekboardClient *client = user_data;
|
EekboardClient *client = user_data;
|
||||||
send_fake_key_event (client, key, TRUE);
|
send_fake_key_event (client, key, TRUE);
|
||||||
|
send_fake_key_event (client, key, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -869,8 +896,6 @@ on_key_released (EekKeyboard *keyboard,
|
|||||||
EekKey *key,
|
EekKey *key,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
EekboardClient *client = user_data;
|
|
||||||
send_fake_key_event (client, key, FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -892,10 +917,130 @@ update_modifier_keycodes (EekboardClient *client)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The following functions for keyboard mapping change are direct
|
||||||
|
translation of the code in Caribou (in libcaribou/xadapter.vala):
|
||||||
|
|
||||||
|
- get_reserved_keycode
|
||||||
|
- reset_reserved
|
||||||
|
- get_keycode_for_keysym_replace (Caribou: replace_keycode)
|
||||||
|
- get_keycode_for_keysym_best (Caribou: best_keycode_keyval_match)
|
||||||
|
- get_keycode_for_keysym (Caribou: keycode_for_keyval)
|
||||||
|
*/
|
||||||
|
static guint
|
||||||
|
get_reserved_keycode (EekboardClient *client)
|
||||||
|
{
|
||||||
|
Display *display = GDK_DISPLAY_XDISPLAY (client->display);
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
for (i = client->xkb->max_key_code; i >= client->xkb->min_key_code; --i) {
|
||||||
|
if (client->xkb->map->key_sym_map[i].kt_index[0] == XkbOneLevelIndex) {
|
||||||
|
if (XKeycodeToKeysym (display, i, 0) != 0) {
|
||||||
|
gdk_error_trap_push ();
|
||||||
|
XGrabKey (display, i, 0,
|
||||||
|
gdk_x11_get_default_root_xwindow (), TRUE,
|
||||||
|
GrabModeSync, GrabModeSync);
|
||||||
|
XFlush (display);
|
||||||
|
XUngrabKey (display, i, 0,
|
||||||
|
gdk_x11_get_default_root_xwindow ());
|
||||||
|
if (gdk_error_trap_pop () == 0)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return XKeysymToKeycode (display, 0x0023); /* XK_numbersign */
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
reset_reserved (gpointer user_data)
|
||||||
|
{
|
||||||
|
EekboardClient *client = user_data;
|
||||||
|
guint keycode, modifiers;
|
||||||
|
|
||||||
|
get_keycode_for_keysym_replace (client,
|
||||||
|
client->reserved_keysym,
|
||||||
|
&keycode,
|
||||||
|
&modifiers);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
get_keycode_for_keysym_replace (EekboardClient *client,
|
||||||
|
guint keysym,
|
||||||
|
guint *keycode,
|
||||||
|
guint *modifiers)
|
||||||
|
{
|
||||||
|
Display *display = GDK_DISPLAY_XDISPLAY (client->display);
|
||||||
|
guint offset;
|
||||||
|
if (client->reserved_keycode == 0) {
|
||||||
|
client->reserved_keycode = get_reserved_keycode (client);
|
||||||
|
client->reserved_keysym =
|
||||||
|
XKeycodeToKeysym (display,
|
||||||
|
client->reserved_keycode,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
XFlush (display);
|
||||||
|
|
||||||
|
offset = client->xkb->map->key_sym_map[client->reserved_keycode].offset;
|
||||||
|
client->xkb->map->syms[offset] = keysym;
|
||||||
|
XkbSetMap (display,
|
||||||
|
XkbAllMapComponentsMask,
|
||||||
|
client->xkb);
|
||||||
|
XFlush (display);
|
||||||
|
|
||||||
|
*keycode = client->reserved_keycode;
|
||||||
|
*modifiers = 0;
|
||||||
|
|
||||||
|
if (keysym != client->reserved_keysym)
|
||||||
|
g_timeout_add (500, reset_reserved, client);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
get_keycode_for_keysym_best (EekboardClient *client,
|
||||||
|
guint keysym,
|
||||||
|
guint *keycode,
|
||||||
|
guint *modifiers)
|
||||||
|
{
|
||||||
|
GdkKeymap *keymap = gdk_keymap_get_default ();
|
||||||
|
GdkKeymapKey *keys, *best_match;
|
||||||
|
gint n_keys, i;
|
||||||
|
|
||||||
|
if (!gdk_keymap_get_entries_for_keyval (keymap, keysym, &keys, &n_keys))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < n_keys; i++)
|
||||||
|
if (keys[i].group == client->group)
|
||||||
|
best_match = &keys[i];
|
||||||
|
|
||||||
|
*keycode = best_match->keycode;
|
||||||
|
*modifiers = best_match->level == 1 ? EEK_SHIFT_MASK : 0;
|
||||||
|
|
||||||
|
g_free (keys);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
get_keycode_for_keysym (EekboardClient *client,
|
||||||
|
guint keysym,
|
||||||
|
guint *keycode,
|
||||||
|
guint *modifiers)
|
||||||
|
{
|
||||||
|
if (get_keycode_for_keysym_best (client, keysym, keycode, modifiers))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (get_keycode_for_keysym_replace (client, keysym, keycode, modifiers))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
eekboard_client_enable_xtest (EekboardClient *client)
|
eekboard_client_enable_xtest (EekboardClient *client)
|
||||||
{
|
{
|
||||||
int event_base, error_base, major_version, minor_version;
|
int opcode, event_base, error_base, major_version, minor_version;
|
||||||
|
|
||||||
if (!client->display) {
|
if (!client->display) {
|
||||||
client->display = gdk_display_get_default ();
|
client->display = gdk_display_get_default ();
|
||||||
@ -908,7 +1053,21 @@ eekboard_client_enable_xtest (EekboardClient *client)
|
|||||||
g_warning ("XTest extension is not available");
|
g_warning ("XTest extension is not available");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!XkbQueryExtension (GDK_DISPLAY_XDISPLAY (client->display),
|
||||||
|
&opcode, &event_base, &error_base,
|
||||||
|
&major_version, &minor_version)) {
|
||||||
|
g_warning ("Xkb extension is not available");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!client->xkb)
|
||||||
|
client->xkb = XkbGetKeyboard (GDK_DISPLAY_XDISPLAY (client->display),
|
||||||
|
XkbGBN_AllComponentsMask,
|
||||||
|
XkbUseCoreKbd);
|
||||||
|
g_assert (client->xkb);
|
||||||
|
|
||||||
|
client->reserved_keycode = 0;
|
||||||
update_modifier_keycodes (client);
|
update_modifier_keycodes (client);
|
||||||
|
|
||||||
client->key_pressed_handler =
|
client->key_pressed_handler =
|
||||||
@ -924,6 +1083,11 @@ eekboard_client_enable_xtest (EekboardClient *client)
|
|||||||
void
|
void
|
||||||
eekboard_client_disable_xtest (EekboardClient *client)
|
eekboard_client_disable_xtest (EekboardClient *client)
|
||||||
{
|
{
|
||||||
|
if (client->xkb) {
|
||||||
|
XkbFreeKeyboard (client->xkb, 0, TRUE); /* free_all = TRUE */
|
||||||
|
client->xkb = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_signal_handler_is_connected (client->keyboard,
|
if (g_signal_handler_is_connected (client->keyboard,
|
||||||
client->key_pressed_handler))
|
client->key_pressed_handler))
|
||||||
g_signal_handler_disconnect (client->keyboard,
|
g_signal_handler_disconnect (client->keyboard,
|
||||||
|
|||||||
36
src/client.h
36
src/client.h
@ -31,36 +31,38 @@ G_BEGIN_DECLS
|
|||||||
|
|
||||||
typedef struct _EekboardClient EekboardClient;
|
typedef struct _EekboardClient EekboardClient;
|
||||||
|
|
||||||
EekboardClient * eekboard_client_new (GDBusConnection *connection);
|
EekboardClient * eekboard_client_new (GDBusConnection *connection);
|
||||||
|
|
||||||
gboolean eekboard_client_load_keyboard_from_file
|
gboolean eekboard_client_load_keyboard_from_file
|
||||||
(EekboardClient *client,
|
(EekboardClient *client,
|
||||||
const gchar *file);
|
const gchar *file);
|
||||||
gboolean eekboard_client_set_xkl_config (EekboardClient *client,
|
|
||||||
const gchar *model,
|
|
||||||
const gchar *layouts,
|
|
||||||
const gchar *options);
|
|
||||||
|
|
||||||
gboolean eekboard_client_enable_xkl (EekboardClient *client);
|
gboolean eekboard_client_load_keyboard_from_xkl
|
||||||
void eekboard_client_disable_xkl (EekboardClient *client);
|
(EekboardClient *client,
|
||||||
|
const gchar *model,
|
||||||
|
const gchar *layouts,
|
||||||
|
const gchar *options);
|
||||||
|
|
||||||
|
gboolean eekboard_client_enable_xkl (EekboardClient *client);
|
||||||
|
void eekboard_client_disable_xkl (EekboardClient *client);
|
||||||
|
|
||||||
gboolean eekboard_client_enable_atspi_focus
|
gboolean eekboard_client_enable_atspi_focus
|
||||||
(EekboardClient *client);
|
(EekboardClient *client);
|
||||||
void eekboard_client_disable_atspi_focus
|
void eekboard_client_disable_atspi_focus
|
||||||
(EekboardClient *client);
|
(EekboardClient *client);
|
||||||
|
|
||||||
gboolean eekboard_client_enable_atspi_keystroke
|
gboolean eekboard_client_enable_atspi_keystroke
|
||||||
(EekboardClient *client);
|
(EekboardClient *client);
|
||||||
void eekboard_client_disable_atspi_keystroke
|
void eekboard_client_disable_atspi_keystroke
|
||||||
(EekboardClient *client);
|
(EekboardClient *client);
|
||||||
|
|
||||||
gboolean eekboard_client_enable_xtest (EekboardClient *client);
|
gboolean eekboard_client_enable_xtest (EekboardClient *client);
|
||||||
void eekboard_client_disable_xtest (EekboardClient *client);
|
void eekboard_client_disable_xtest (EekboardClient *client);
|
||||||
|
|
||||||
gboolean eekboard_client_enable_ibus_focus
|
gboolean eekboard_client_enable_ibus_focus
|
||||||
(EekboardClient *client);
|
(EekboardClient *client);
|
||||||
void eekboard_client_disable_ibus_focus
|
void eekboard_client_disable_ibus_focus
|
||||||
(EekboardClient *client);
|
(EekboardClient *client);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* EEKBOARD_CLIENT_H */
|
#endif /* EEKBOARD_CLIENT_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user