Blame src/tests/ibus-keypress.c

Packit 3ff832
#include <gtk/gtk.h>
Packit 3ff832
#include <gdk/gdkx.h>
Packit 3ff832
#include "ibus.h"
Packit 3ff832
#include <stdlib.h>
Packit 3ff832
#include <X11/Xlib.h>
Packit 3ff832
#include <X11/extensions/XTest.h>
Packit 3ff832
Packit 3ff832
#define GREEN "\033[0;32m"
Packit 3ff832
#define RED   "\033[0;31m"
Packit 3ff832
#define NC    "\033[0m"
Packit 3ff832
Packit 3ff832
typedef struct _KeyData {
Packit 3ff832
    guint keyval;
Packit 3ff832
    guint modifiers;
Packit 3ff832
} KeyData;
Packit 3ff832
Packit 3ff832
static const KeyData test_cases[][30] = {
Packit 3ff832
   { { IBUS_KEY_a, 0 }, { IBUS_KEY_comma, IBUS_SHIFT_MASK },
Packit 3ff832
     { IBUS_KEY_b, 0 }, { IBUS_KEY_period, IBUS_SHIFT_MASK },
Packit 3ff832
     { IBUS_KEY_c, 0 }, { IBUS_KEY_slash, IBUS_SHIFT_MASK },
Packit 3ff832
     { IBUS_KEY_d, 0 }, { IBUS_KEY_semicolon, IBUS_SHIFT_MASK },
Packit 3ff832
     { IBUS_KEY_e, 0 }, { IBUS_KEY_apostrophe, IBUS_SHIFT_MASK },
Packit 3ff832
     { IBUS_KEY_f, 0 }, { IBUS_KEY_bracketleft, IBUS_SHIFT_MASK },
Packit 3ff832
     { IBUS_KEY_g, 0 }, { IBUS_KEY_backslash, IBUS_SHIFT_MASK },
Packit 3ff832
     { 0, 0 } },
Packit 3ff832
   { { IBUS_KEY_grave, IBUS_SHIFT_MASK }, { IBUS_KEY_a, IBUS_SHIFT_MASK },
Packit 3ff832
     { IBUS_KEY_1, IBUS_SHIFT_MASK }, { IBUS_KEY_b, IBUS_SHIFT_MASK  },
Packit 3ff832
     { IBUS_KEY_2, IBUS_SHIFT_MASK }, { IBUS_KEY_c, IBUS_SHIFT_MASK  },
Packit 3ff832
     { IBUS_KEY_3, IBUS_SHIFT_MASK }, { IBUS_KEY_d, IBUS_SHIFT_MASK },
Packit 3ff832
     { IBUS_KEY_9, IBUS_SHIFT_MASK }, { IBUS_KEY_e, IBUS_SHIFT_MASK },
Packit 3ff832
     { IBUS_KEY_0, IBUS_SHIFT_MASK }, { IBUS_KEY_f, IBUS_SHIFT_MASK },
Packit 3ff832
     { IBUS_KEY_equal, IBUS_SHIFT_MASK }, { IBUS_KEY_g, IBUS_SHIFT_MASK },
Packit 3ff832
     { 0, 0 } },
Packit 3ff832
   { { 0, 0 } }
Packit 3ff832
};
Packit 3ff832
Packit 3ff832
KeyData test_end_key = { IBUS_KEY_z, IBUS_SHIFT_MASK };
Packit 3ff832
Packit 3ff832
static const gunichar test_results[][60] = {
Packit 3ff832
   { 'a', '<', 'b', '>', 'c', '?', 'd', ':', 'e', '"', 'f', '{', 'g', '|', 0 },
Packit 3ff832
   { '~', 'A', '!', 'B', '@', 'C', '#', 'D', '(', 'E', ')', 'F', '+', 'G', 0 },
Packit 3ff832
   { 0 }
Packit 3ff832
};
Packit 3ff832
Packit 3ff832
Packit 3ff832
IBusBus *m_bus;
Packit 3ff832
IBusEngine *m_engine;
Packit 3ff832
Packit 3ff832
static gboolean window_focus_in_event_cb (GtkWidget     *entry,
Packit 3ff832
                                          GdkEventFocus *event,
Packit 3ff832
                                          gpointer       data);
