Blame bus/test-client.c

Packit Service 1d8f1c
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
Packit Service 1d8f1c
/* vim:set et sts=4: */
Packit Service 1d8f1c
/* bus - The Input Bus
Packit Service 1d8f1c
 * Copyright (C) 2010 Google Inc.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * This library is free software; you can redistribute it and/or
Packit Service 1d8f1c
 * modify it under the terms of the GNU Lesser General Public
Packit Service 1d8f1c
 * License as published by the Free Software Foundation; either
Packit Service 1d8f1c
 * version 2.1 of the License, or (at your option) any later version.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * This library is distributed in the hope that it will be useful,
Packit Service 1d8f1c
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 1d8f1c
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 1d8f1c
 * Lesser General Public License for more details.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * You should have received a copy of the GNU Lesser General Public
Packit Service 1d8f1c
 * License along with this library; if not, write to the Free Software
Packit Service 1d8f1c
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
Packit Service 1d8f1c
 * USA
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
Packit Service 1d8f1c
#include <ibus.h>
Packit Service 1d8f1c
#include <X11/Xlib.h>
Packit Service 1d8f1c
#include <X11/Xutil.h>
Packit Service 1d8f1c
Packit Service 1d8f1c
#include "test-client.h"
Packit Service 1d8f1c
Packit Service 1d8f1c
#ifdef DEBUG
Packit Service 1d8f1c
#  define IDEBUG g_debug
Packit Service 1d8f1c
#else
Packit Service 1d8f1c
#  define IDEBUG(a...)
Packit Service 1d8f1c
#endif
Packit Service 1d8f1c
/* functions prototype */
Packit Service 1d8f1c
static void          bus_test_client_class_init      (BusTestClientClass *class);
Packit Service 1d8f1c
static void          bus_test_client_destroy         (IBusObject         *object);
Packit Service 1d8f1c
Packit Service 1d8f1c
/* static methods*/
Packit Service 1d8f1c
static void          _store_modifier_state          (BusTestClient      *client,
Packit Service 1d8f1c
                                                     guint               modifier);
Packit Service 1d8f1c
static gboolean      _is_shift_set                  (BusTestClient      *client);
Packit Service 1d8f1c
static gboolean      _is_modifier_set               (BusTestClient      *client,
Packit Service 1d8f1c
                                                     guint               modifier);
Packit Service 1d8f1c
static gboolean      _is_modifier_key               (guint               modifier);
Packit Service 1d8f1c
static guint         _get_modifiers_to_mask         (BusTestClient      *client);
Packit Service 1d8f1c
static gint16        _get_keysym_to_keycode         (guint               keysym);
Packit Service 1d8f1c
Packit Service 1d8f1c
static void          _bus_disconnected_cb           (IBusBus            *ibusbus,
Packit Service 1d8f1c
                                                     BusTestClient      *client);
Packit Service 1d8f1c
static void          _bus_disabled_cb               (IBusInputContext   *ibuscontext,
Packit Service 1d8f1c
                                                     BusTestClient      *client);
