diff --git a/README b/README index c74b19dd..1770da39 100644 --- a/README +++ b/README @@ -8,7 +8,7 @@ tools to implement desktop virtual keyboards. ** Dependencies REQUIRED: GLib2, GTK, PangoCairo, libxklavier, libcroco -OPTIONAL: fakekey, at-spi2-core, Clutter, Clutter-Gtk, Python, Vala, gobject-introspection +OPTIONAL: libXtst, at-spi2-core, Clutter, Clutter-Gtk, Python, Vala, gobject-introspection ** Build from git repo diff --git a/configure.ac b/configure.ac index 4a67666f..a04cded7 100644 --- a/configure.ac +++ b/configure.ac @@ -104,21 +104,24 @@ PKG_CHECK_MODULES([LIBXKLAVIER], [libxklavier x11], , PKG_CHECK_MODULES([LIBCROCO], [libcroco-0.6], , [AC_MSG_ERROR([libcroco not found])]) -dnl use libfakekey to generate key events -AC_MSG_CHECKING([whether you enable fakekey]) -AC_ARG_ENABLE(fakekey, - AS_HELP_STRING([--enable-fakekey=no/yes], - [Enable fakekey default=yes]),, - enable_fakekey=yes) +dnl use XTest to generate key events +AC_MSG_CHECKING([whether you enable XTest]) +AC_ARG_ENABLE(xtest, + AS_HELP_STRING([--enable-xtest=no/yes], + [Enable XTest default=yes]),, + enable_xtest=yes) -if test x$enable_fakekey = xyes; then - PKG_CHECK_MODULES([FAKEKEY], [libfakekey], , enable_fakekey=no) - if test x$enable_fakekey = xyes; then - AC_DEFINE([HAVE_FAKEKEY], [1], [Define if fakekey is found]) +if test x$enable_xtest = xyes; then + PKG_CHECK_MODULES([XTEST], [xtst], , enable_xtest=no) + if test x$enable_xtest = xyes; then + AC_DEFINE([HAVE_XTEST], [1], [Define if XTest is found]) fi fi -AM_CONDITIONAL(ENABLE_FAKEKEY, [test x$enable_fakekey = xyes]) -AC_MSG_RESULT($enable_fakekey) +AM_CONDITIONAL(ENABLE_XTEST, [test x$enable_xtest = xyes]) +AC_MSG_RESULT($enable_xtest) + +focus_listeners="" +keystroke_listeners="" focus_listeners="" keystroke_listeners="" diff --git a/src/Makefile.am b/src/Makefile.am index 6ed0491d..81d29c8b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,11 +41,11 @@ eekboard_LDADD = \ $(XKB_LIBS) \ $(LIBXKLAVIER_LIBS) -if ENABLE_FAKEKEY +if ENABLE_XTEST eekboard_CFLAGS += \ - $(FAKEKEY_CFLAGS) + $(XTEST_CFLAGS) eekboard_LDADD += \ - $(FAKEKEY_LIBS) + $(XTEST_LIBS) endif if ENABLE_ATSPI diff --git a/src/client-main.c b/src/client-main.c index 3133e4db..e2bb3d12 100644 --- a/src/client-main.c +++ b/src/client-main.c @@ -277,12 +277,12 @@ main (int argc, char **argv) g_free (file); } -#ifdef HAVE_FAKEKEY - if (!eekboard_client_enable_fakekey (client)) { - g_printerr ("Can't init fakekey\n"); +#ifdef HAVE_XTEST + if (!eekboard_client_enable_xtest (client)) { + g_printerr ("Can't init xtest\n"); exit (1); } -#endif /* HAVE_FAKEKEY */ +#endif /* HAVE_XTEST */ loop = g_main_loop_new (NULL, FALSE); if (!opt_focus) { diff --git a/src/client.c b/src/client.c index 957ebbc2..98529110 100644 --- a/src/client.c +++ b/src/client.c @@ -28,9 +28,9 @@ #include -#ifdef HAVE_FAKEKEY -#include -#endif /* HAVE_FAKEKEY */ +#ifdef HAVE_XTEST +#include +#endif /* HAVE_XTEST */ #ifdef HAVE_IBUS #include @@ -42,6 +42,8 @@ #include "client.h" #include "xklutil.h" +#include + #define CSW 640 #define CSH 480 @@ -86,9 +88,9 @@ struct _EekboardClient { guint ibus_focus_message_filter; #endif /* HAVE_IBUS */ -#ifdef HAVE_FAKEKEY - FakeKey *fakekey; -#endif /* HAVE_FAKEKEY */ +#ifdef HAVE_XTEST + KeyCode modifier_keycodes[8]; +#endif /* HAVE_XTEST */ }; struct _EekboardClientClass { @@ -124,6 +126,10 @@ static gboolean set_xkl_keyboard (EekboardClient *client, const gchar *model, const gchar *layouts, const gchar *options); +#ifdef HAVE_XTEST +static void update_modifier_keycodes + (EekboardClient *client); +#endif /* HAVE_XTEST */ static void eekboard_client_set_property (GObject *object, @@ -204,9 +210,9 @@ eekboard_client_dispose (GObject *object) } #endif /* HAVE_IBUS */ -#ifdef HAVE_FAKEKEY - eekboard_client_disable_fakekey (client); -#endif /* HAVE_FAKEKEY */ +#ifdef HAVE_XTEST + eekboard_client_disable_xtest (client); +#endif /* HAVE_XTEST */ if (client->context) { if (client->eekboard) { @@ -227,12 +233,6 @@ eekboard_client_dispose (GObject *object) client->keyboard = NULL; } -#ifdef HAVE_FAKEKEY - if (client->fakekey) { - client->fakekey = NULL; - } -#endif /* HAVE_FAKEKEY */ - if (client->display) { gdk_display_close (client->display); client->display = NULL; @@ -302,9 +302,6 @@ eekboard_client_init (EekboardClient *client) client->ibus_bus = NULL; client->ibus_focus_message_filter = 0; #endif /* HAVE_IBUS */ -#ifdef HAVE_FAKEKEY - client->fakekey = NULL; -#endif /* HAVE_FAKEKEY */ } gboolean @@ -683,8 +680,7 @@ on_xkl_config_changed (XklEngine *xklengine, g_return_if_fail (retval); #ifdef HAVE_FAKEKEY - if (client->fakekey) - fakekey_reload_keysyms (client->fakekey); + update_modifier_keycodes (client); #endif /* HAVE_FAKEKEY */ } @@ -789,22 +785,59 @@ on_xkl_state_changed (XklEngine *xklengine, } } -#ifdef HAVE_FAKEKEY -G_INLINE_FUNC FakeKeyModifier -get_fakekey_modifiers (EekModifierType modifiers) +#ifdef HAVE_XTEST +static void +send_fake_modifier_key_event (EekboardClient *client, + EekModifierType modifiers, + gboolean is_pressed) { - FakeKeyModifier retval = 0; + gint i; - if (modifiers & EEK_SHIFT_MASK) - retval |= FAKEKEYMOD_SHIFT; - if (modifiers & EEK_CONTROL_MASK) - retval |= FAKEKEYMOD_CONTROL; - if (modifiers & EEK_MOD1_MASK) - retval |= FAKEKEYMOD_ALT; - if (modifiers & EEK_META_MASK) - retval |= FAKEKEYMOD_META; + for (i = 0; i < G_N_ELEMENTS(client->modifier_keycodes); i++) { + if (modifiers & (1 << i)) { + guint keycode = client->modifier_keycodes[i]; - return retval; + g_return_if_fail (keycode > 0); + + XTestFakeKeyEvent (GDK_DISPLAY_XDISPLAY (client->display), + keycode, + is_pressed, + CurrentTime); + } + } +} + +static void +send_fake_key_event (EekboardClient *client, + EekKey *key, + gboolean is_pressed) +{ + EekSymbol *symbol; + EekModifierType modifiers; + guint xkeysym; + guint keycode; + + symbol = eek_key_get_symbol_with_fallback (key, 0, 0); + + /* Ignore special keys and modifiers */ + if (!EEK_IS_KEYSYM(symbol) || eek_symbol_is_modifier (symbol)) + return; + + xkeysym = eek_keysym_get_xkeysym (EEK_KEYSYM(symbol)); + g_return_if_fail (xkeysym > 0); + + keycode = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (client->display), + xkeysym); + 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), + keycode, + is_pressed, + CurrentTime); + XSync (GDK_DISPLAY_XDISPLAY (client->display), False); } static void @@ -813,35 +846,7 @@ on_key_pressed (EekKeyboard *keyboard, gpointer user_data) { EekboardClient *client = user_data; - EekSymbol *symbol; - - g_assert (client->fakekey); - - symbol = eek_key_get_symbol_with_fallback (key, 0, 0); - if (EEK_IS_KEYSYM(symbol) && !eek_symbol_is_modifier (symbol)) { - guint xkeysym; - guint keycode; - EekModifierType modifiers; - FakeKeyModifier fakekey_modifiers; - - xkeysym = eek_keysym_get_xkeysym (EEK_KEYSYM(symbol)); - g_return_if_fail (xkeysym > 0); - keycode = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (client->display), - xkeysym); - g_return_if_fail (keycode > 0); - - modifiers = eek_keyboard_get_modifiers (client->keyboard); - fakekey_modifiers = get_fakekey_modifiers (modifiers); - - fakekey_send_keyevent (client->fakekey, - keycode, - TRUE, - fakekey_modifiers); - fakekey_send_keyevent (client->fakekey, - keycode, - FALSE, - fakekey_modifiers); - } + send_fake_key_event (client, key, TRUE); } static void @@ -850,23 +855,37 @@ on_key_released (EekKeyboard *keyboard, gpointer user_data) { EekboardClient *client = user_data; + send_fake_key_event (client, key, FALSE); +} - g_assert (client->fakekey); - fakekey_release (client->fakekey); +static void +update_modifier_keycodes (EekboardClient *client) +{ + XModifierKeymap *mods; + gint i, j; + + mods = XGetModifierMapping (GDK_DISPLAY_XDISPLAY (client->display)); + for (i = 0; i < 8; i++) { + client->modifier_keycodes[i] = 0; + for (j = 0; j < mods->max_keypermod; j++) { + KeyCode keycode = mods->modifiermap[mods->max_keypermod * i + j]; + if (keycode != 0) { + client->modifier_keycodes[i] = keycode; + break; + } + } + } } gboolean -eekboard_client_enable_fakekey (EekboardClient *client) +eekboard_client_enable_xtest (EekboardClient *client) { if (!client->display) { client->display = gdk_display_get_default (); } g_assert (client->display); - if (!client->fakekey) { - client->fakekey = fakekey_init (GDK_DISPLAY_XDISPLAY (client->display)); - } - g_assert (client->fakekey); + update_modifier_keycodes (client); client->key_pressed_handler = g_signal_connect (client->keyboard, "key-pressed", @@ -879,11 +898,8 @@ eekboard_client_enable_fakekey (EekboardClient *client) } void -eekboard_client_disable_fakekey (EekboardClient *client) +eekboard_client_disable_xtest (EekboardClient *client) { - if (client->fakekey) - fakekey_release (client->fakekey); - if (g_signal_handler_is_connected (client->keyboard, client->key_pressed_handler)) g_signal_handler_disconnect (client->keyboard, @@ -922,4 +938,4 @@ eekboard_client_load_keyboard_from_file (EekboardClient *client, return retval; } -#endif /* HAVE_FAKEKEY */ +#endif /* HAVE_XTEST */ diff --git a/src/client.h b/src/client.h index ca5f082c..4dd6c667 100644 --- a/src/client.h +++ b/src/client.h @@ -31,36 +31,36 @@ G_BEGIN_DECLS typedef struct _EekboardClient EekboardClient; -EekboardClient * eekboard_client_new (GDBusConnection *connection); +EekboardClient * eekboard_client_new (GDBusConnection *connection); gboolean eekboard_client_load_keyboard_from_file - (EekboardClient *client, - const gchar *file); -gboolean eekboard_client_set_xkl_config (EekboardClient *client, - const gchar *model, - const gchar *layouts, - const gchar *options); + (EekboardClient *client, + 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); -void eekboard_client_disable_xkl (EekboardClient *client); +gboolean eekboard_client_enable_xkl (EekboardClient *client); +void eekboard_client_disable_xkl (EekboardClient *client); gboolean eekboard_client_enable_atspi_focus - (EekboardClient *client); + (EekboardClient *client); void eekboard_client_disable_atspi_focus - (EekboardClient *client); + (EekboardClient *client); gboolean eekboard_client_enable_atspi_keystroke - (EekboardClient *client); + (EekboardClient *client); void eekboard_client_disable_atspi_keystroke - (EekboardClient *client); + (EekboardClient *client); -gboolean eekboard_client_enable_fakekey (EekboardClient *client); -void eekboard_client_disable_fakekey (EekboardClient *client); +gboolean eekboard_client_enable_xtest (EekboardClient *client); +void eekboard_client_disable_xtest (EekboardClient *client); gboolean eekboard_client_enable_ibus_focus - (EekboardClient *client); + (EekboardClient *client); void eekboard_client_disable_ibus_focus - (EekboardClient *client); + (EekboardClient *client); G_END_DECLS #endif /* EEKBOARD_CLIENT_H */