Packit 3ff832
Packit 3ff832
static IBusEngine *
Packit 3ff832
create_engine_cb (IBusFactory *factory, const gchar *name, gpointer data)
Packit 3ff832
{
Packit 3ff832
    static int i = 1;
Packit 3ff832
    gchar *engine_path =
Packit 3ff832
            g_strdup_printf ("/org/freedesktop/IBus/engine/simpletest/%d",
Packit 3ff832
                             i++);
Packit 3ff832
Packit 3ff832
    m_engine = ibus_engine_new_with_type (IBUS_TYPE_ENGINE_SIMPLE,
Packit 3ff832
                                          name,
Packit 3ff832
                                          engine_path,
Packit 3ff832
                                          ibus_bus_get_connection (m_bus));
Packit 3ff832
    g_free (engine_path);
Packit 3ff832
    return m_engine;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static gboolean
Packit 3ff832
register_ibus_engine ()
Packit 3ff832
{
Packit 3ff832
    IBusFactory *factory;
Packit 3ff832
    IBusComponent *component;
Packit 3ff832
    IBusEngineDesc *desc;
Packit 3ff832
Packit 3ff832
    m_bus = ibus_bus_new ();
Packit 3ff832
    if (!ibus_bus_is_connected (m_bus)) {
Packit 3ff832
        g_critical ("ibus-daemon is not running.");
Packit 3ff832
        return FALSE;
Packit 3ff832
    }
Packit 3ff832
    factory = ibus_factory_new (ibus_bus_get_connection (m_bus));
Packit 3ff832
    g_signal_connect (factory, "create-engine",
Packit 3ff832
                      G_CALLBACK (create_engine_cb), NULL);
Packit 3ff832
Packit 3ff832
    component = ibus_component_new (
Packit 3ff832
            "org.freedesktop.IBus.SimpleTest",
Packit 3ff832
            "Simple Engine Test",
Packit 3ff832
            "0.0.1",
Packit 3ff832
            "GPL",
Packit 3ff832
            "Takao Fujiwara <takao.fujiwara1@gmail.com>",
Packit 3ff832
            "https://github.com/ibus/ibus/wiki",
Packit 3ff832
            "",
Packit 3ff832
            "ibus");
Packit 3ff832
    desc = ibus_engine_desc_new (
Packit 3ff832
            "xkbtest:us::eng",
Packit 3ff832
            "XKB Test",
Packit 3ff832
            "XKB Test",
Packit 3ff832
            "en",
Packit 3ff832
            "GPL",
Packit 3ff832
            "Takao Fujiwara <takao.fujiwara1@gmail.com>",
Packit 3ff832
            "ibus-engine",
Packit 3ff832
            "us");
Packit 3ff832
    ibus_component_add_engine (component, desc);
Packit 3ff832
    ibus_bus_register_component (m_bus, component);
Packit 3ff832
Packit 3ff832
    return TRUE;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static gboolean
Packit 3ff832
finit (gpointer data)
Packit 3ff832
{
Packit 3ff832
    g_critical ("time out");
Packit 3ff832
    gtk_main_quit ();
Packit 3ff832
    return FALSE;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static void
Packit 3ff832
send_key_event (Display *xdisplay,
Packit 3ff832
                guint    keyval,
Packit 3ff832
                guint    modifiers)
Packit 3ff832
{
Packit 3ff832
    static struct {
Packit 3ff832
        guint   state;
Packit 3ff832
        KeySym  keysym;
Packit 3ff832
    } state2keysym[] = {
Packit 3ff832
        { IBUS_CONTROL_MASK, XK_Control_L } ,
Packit 3ff832
        { IBUS_MOD1_MASK,    XK_Alt_L },
Packit 3ff832
        { IBUS_MOD4_MASK,    XK_Super_L },
Packit 3ff832
        { IBUS_SHIFT_MASK,   XK_Shift_L },
Packit 3ff832
        { IBUS_LOCK_MASK,    XK_Caps_Lock },
Packit 3ff832
        { 0,           0L }
Packit 3ff832
    };
Packit 3ff832
    int i;
Packit 3ff832
    guint keycode;
Packit 3ff832
    guint state = modifiers;
Packit 3ff832
Packit 3ff832
    while (state) {
Packit 3ff832
        for (i = 0; state2keysym[i].state; i++) {
Packit 3ff832
            if ((state2keysym[i].state & state) != 0) {
Packit 3ff832
                keycode = XKeysymToKeycode (xdisplay, state2keysym[i].keysym);
Packit 3ff832
                XTestFakeKeyEvent (xdisplay, keycode, True, CurrentTime);
Packit 3ff832
                XSync (xdisplay, False);
Packit 3ff832
                state ^= state2keysym[i].state;
Packit 3ff832
                break;
Packit 3ff832
            }
Packit 3ff832
        }
Packit 3ff832
    }
Packit 3ff832
    keycode = XKeysymToKeycode (xdisplay, keyval);
Packit 3ff832
    XTestFakeKeyEvent (xdisplay, keycode, True, CurrentTime);
Packit 3ff832
    XSync (xdisplay, False);
Packit 3ff832
    XTestFakeKeyEvent (xdisplay, keycode, False, CurrentTime);
Packit 3ff832
    XSync (xdisplay, False);
Packit 3ff832
Packit 3ff832
    state = modifiers;
Packit 3ff832
    while (state) {
Packit 3ff832
        for (i = G_N_ELEMENTS (state2keysym) - 1; i >= 0; i--) {
Packit 3ff832
            if ((state2keysym[i].state & state) != 0) {
Packit 3ff832
                keycode = XKeysymToKeycode (xdisplay, state2keysym[i].keysym);
Packit 3ff832
                XTestFakeKeyEvent (xdisplay, keycode, False, CurrentTime);
Packit 3ff832
                XSync (xdisplay, False);
Packit 3ff832
                state ^= state2keysym[i].state;
Packit 3ff832
                break;
Packit 3ff832
            }
Packit 3ff832
        }
Packit 3ff832
    }
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static void
Packit 3ff832
set_engine_cb (GObject      *object,
Packit 3ff832
               GAsyncResult *res,
Packit 3ff832
               gpointer      data)
Packit 3ff832
{
Packit 3ff832
    IBusBus *bus = IBUS_BUS (object);
Packit 3ff832
    GtkWidget *entry = GTK_WIDGET (data);
Packit 3ff832
    GdkDisplay *display;
Packit 3ff832
    Display *xdisplay;
Packit 3ff832
    GError *error = NULL;
Packit 3ff832
    int i, j;
Packit 3ff832
Packit 3ff832
    g_assert (GTK_IS_ENTRY (entry));
Packit 3ff832
Packit 3ff832
    if (!ibus_bus_set_global_engine_async_finish (bus, res, &error)) {
Packit 3ff832
        g_critical ("set engine failed: %s", error->message);
Packit 3ff832
        g_error_free (error);
Packit 3ff832
        return;
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    display = gtk_widget_get_display (entry);
Packit 3ff832
    if (GDK_IS_X11_DISPLAY (display)) {
Packit 3ff832
        xdisplay = gdk_x11_display_get_xdisplay (display);
Packit 3ff832
    } else {
Packit 3ff832
#if 0
Packit 3ff832
        xdisplay = XOpenDisplay (NULL);
Packit 3ff832
#else
Packit 3ff832
        g_critical ("No idea to simulate key events in Wayland\n");
Packit 3ff832
#endif
Packit 3ff832
    }
Packit 3ff832
    g_return_if_fail (xdisplay);
Packit 3ff832
Packit 3ff832
    for (i = 0; test_cases[i][0].keyval; i++) {
Packit 3ff832
        for (j = 0; test_cases[i][j].keyval; j++) {
Packit 3ff832
            send_key_event (xdisplay,
Packit 3ff832
                            test_cases[i][j].keyval,
Packit 3ff832
                            test_cases[i][j].modifiers);
Packit 3ff832
        }
Packit 3ff832
        send_key_event (xdisplay, test_end_key.keyval, test_end_key.modifiers);
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    g_timeout_add_seconds (10, finit, NULL);
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static gboolean
Packit 3ff832
window_focus_in_event_cb (GtkWidget *entry, GdkEventFocus *event, gpointer data)
Packit 3ff832
{
Packit 3ff832
    g_assert (m_bus != NULL);
Packit 3ff832
    ibus_bus_set_global_engine_async (m_bus,
Packit 3ff832
                                      "xkbtest:us::eng",
Packit 3ff832
                                      -1,
Packit 3ff832
                                      NULL,
Packit 3ff832
                                      set_engine_cb,
Packit 3ff832
                                      entry);
Packit 3ff832
    return FALSE;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static void
Packit 3ff832
window_inserted_text_cb (GtkEntryBuffer *buffer,
Packit 3ff832
                         guint           position,
Packit 3ff832
                         const gchar    *chars,
Packit 3ff832
                         guint           nchars,
Packit 3ff832
                         gpointer        data)
Packit 3ff832
{
Packit 3ff832
    GtkWidget *entry = data;
Packit 3ff832
    static int i = 0;
Packit 3ff832
    static int j = 0;
Packit 3ff832
Packit 3ff832
    if (g_utf8_get_char (chars) == 'Z') {
Packit 3ff832
        int k;
Packit 3ff832
        g_print ("\n" GREEN "PASS" NC ": ");
Packit 3ff832
        for (k = 0; k < j; k++)
Packit 3ff832
            g_print ("%lc(%X) ", test_results[i][k], test_results[i][k]);
Packit 3ff832
        g_print ("\n");
Packit 3ff832
        i++;
Packit 3ff832
        j = 0;
Packit 3ff832
        if (test_results[i][0] == 0)
Packit 3ff832
            gtk_main_quit ();
Packit 3ff832
        else
Packit 3ff832
            gtk_entry_set_text (GTK_ENTRY (entry), "");
Packit 3ff832
        return;
Packit 3ff832
    }
Packit 3ff832
    g_assert (g_utf8_get_char (chars) == test_results[i][j]);
Packit 3ff832
    j++;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static void
Packit 3ff832
create_window ()
Packit 3ff832
{
Packit 3ff832
    GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
Packit 3ff832
    GtkWidget *entry = gtk_entry_new ();
Packit 3ff832
    GtkEntryBuffer *buffer;
Packit 3ff832
Packit 3ff832
    g_signal_connect (window, "destroy",
Packit 3ff832
                      G_CALLBACK (gtk_main_quit), NULL);
Packit 3ff832
    g_signal_connect (entry, "focus-in-event",
Packit 3ff832
                      G_CALLBACK (window_focus_in_event_cb), NULL);
Packit 3ff832
    buffer = gtk_entry_get_buffer (GTK_ENTRY (entry));
Packit 3ff832
    g_signal_connect (buffer, "inserted-text",
Packit 3ff832
                      G_CALLBACK (window_inserted_text_cb), entry);
Packit 3ff832
    gtk_container_add (GTK_CONTAINER (window), entry);
Packit 3ff832
    gtk_widget_show_all (window);
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static void
Packit 3ff832
test_keypress (void)
Packit 3ff832
{
Packit 3ff832
    int status = 0;
Packit 3ff832
    GError *error = NULL;
Packit 3ff832
Packit 3ff832
    g_spawn_command_line_sync ("setxkbmap -layout us",
Packit 3ff832
                               NULL, NULL,
Packit 3ff832
                               &status, &error);
Packit 3ff832
    g_assert (register_ibus_engine ());
Packit 3ff832
Packit 3ff832
    create_window ();
Packit 3ff832
    gtk_main ();
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
int
Packit 3ff832
main (int argc, char *argv[])
Packit 3ff832
{
Packit 3ff832
    ibus_init ();
Packit 3ff832
    g_test_init (&argc, &argv, NULL);
Packit 3ff832
    gtk_init (&argc, &argv);
Packit 3ff832
Packit 3ff832
    g_test_add_func ("/ibus/keyrepss", test_keypress);
Packit 3ff832
Packit 3ff832
Packit 3ff832
    return g_test_run ();
Packit 3ff832
}