Packit Service 1d8f1c
Packit Service 1d8f1c
static IBusBus      *_bus = NULL;
Packit Service 1d8f1c
static Display      *_xdisplay = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
G_DEFINE_TYPE (BusTestClient, bus_test_client, IBUS_TYPE_OBJECT)
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_test_client_class_init (BusTestClientClass *class)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IDEBUG ("%s", __FUNCTION__);
Packit Service 1d8f1c
Packit Service 1d8f1c
    IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (class);
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_object_class->destroy = bus_test_client_destroy;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* init display object */
Packit Service 1d8f1c
    if (_xdisplay == NULL) {
Packit Service 1d8f1c
        _xdisplay = XOpenDisplay (NULL);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* init bus object */
Packit Service 1d8f1c
    if (_bus == NULL) {
Packit Service 1d8f1c
        ibus_set_display (XDisplayString (_xdisplay));
Packit Service 1d8f1c
        _bus = ibus_bus_new();
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_connect (_bus, "disconnected", G_CALLBACK (_bus_disconnected_cb), NULL);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_test_client_init (BusTestClient *client)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IDEBUG ("%s", __FUNCTION__);
Packit Service 1d8f1c
    client->connected = FALSE;
Packit Service 1d8f1c
    client->enabled = FALSE;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_return_if_fail (ibus_bus_is_connected (_bus));
Packit Service 1d8f1c
    client->connected = TRUE;
Packit Service 1d8f1c
Packit Service 1d8f1c
    client->ibuscontext = ibus_bus_create_input_context (_bus, "test-client");
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_return_if_fail (client->ibuscontext != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_connect (client->ibuscontext,
Packit Service 1d8f1c
                      "disabled",
Packit Service 1d8f1c
                      G_CALLBACK (_bus_disabled_cb),
Packit Service 1d8f1c
                      client);
Packit Service 1d8f1c
Packit Service 1d8f1c
    bus_test_client_clear_modifier (client);
Packit Service 1d8f1c
Packit Service 1d8f1c
    client->caps = IBUS_CAP_FOCUS;
Packit Service 1d8f1c
    ibus_input_context_set_capabilities (client->ibuscontext, client->caps);
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_bus_set_global_engine (_bus, "xkb:us::eng");
Packit Service 1d8f1c
Packit Service 1d8f1c
    client->enabled = TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_test_client_destroy (IBusObject *object)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IDEBUG ("%s", __FUNCTION__);
Packit Service 1d8f1c
    BusTestClient *client = BUS_TEST_CLIENT (object);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_object_unref (client->ibuscontext);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
BusTestClient *
Packit Service 1d8f1c
bus_test_client_new (void)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IDEBUG ("%s", __FUNCTION__);
Packit Service 1d8f1c
    BusTestClient *client = BUS_TEST_CLIENT (g_object_new (BUS_TYPE_TEST_CLIENT, NULL));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (client->connected && client->enabled) {
Packit Service 1d8f1c
        return client;
Packit Service 1d8f1c
    } else {
Packit Service 1d8f1c
        return NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
gboolean
Packit Service 1d8f1c
bus_test_client_is_enabled (BusTestClient *client)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IDEBUG ("%s", __FUNCTION__);
Packit Service 1d8f1c
    return client->enabled;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
gboolean
Packit Service 1d8f1c
bus_test_client_is_connected (BusTestClient *client)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IDEBUG ("%s", __FUNCTION__);
Packit Service 1d8f1c
    return client->connected;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
gboolean
Packit Service 1d8f1c
bus_test_client_send_key (BusTestClient *client,
Packit Service 1d8f1c
                     guint      keysym)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    gboolean is_modifier = _is_modifier_key (keysym);
Packit Service 1d8f1c
    gint16 keycode;
Packit Service 1d8f1c
    guint state;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (is_modifier) {
Packit Service 1d8f1c
        IDEBUG ("key: %d is modifier.", keysym);
Packit Service 1d8f1c
        gboolean is_modifier_set = _is_modifier_set (client, keysym);
Packit Service 1d8f1c
        keycode = _get_keysym_to_keycode (keysym);
Packit Service 1d8f1c
        state = _get_modifiers_to_mask (client);
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (is_modifier_set) {
Packit Service 1d8f1c
            state |= IBUS_RELEASE_MASK;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        ibus_input_context_process_key_event (client->ibuscontext,
Packit Service 1d8f1c
                                              keysym,
Packit Service 1d8f1c
                                              keycode,
Packit Service 1d8f1c
                                              state);
Packit Service 1d8f1c
        _store_modifier_state (client, keysym);
Packit Service 1d8f1c
    } else {
Packit Service 1d8f1c
        IDEBUG ("key: %d is not modifier.", keysym);
Packit Service 1d8f1c
        /* This is an example code. If you use the keysym >= 0x01000000,
Packit Service 1d8f1c
         * gdk_keyval_is_upper may be useful since 
Packit Service 1d8f1c
         * XConvertCase supports implementation-independent conversions.
Packit Service 1d8f1c
         */
Packit Service 1d8f1c
        KeySym xlower = 0;
Packit Service 1d8f1c
        KeySym xupper = 0;
Packit Service 1d8f1c
        gboolean is_upper = FALSE;
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (keysym) {
Packit Service 1d8f1c
            XConvertCase (keysym, &xlower, &xupper);
Packit Service 1d8f1c
            is_upper = ((guint) xupper == keysym);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
Packit Service 1d8f1c
        gboolean is_shift_set = _is_shift_set (client);
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (is_upper && !is_shift_set) {
Packit Service 1d8f1c
            _store_modifier_state (client, IBUS_KEY_Shift_L);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        keycode = _get_keysym_to_keycode (keysym);
Packit Service 1d8f1c
        state = _get_modifiers_to_mask (client);
Packit Service 1d8f1c
        ibus_input_context_process_key_event (client->ibuscontext,
Packit Service 1d8f1c
                                              keysym,
Packit Service 1d8f1c
                                              keycode,
Packit Service 1d8f1c
                                              state);
Packit Service 1d8f1c
        state |= IBUS_RELEASE_MASK;
Packit Service 1d8f1c
        ibus_input_context_process_key_event (client->ibuscontext,
Packit Service 1d8f1c
                                              keysym,
Packit Service 1d8f1c
                                              keycode,
Packit Service 1d8f1c
                                              state);
Packit Service 1d8f1c
        if (is_upper && !is_shift_set) {
Packit Service 1d8f1c
            _store_modifier_state (client, IBUS_KEY_Shift_L);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
void bus_test_client_clear_modifier (BusTestClient *client)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    int i;
Packit Service 1d8f1c
    for (i = 0; i < MODIFIER_KEY_NUM; i++) {
Packit Service 1d8f1c
        (client->modifier)[i] = FALSE;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_store_modifier_state (BusTestClient    *client,
Packit Service 1d8f1c
                       guint         modifier)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    switch(modifier) {
Packit Service 1d8f1c
    case IBUS_KEY_Shift_L:
Packit Service 1d8f1c
    case IBUS_KEY_Shift_R:
Packit Service 1d8f1c
        /* ShiftMask */
Packit Service 1d8f1c
        client->modifier[0] = !client->modifier[0];
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    case IBUS_KEY_Shift_Lock:
Packit Service 1d8f1c
    case IBUS_KEY_Caps_Lock:
Packit Service 1d8f1c
        /* LockMask */
Packit Service 1d8f1c
        client->modifier[1] = !client->modifier[1];
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    case IBUS_KEY_Control_L:
Packit Service 1d8f1c
    case IBUS_KEY_Control_R:
Packit Service 1d8f1c
        /* ControlMask */
Packit Service 1d8f1c
        client->modifier[2] = !client->modifier[2];
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    case IBUS_KEY_Alt_L:
Packit Service 1d8f1c
    case IBUS_KEY_Alt_R:
Packit Service 1d8f1c
    case IBUS_KEY_Meta_L:
Packit Service 1d8f1c
        /* Mod1Mask */
Packit Service 1d8f1c
        client->modifier[3] = !client->modifier[3];
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    case IBUS_KEY_Num_Lock:
Packit Service 1d8f1c
        /* Mod2Mask */
Packit Service 1d8f1c
        client->modifier[4] = !client->modifier[4];
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    case IBUS_KEY_Super_L:
Packit Service 1d8f1c
    case IBUS_KEY_Hyper_L:
Packit Service 1d8f1c
        /* Mod4Mask */
Packit Service 1d8f1c
        client->modifier[5] = !client->modifier[5];
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    case IBUS_KEY_ISO_Level3_Shift:
Packit Service 1d8f1c
    case IBUS_KEY_Mode_switch:
Packit Service 1d8f1c
        /* Mod5Mask */
Packit Service 1d8f1c
        client->modifier[6] = !client->modifier[6];
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    default:
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gint16
Packit Service 1d8f1c
_get_keysym_to_keycode (guint keysym)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return XKeysymToKeycode (_xdisplay, keysym);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
_is_shift_set (BusTestClient *client)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return client->modifier[0];
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
_is_modifier_set (BusTestClient *client,
Packit Service 1d8f1c
                  guint      modifier)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    switch(modifier) {
Packit Service 1d8f1c
    case IBUS_KEY_Shift_L:
Packit Service 1d8f1c
    case IBUS_KEY_Shift_R:
Packit Service 1d8f1c
        /* ShiftMask */
Packit Service 1d8f1c
        return client->modifier[0];
Packit Service 1d8f1c
    case IBUS_KEY_Shift_Lock:
Packit Service 1d8f1c
    case IBUS_KEY_Caps_Lock:
Packit Service 1d8f1c
        /* LockMask */
Packit Service 1d8f1c
        return client->modifier[1];
Packit Service 1d8f1c
    case IBUS_KEY_Control_L:
Packit Service 1d8f1c
    case IBUS_KEY_Control_R:
Packit Service 1d8f1c
        /* ControlMask */
Packit Service 1d8f1c
        return client->modifier[2];
Packit Service 1d8f1c
    case IBUS_KEY_Alt_L:
Packit Service 1d8f1c
    case IBUS_KEY_Alt_R:
Packit Service 1d8f1c
    case IBUS_KEY_Meta_L:
Packit Service 1d8f1c
        /* Mod1Mask */
Packit Service 1d8f1c
        return client->modifier[3];
Packit Service 1d8f1c
    case IBUS_KEY_Num_Lock:
Packit Service 1d8f1c
        /* Mod2Mask */
Packit Service 1d8f1c
        return client->modifier[4];
Packit Service 1d8f1c
    case IBUS_KEY_Super_L:
Packit Service 1d8f1c
    case IBUS_KEY_Hyper_L:
Packit Service 1d8f1c
        /* Mod4Mask */
Packit Service 1d8f1c
        return client->modifier[5];
Packit Service 1d8f1c
    case IBUS_KEY_ISO_Level3_Shift:
Packit Service 1d8f1c
    case IBUS_KEY_Mode_switch:
Packit Service 1d8f1c
        /* Mod5Mask */
Packit Service 1d8f1c
        return client->modifier[6];
Packit Service 1d8f1c
    default:
Packit Service 1d8f1c
        return FALSE;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
_is_modifier_key (guint modifier)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    switch(modifier) {
Packit Service 1d8f1c
    case IBUS_KEY_Shift_L:
Packit Service 1d8f1c
    case IBUS_KEY_Shift_R:
Packit Service 1d8f1c
    case IBUS_KEY_Shift_Lock:
Packit Service 1d8f1c
    case IBUS_KEY_Caps_Lock:
Packit Service 1d8f1c
    case IBUS_KEY_Control_L:
Packit Service 1d8f1c
    case IBUS_KEY_Control_R:
Packit Service 1d8f1c
    case IBUS_KEY_Alt_L:
Packit Service 1d8f1c
    case IBUS_KEY_Alt_R:
Packit Service 1d8f1c
    case IBUS_KEY_Meta_L:
Packit Service 1d8f1c
    case IBUS_KEY_Num_Lock:
Packit Service 1d8f1c
    case IBUS_KEY_Super_L:
Packit Service 1d8f1c
    case IBUS_KEY_Hyper_L:
Packit Service 1d8f1c
    case IBUS_KEY_ISO_Level3_Shift:
Packit Service 1d8f1c
    case IBUS_KEY_Mode_switch:
Packit Service 1d8f1c
        return TRUE;
Packit Service 1d8f1c
    default:
Packit Service 1d8f1c
        return FALSE;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static guint
Packit Service 1d8f1c
_get_modifiers_to_mask (BusTestClient *client)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    guint retval = 0;
Packit Service 1d8f1c
    if(client->modifier[0])
Packit Service 1d8f1c
        retval |= IBUS_SHIFT_MASK;
Packit Service 1d8f1c
    if(client->modifier[1])
Packit Service 1d8f1c
        retval |= IBUS_LOCK_MASK;
Packit Service 1d8f1c
    if(client->modifier[2])
Packit Service 1d8f1c
        retval |= IBUS_CONTROL_MASK;
Packit Service 1d8f1c
    if(client->modifier[3])
Packit Service 1d8f1c
        retval |= IBUS_MOD1_MASK;
Packit Service 1d8f1c
    if(client->modifier[4])
Packit Service 1d8f1c
        retval |= IBUS_MOD2_MASK;
Packit Service 1d8f1c
    if(client->modifier[5])
Packit Service 1d8f1c
        retval |= IBUS_MOD4_MASK;
Packit Service 1d8f1c
    if(client->modifier[6])
Packit Service 1d8f1c
        retval |= IBUS_MOD5_MASK;
Packit Service 1d8f1c
    return retval;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_bus_disconnected_cb (IBusBus   *ibusbus,
Packit Service 1d8f1c
                      BusTestClient *client)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (IBUS_IS_BUS (ibusbus));
Packit Service 1d8f1c
    g_assert (BUS_IS_TEST_CLIENT (client));
Packit Service 1d8f1c
    IDEBUG ("%s", __FUNCTION__);
Packit Service 1d8f1c
    client->connected = FALSE;
Packit Service 1d8f1c
    IDEBUG ("Disconnected ibus daemon");
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_bus_disabled_cb (IBusInputContext  *ibuscontext,
Packit Service 1d8f1c
                  BusTestClient         *client)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (IBUS_IS_INPUT_CONTEXT (ibuscontext));
Packit Service 1d8f1c
    g_assert (BUS_IS_TEST_CLIENT (client));
Packit Service 1d8f1c
    IDEBUG ("%s", __FUNCTION__);
Packit Service 1d8f1c
    client->enabled = FALSE;
Packit Service 1d8f1c
    IDEBUG ("Disabled ibus engine");
Packit Service 1d8f1c
}
Packit Service 1d8f1c