Blame client/x11/main.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
/* ibus
Packit Service 1d8f1c
 * Copyright (C) 2007-2015 Peng Huang <shawn.p.huang@gmail.com>
Packit Service 1d8f1c
 * Copyright (C) 2015-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
Packit Service 1d8f1c
 * Copyright (C) 2007-2015 Red Hat, Inc.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * main.c:
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
#define _GNU_SOURCE
Packit Service 1d8f1c
Packit Service 1d8f1c
#include <X11/Xproto.h>
Packit Service 1d8f1c
#include <X11/Xlib.h>
Packit Service 1d8f1c
#include <X11/keysym.h>
Packit Service 1d8f1c
#include <X11/Xutil.h>
Packit Service 1d8f1c
#include <XimProto.h>
Packit Service 1d8f1c
#include <IMdkit.h>
Packit Service 1d8f1c
#include <Xi18n.h>
Packit Service 1d8f1c
#include <stdio.h>
Packit Service 1d8f1c
#include <gtk/gtk.h>
Packit Service 1d8f1c
#include <gdk/gdk.h>
Packit Service 1d8f1c
#include <gdk/gdkx.h>
Packit Service 1d8f1c
#include <langinfo.h>
Packit Service 1d8f1c
#include <locale.h>
Packit Service 1d8f1c
#include <iconv.h>
Packit Service 1d8f1c
#include <signal.h>
Packit Service 1d8f1c
#include <stdlib.h>
Packit Service 1d8f1c
Packit Service 1d8f1c
#include <getopt.h>
Packit Service 1d8f1c
Packit Service 1d8f1c
#define LOG(level, fmt_args...) \
Packit Service 1d8f1c
    if (g_debug_level >= (level)) { \
Packit Service 1d8f1c
        g_debug (fmt_args); \
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
#include <ibus.h>
Packit Service 1d8f1c
#include "gdk-private.h"
Packit Service 1d8f1c
#include "locales.h"
Packit Service 1d8f1c
Packit Service 1d8f1c
struct _X11ICONN {
Packit Service 1d8f1c
    GList        *clients;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
typedef struct _X11ICONN    X11ICONN;
Packit Service 1d8f1c
Packit Service 1d8f1c
typedef struct _X11IC    X11IC;
Packit Service 1d8f1c
struct _X11IC {
Packit Service 1d8f1c
    IBusInputContext *context;
Packit Service 1d8f1c
    Window           client_window;
Packit Service 1d8f1c
    Window           focus_window;
Packit Service 1d8f1c
    gint32           input_style;
Packit Service 1d8f1c
    X11ICONN        *conn;
Packit Service 1d8f1c
    gint             icid;
Packit Service 1d8f1c
    gint             connect_id;
Packit Service 1d8f1c
    gchar           *lang;
Packit Service 1d8f1c
    gboolean         has_preedit_area;
Packit Service 1d8f1c
    GdkRectangle     preedit_area;
Packit Service 1d8f1c
Packit Service 1d8f1c
    gchar           *preedit_string;
Packit Service 1d8f1c
    IBusAttrList    *preedit_attrs;
Packit Service 1d8f1c
    gint             preedit_cursor;
Packit Service 1d8f1c
    gboolean         preedit_visible;
Packit Service 1d8f1c
    gboolean         preedit_started;
Packit Service 1d8f1c
    gint             onspot_preedit_length;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
static void     _xim_set_cursor_location    (X11IC              *x11ic);
Packit Service 1d8f1c
static void     _context_commit_text_cb     (IBusInputContext   *context,
Packit Service 1d8f1c
                                             IBusText           *text,
Packit Service 1d8f1c
                                             X11IC              *x11ic);
Packit Service 1d8f1c
static void     _context_forward_key_event_cb
Packit Service 1d8f1c
                                            (IBusInputContext   *context,
Packit Service 1d8f1c
                                             guint               keyval,
Packit Service 1d8f1c
                                             guint               keycode,
Packit Service 1d8f1c
                                             guint               state,
Packit Service 1d8f1c
                                             X11IC              *x11ic);
Packit Service 1d8f1c
Packit Service 1d8f1c
static void     _context_update_preedit_text_cb
Packit Service 1d8f1c
                                            (IBusInputContext   *context,
Packit Service 1d8f1c
                                             IBusText           *text,
Packit Service 1d8f1c
                                             gint                cursor_pos,
Packit Service 1d8f1c
                                             gboolean            visible,
Packit Service 1d8f1c
                                             X11IC              *x11ic);
Packit Service 1d8f1c
static void     _context_show_preedit_text_cb
Packit Service 1d8f1c
                                            (IBusInputContext   *context,
Packit Service 1d8f1c
                                             X11IC              *x11ic);
Packit Service 1d8f1c
static void     _context_hide_preedit_text_cb
Packit Service 1d8f1c
                                            (IBusInputContext   *context,
Packit Service 1d8f1c
                                             X11IC              *x11ic);
Packit Service 1d8f1c
static void     _context_enabled_cb         (IBusInputContext   *context,
Packit Service 1d8f1c
                                             X11IC              *x11ic);
Packit Service 1d8f1c
static void     _context_disabled_cb        (IBusInputContext   *context,
Packit Service 1d8f1c
                                             X11IC              *x11ic);
Packit Service 1d8f1c
Packit Service 1d8f1c
static GHashTable     *_x11_ic_table = NULL;
Packit Service 1d8f1c
static GHashTable     *_connections = NULL;
Packit Service 1d8f1c
static XIMS _xims = NULL;
Packit Service 1d8f1c
static gchar *_server_name = NULL;
Packit Service 1d8f1c
static gchar *_locale = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean _kill_daemon = FALSE;
Packit Service 1d8f1c
static gint     g_debug_level = 0;
Packit Service 1d8f1c
Packit Service 1d8f1c
static IBusBus *_bus = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean _use_sync_mode = TRUE;
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_xim_preedit_start (XIMS xims, const X11IC *x11ic)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IMPreeditStateStruct ips;
Packit Service 1d8f1c
    ips.major_code = 0;
Packit Service 1d8f1c
    ips.minor_code = 0;
Packit Service 1d8f1c
    ips.icid = x11ic->icid;
Packit Service 1d8f1c
    ips.connect_id = x11ic->connect_id;
Packit Service 1d8f1c
    IMPreeditStart (xims, (XPointer)&ips;;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_xim_preedit_end (XIMS xims, const X11IC *x11ic)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IMPreeditStateStruct ips;
Packit Service 1d8f1c
    ips.major_code = 0;
Packit Service 1d8f1c
    ips.minor_code = 0;
Packit Service 1d8f1c
    ips.icid = x11ic->icid;
Packit Service 1d8f1c
    ips.connect_id = x11ic->connect_id;
Packit Service 1d8f1c
    IMPreeditEnd (xims, (XPointer)&ips;;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_xim_preedit_callback_start (XIMS xims, const X11IC *x11ic)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IMPreeditCBStruct pcb;
Packit Service 1d8f1c
Packit Service 1d8f1c
    pcb.major_code        = XIM_PREEDIT_START;
Packit Service 1d8f1c
    pcb.minor_code        = 0;
Packit Service 1d8f1c
    pcb.connect_id        = x11ic->connect_id;
Packit Service 1d8f1c
    pcb.icid              = x11ic->icid;
Packit Service 1d8f1c
    pcb.todo.return_value = 0;
Packit Service 1d8f1c
    IMCallCallback (xims, (XPointer) & pcb);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_xim_preedit_callback_done (XIMS xims, const X11IC *x11ic)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IMPreeditCBStruct pcb;
Packit Service 1d8f1c
Packit Service 1d8f1c
    pcb.major_code        = XIM_PREEDIT_DONE;
Packit Service 1d8f1c
    pcb.minor_code        = 0;
Packit Service 1d8f1c
    pcb.connect_id        = x11ic->connect_id;
Packit Service 1d8f1c
    pcb.icid              = x11ic->icid;
Packit Service 1d8f1c
    pcb.todo.return_value = 0;
Packit Service 1d8f1c
    IMCallCallback (xims, (XPointer) & pcb);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_xim_preedit_callback_draw (XIMS xims, X11IC *x11ic, const gchar *preedit_string, IBusAttrList *attr_list)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IMPreeditCBStruct pcb;
Packit Service 1d8f1c
    XIMText text;
Packit Service 1d8f1c
    XTextProperty tp;
Packit Service 1d8f1c
Packit Service 1d8f1c
    static XIMFeedback *feedback;
Packit Service 1d8f1c
    static gint feedback_len = 0;
Packit Service 1d8f1c
    guint j, i, len;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (preedit_string == NULL)
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
Packit Service 1d8f1c
    len = g_utf8_strlen (preedit_string, -1);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (len + 1 > feedback_len) {
Packit Service 1d8f1c
        feedback_len = (len + 1 + 63) & ~63;
Packit Service 1d8f1c
        if (feedback) {
Packit Service 1d8f1c
            feedback = g_renew (XIMFeedback, feedback, feedback_len);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        else {
Packit Service 1d8f1c
            feedback = g_new (XIMFeedback, feedback_len);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (i = 0; feedback && i < len; i++) {
Packit Service 1d8f1c
        feedback[i] = 0;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (attr_list != NULL) {
Packit Service 1d8f1c
        for (i = 0;; i++) {
Packit Service 1d8f1c
            XIMFeedback attr = 0;
Packit Service 1d8f1c
            IBusAttribute *ibus_attr = ibus_attr_list_get (attr_list, i);
Packit Service 1d8f1c
            if (ibus_attr == NULL) {
Packit Service 1d8f1c
                break;
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            switch (ibus_attr->type) {
Packit Service 1d8f1c
            case IBUS_ATTR_TYPE_UNDERLINE:
Packit Service 1d8f1c
                if (ibus_attr->value == IBUS_ATTR_UNDERLINE_SINGLE) {
Packit Service 1d8f1c
                    attr = XIMUnderline;
Packit Service 1d8f1c
                }
Packit Service 1d8f1c
                break;
Packit Service 1d8f1c
            case IBUS_ATTR_TYPE_BACKGROUND:
Packit Service 1d8f1c
                {
Packit Service 1d8f1c
                    if (ibus_attr->value != 0xffffff) {
Packit Service 1d8f1c
                        attr = XIMReverse;
Packit Service 1d8f1c
                    }
Packit Service 1d8f1c
                    break;
Packit Service 1d8f1c
                }
Packit Service 1d8f1c
            default:
Packit Service 1d8f1c
                continue;
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            for (j = ibus_attr->start_index; j < ibus_attr->end_index; j++) {
Packit Service 1d8f1c
                feedback[j] |= attr;
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (i = 0; i < len; i++) {
Packit Service 1d8f1c
        if (feedback[i] == 0) {
Packit Service 1d8f1c
            feedback[i] = XIMUnderline;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    feedback[len] = 0;
Packit Service 1d8f1c
Packit Service 1d8f1c
    pcb.major_code = XIM_PREEDIT_DRAW;
Packit Service 1d8f1c
    pcb.connect_id = x11ic->connect_id;
Packit Service 1d8f1c
    pcb.icid = x11ic->icid;
Packit Service 1d8f1c
Packit Service 1d8f1c
    pcb.todo.draw.caret = len;
Packit Service 1d8f1c
    pcb.todo.draw.chg_first = 0;
Packit Service 1d8f1c
    pcb.todo.draw.chg_length = x11ic->onspot_preedit_length;
Packit Service 1d8f1c
    pcb.todo.draw.text = &tex;;
Packit Service 1d8f1c
Packit Service 1d8f1c
    text.feedback = feedback;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (len > 0) {
Packit Service 1d8f1c
        Xutf8TextListToTextProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
Packit Service 1d8f1c
                                     (char **)&preedit_string,
Packit Service 1d8f1c
                                     1, XCompoundTextStyle, &tp);
Packit Service 1d8f1c
        text.encoding_is_wchar = 0;
Packit Service 1d8f1c
        text.length = strlen ((char*)tp.value);
Packit Service 1d8f1c
        text.string.multi_byte = (char*)tp.value;
Packit Service 1d8f1c
        IMCallCallback (xims, (XPointer) & pcb);
Packit Service 1d8f1c
        XFree (tp.value);
Packit Service 1d8f1c
    } else {
Packit Service 1d8f1c
        text.encoding_is_wchar = 0;
Packit Service 1d8f1c
        text.length = 0;
Packit Service 1d8f1c
        text.string.multi_byte = "";
Packit Service 1d8f1c
        IMCallCallback (xims, (XPointer) & pcb);
Packit Service 1d8f1c
        len = 0;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    x11ic->onspot_preedit_length = len;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static int
Packit Service 1d8f1c
_xim_store_ic_values (X11IC *x11ic, IMChangeICStruct *call_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    XICAttribute *ic_attr = call_data->ic_attr;
Packit Service 1d8f1c
    XICAttribute *pre_attr = call_data->preedit_attr;
Packit Service 1d8f1c
    XICAttribute *sts_attr = call_data->status_attr;
Packit Service 1d8f1c
Packit Service 1d8f1c
    gint i;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_return_val_if_fail (x11ic != NULL, 0);
Packit Service 1d8f1c
    for (i = 0; i < (int)call_data->ic_attr_num; ++i, ++ic_attr) {
Packit Service 1d8f1c
        if (g_strcmp0 (XNInputStyle, ic_attr->name) == 0) {
Packit Service 1d8f1c
            x11ic->input_style = *(gint32 *) ic_attr->value;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        else if (g_strcmp0 (XNClientWindow, ic_attr->name) == 0) {
Packit Service 1d8f1c
            x11ic->client_window =  (Window)(*(CARD32 *) call_data->ic_attr[i].value);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        else if (g_strcmp0 (XNFocusWindow, ic_attr->name) == 0) {
Packit Service 1d8f1c
            x11ic->focus_window =  (Window)(*(CARD32 *) call_data->ic_attr[i].value);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        else {
Packit Service 1d8f1c
            LOG (1, "Unknown ic attribute: %s", ic_attr->name);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (i = 0; i < (int)call_data->preedit_attr_num; ++i, ++pre_attr) {
Packit Service 1d8f1c
        if (g_strcmp0 (XNSpotLocation, pre_attr->name) == 0) {
Packit Service 1d8f1c
            x11ic->has_preedit_area = TRUE;
Packit Service 1d8f1c
            x11ic->preedit_area.x = ((XPoint *)pre_attr->value)->x;
Packit Service 1d8f1c
            x11ic->preedit_area.y = ((XPoint *)pre_attr->value)->y;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        else {
Packit Service 1d8f1c
            LOG (1, "Unknown preedit attribute: %s", pre_attr->name);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (i=0; i< (int) call_data->status_attr_num; ++i, ++sts_attr) {
Packit Service 1d8f1c
        LOG (1, "Unknown status attribute: %s", sts_attr->name);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return 1;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
static int
Packit Service 1d8f1c
xim_create_ic (XIMS xims, IMChangeICStruct *call_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    static int base_icid = 1;
Packit Service 1d8f1c
    X11IC *x11ic;
Packit Service 1d8f1c
Packit Service 1d8f1c
    call_data->icid = base_icid ++;
Packit Service 1d8f1c
Packit Service 1d8f1c
    LOG (1, "XIM_CREATE_IC ic=%d connect_id=%d",
Packit Service 1d8f1c
                call_data->icid, call_data->connect_id);
Packit Service 1d8f1c
Packit Service 1d8f1c
    x11ic = g_slice_new0 (X11IC);
Packit Service 1d8f1c
    g_return_val_if_fail (x11ic != NULL, 0);
Packit Service 1d8f1c
Packit Service 1d8f1c
    x11ic->icid = call_data->icid;
Packit Service 1d8f1c
    x11ic->connect_id = call_data->connect_id;
Packit Service 1d8f1c
    x11ic->conn = (X11ICONN *)g_hash_table_lookup (_connections,
Packit Service 1d8f1c
                                                   GINT_TO_POINTER ((gint) call_data->connect_id));
Packit Service 1d8f1c
    if (x11ic->conn == NULL) {
Packit Service 1d8f1c
        g_slice_free (X11IC, x11ic);
Packit Service 1d8f1c
        g_return_val_if_reached (0);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    _xim_store_ic_values (x11ic, call_data);
Packit Service 1d8f1c
Packit Service 1d8f1c
    x11ic->context = ibus_bus_create_input_context (_bus, "xim");
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (x11ic->context == NULL) {
Packit Service 1d8f1c
        g_slice_free (X11IC, x11ic);
Packit Service 1d8f1c
        g_return_val_if_reached (0);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_connect (x11ic->context, "commit-text",
Packit Service 1d8f1c
                        G_CALLBACK (_context_commit_text_cb), x11ic);
Packit Service 1d8f1c
    g_signal_connect (x11ic->context, "forward-key-event",
Packit Service 1d8f1c
                        G_CALLBACK (_context_forward_key_event_cb), x11ic);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_connect (x11ic->context, "update-preedit-text",
Packit Service 1d8f1c
                        G_CALLBACK (_context_update_preedit_text_cb), x11ic);
Packit Service 1d8f1c
    g_signal_connect (x11ic->context, "show-preedit-text",
Packit Service 1d8f1c
                        G_CALLBACK (_context_show_preedit_text_cb), x11ic);
Packit Service 1d8f1c
    g_signal_connect (x11ic->context, "hide-preedit-text",
Packit Service 1d8f1c
                        G_CALLBACK (_context_hide_preedit_text_cb), x11ic);
Packit Service 1d8f1c
    g_signal_connect (x11ic->context, "enabled",
Packit Service 1d8f1c
                        G_CALLBACK (_context_enabled_cb), x11ic);
Packit Service 1d8f1c
    g_signal_connect (x11ic->context, "disabled",
Packit Service 1d8f1c
                        G_CALLBACK (_context_disabled_cb), x11ic);
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (x11ic->input_style & XIMPreeditCallbacks) {
Packit Service 1d8f1c
        ibus_input_context_set_capabilities (x11ic->context, IBUS_CAP_FOCUS | IBUS_CAP_PREEDIT_TEXT);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        ibus_input_context_set_capabilities (x11ic->context, IBUS_CAP_FOCUS);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_hash_table_insert (_x11_ic_table,
Packit Service 1d8f1c
                         GINT_TO_POINTER (x11ic->icid), (gpointer)x11ic);
Packit Service 1d8f1c
    x11ic->conn->clients = g_list_append (x11ic->conn->clients,
Packit Service 1d8f1c
                         (gpointer)x11ic);
Packit Service 1d8f1c
    return 1;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
static int
Packit Service 1d8f1c
xim_destroy_ic (XIMS xims, IMChangeICStruct *call_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    X11IC *x11ic;
Packit Service 1d8f1c
Packit Service 1d8f1c
    LOG (1, "XIM_DESTROY_IC ic=%d connect_id=%d",
Packit Service 1d8f1c
                call_data->icid, call_data->connect_id);
Packit Service 1d8f1c
Packit Service 1d8f1c
    x11ic = (X11IC *)g_hash_table_lookup (_x11_ic_table,
Packit Service 1d8f1c
                                          GINT_TO_POINTER ((gint) call_data->icid));
Packit Service 1d8f1c
    g_return_val_if_fail (x11ic != NULL, 0);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (x11ic->context) {
Packit Service 1d8f1c
        ibus_proxy_destroy ((IBusProxy *)x11ic->context);
Packit Service 1d8f1c
        g_object_unref (x11ic->context);
Packit Service 1d8f1c
        x11ic->context = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_hash_table_remove (_x11_ic_table,
Packit Service 1d8f1c
                         GINT_TO_POINTER ((gint) call_data->icid));
Packit Service 1d8f1c
    x11ic->conn->clients = g_list_remove (x11ic->conn->clients, (gconstpointer)x11ic);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_free (x11ic->preedit_string);
Packit Service 1d8f1c
    x11ic->preedit_string = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (x11ic->preedit_attrs) {
Packit Service 1d8f1c
        g_object_unref (x11ic->preedit_attrs);
Packit Service 1d8f1c
        x11ic->preedit_attrs = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_slice_free (X11IC, x11ic);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return 1;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static int
Packit Service 1d8f1c
xim_set_ic_focus (XIMS xims, IMChangeFocusStruct *call_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    X11IC *x11ic;
Packit Service 1d8f1c
Packit Service 1d8f1c
    LOG (1, "XIM_SET_IC_FOCUS ic=%d connect_id=%d",
Packit Service 1d8f1c
                call_data->icid, call_data->connect_id);
Packit Service 1d8f1c
Packit Service 1d8f1c
    x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
Packit Service 1d8f1c
                                           GINT_TO_POINTER ((gint) call_data->icid));
Packit Service 1d8f1c
    g_return_val_if_fail (x11ic != NULL, 0);
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_input_context_focus_in (x11ic->context);
Packit Service 1d8f1c
    _xim_set_cursor_location (x11ic);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return 1;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static int
Packit Service 1d8f1c
xim_unset_ic_focus (XIMS xims, IMChangeFocusStruct *call_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    X11IC *x11ic;
Packit Service 1d8f1c
Packit Service 1d8f1c
    LOG (1, "XIM_UNSET_IC_FOCUS ic=%d connect_id=%d",
Packit Service 1d8f1c
                call_data->icid, call_data->connect_id);
Packit Service 1d8f1c
Packit Service 1d8f1c
    x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
Packit Service 1d8f1c
                                           GINT_TO_POINTER ((gint) call_data->icid));
Packit Service 1d8f1c
    g_return_val_if_fail (x11ic != NULL, 0);
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_input_context_focus_out (x11ic->context);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return 1;
Packit Service 1d8f1c
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_process_key_event_done (GObject      *object,
Packit Service 1d8f1c
                         GAsyncResult *res,
Packit Service 1d8f1c
                         gpointer      user_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IBusInputContext *context = (IBusInputContext *)object;
Packit Service 1d8f1c
    IMForwardEventStruct *pfe = (IMForwardEventStruct*) user_data;
Packit Service 1d8f1c
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    gboolean retval = ibus_input_context_process_key_event_async_finish (
Packit Service 1d8f1c
            context,
Packit Service 1d8f1c
            res,
Packit Service 1d8f1c
            &error);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (error != NULL) {
Packit Service 1d8f1c
        g_warning ("Process Key Event failed: %s.", error->message);
Packit Service 1d8f1c
        g_error_free (error);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_hash_table_lookup (_connections,
Packit Service 1d8f1c
                             GINT_TO_POINTER ((gint) pfe->connect_id))
Packit Service 1d8f1c
        == NULL) {
Packit Service 1d8f1c
        g_slice_free (IMForwardEventStruct, pfe);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (retval == FALSE) {
Packit Service 1d8f1c
        IMForwardEvent (_xims, (XPointer) pfe);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_slice_free (IMForwardEventStruct, pfe);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static int
Packit Service 1d8f1c
xim_forward_event (XIMS xims, IMForwardEventStruct *call_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    X11IC *x11ic;
Packit Service 1d8f1c
    XKeyEvent *xevent;
Packit Service 1d8f1c
    GdkEventKey event;
Packit Service 1d8f1c
    gboolean retval;
Packit Service 1d8f1c
Packit Service 1d8f1c
    LOG (1, "XIM_FORWARD_EVENT ic=%d connect_id=%d",
Packit Service 1d8f1c
                call_data->icid, call_data->connect_id);
Packit Service 1d8f1c
Packit Service 1d8f1c
    x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
Packit Service 1d8f1c
                                           GINT_TO_POINTER ((gint) call_data->icid));
Packit Service 1d8f1c
    g_return_val_if_fail (x11ic != NULL, 0);
Packit Service 1d8f1c
Packit Service 1d8f1c
    xevent = (XKeyEvent*) &(call_data->event);
Packit Service 1d8f1c
Packit Service 1d8f1c
    translate_key_event (gdk_display_get_default (),
Packit Service 1d8f1c
        (GdkEvent *)&event, (XEvent *)xevent);
Packit Service 1d8f1c
Packit Service 1d8f1c
    event.send_event = xevent->send_event;
Packit Service 1d8f1c
    event.window = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (event.type == GDK_KEY_RELEASE) {
Packit Service 1d8f1c
        event.state |= IBUS_RELEASE_MASK;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (_use_sync_mode) {
Packit Service 1d8f1c
        retval = ibus_input_context_process_key_event (
Packit Service 1d8f1c
                                      x11ic->context,
Packit Service 1d8f1c
                                      event.keyval,
Packit Service 1d8f1c
                                      event.hardware_keycode - 8,
Packit Service 1d8f1c
                                      event.state);
Packit Service 1d8f1c
        if (retval) {
Packit Service 1d8f1c
            if (! x11ic->has_preedit_area) {
Packit Service 1d8f1c
                _xim_set_cursor_location (x11ic);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            return 1;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
Packit Service 1d8f1c
        IMForwardEventStruct fe;
Packit Service 1d8f1c
        memset (&fe, 0, sizeof (fe));
Packit Service 1d8f1c
Packit Service 1d8f1c
        fe.major_code = XIM_FORWARD_EVENT;
Packit Service 1d8f1c
        fe.icid = x11ic->icid;
Packit Service 1d8f1c
        fe.connect_id = x11ic->connect_id;
Packit Service 1d8f1c
        fe.sync_bit = 0;
Packit Service 1d8f1c
        fe.serial_number = 0L;
Packit Service 1d8f1c
        fe.event = call_data->event;
Packit Service 1d8f1c
Packit Service 1d8f1c
        IMForwardEvent (_xims, (XPointer) &fe);
Packit Service 1d8f1c
Packit Service 1d8f1c
        retval = 1;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        IMForwardEventStruct *pfe;
Packit Service 1d8f1c
Packit Service 1d8f1c
        pfe = g_slice_new0 (IMForwardEventStruct);
Packit Service 1d8f1c
        pfe->major_code = XIM_FORWARD_EVENT;
Packit Service 1d8f1c
        pfe->icid = x11ic->icid;
Packit Service 1d8f1c
        pfe->connect_id = x11ic->connect_id;
Packit Service 1d8f1c
        pfe->sync_bit = 0;
Packit Service 1d8f1c
        pfe->serial_number = 0L;
Packit Service 1d8f1c
        pfe->event = call_data->event;
Packit Service 1d8f1c
Packit Service 1d8f1c
        ibus_input_context_process_key_event_async (
Packit Service 1d8f1c
                                      x11ic->context,
Packit Service 1d8f1c
                                      event.keyval,
Packit Service 1d8f1c
                                      event.hardware_keycode - 8,
Packit Service 1d8f1c
                                      event.state,
Packit Service 1d8f1c
                                      -1,
Packit Service 1d8f1c
                                      NULL,
Packit Service 1d8f1c
                                      _process_key_event_done,
Packit Service 1d8f1c
                                      pfe);
Packit Service 1d8f1c
        retval = 1;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    return retval;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
static int
Packit Service 1d8f1c
xim_open (XIMS xims, IMOpenStruct *call_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    X11ICONN *conn;
Packit Service 1d8f1c
Packit Service 1d8f1c
    LOG (1, "XIM_OPEN connect_id=%d",
Packit Service 1d8f1c
                call_data->connect_id);
Packit Service 1d8f1c
Packit Service 1d8f1c
    conn = (X11ICONN *) g_hash_table_lookup (_connections,
Packit Service 1d8f1c
                                             GINT_TO_POINTER ((gint) call_data->connect_id));
Packit Service 1d8f1c
    g_return_val_if_fail (conn == NULL, 0);
Packit Service 1d8f1c
Packit Service 1d8f1c
    conn = g_slice_new0 (X11ICONN);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_hash_table_insert (_connections,
Packit Service 1d8f1c
        (gpointer)(unsigned long)call_data->connect_id,
Packit Service 1d8f1c
        (gpointer) conn);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return 1;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_free_ic (gpointer data, gpointer user_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    X11IC *x11ic = (X11IC *) data;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_return_if_fail (x11ic != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_free (x11ic->preedit_string);
Packit Service 1d8f1c
    x11ic->preedit_string = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (x11ic->preedit_attrs) {
Packit Service 1d8f1c
        g_object_unref (x11ic->preedit_attrs);
Packit Service 1d8f1c
        x11ic->preedit_attrs = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (x11ic->context) {
Packit Service 1d8f1c
        ibus_proxy_destroy ((IBusProxy *)x11ic->context);
Packit Service 1d8f1c
        g_object_unref (x11ic->context);
Packit Service 1d8f1c
        x11ic->context = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* Remove the IC from g_client dictionary */
Packit Service 1d8f1c
    g_hash_table_remove (_x11_ic_table,
Packit Service 1d8f1c
                         GINT_TO_POINTER (x11ic->icid));
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_slice_free (X11IC, x11ic);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static int
Packit Service 1d8f1c
_free_x11_iconn_from_id (CARD16 connect_id)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    X11ICONN *conn;
Packit Service 1d8f1c
Packit Service 1d8f1c
    conn = (X11ICONN *) g_hash_table_lookup (_connections,
Packit Service 1d8f1c
                                             GINT_TO_POINTER ((gint) connect_id));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (conn == NULL) {
Packit Service 1d8f1c
        return 0;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_list_free_full (conn->clients, (GDestroyNotify) _free_ic);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_hash_table_remove (_connections,
Packit Service 1d8f1c
                         GINT_TO_POINTER ((gint) connect_id));
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_slice_free (X11ICONN, conn);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return 1;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static int
Packit Service 1d8f1c
xim_close (XIMS xims, IMCloseStruct *call_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    CARD16 connect_id = call_data->connect_id;
Packit Service 1d8f1c
Packit Service 1d8f1c
    LOG (1, "XIM_CLOSE connect_id=%d", connect_id);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return _free_x11_iconn_from_id (connect_id);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static int
Packit Service 1d8f1c
xim_disconnect_ic (XIMS xims, IMDisConnectStruct *call_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    CARD16 connect_id = call_data->connect_id;
Packit Service 1d8f1c
Packit Service 1d8f1c
    LOG (1, "XIM_DISCONNECT connect_id=%d", connect_id);
Packit Service 1d8f1c
Packit Service 1d8f1c
    _free_x11_iconn_from_id (connect_id);
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* I am not sure if this can return 1 because I have not experienced
Packit Service 1d8f1c
     * that xim_disconnect_ic() is called. But I wish connect_id is
Packit Service 1d8f1c
     * released from _connections to avoid SEGV. */
Packit Service 1d8f1c
    return 0;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_xim_set_cursor_location (X11IC *x11ic)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_if_fail (x11ic != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    GdkRectangle preedit_area = x11ic->preedit_area;
Packit Service 1d8f1c
Packit Service 1d8f1c
    Window w = x11ic->focus_window ?
Packit Service 1d8f1c
        x11ic->focus_window :x11ic->client_window;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (w) {
Packit Service 1d8f1c
        XWindowAttributes xwa;
Packit Service 1d8f1c
        Window child;
Packit Service 1d8f1c
Packit Service 1d8f1c
        XGetWindowAttributes (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), w, &xwa;;
Packit Service 1d8f1c
        if (preedit_area.x <= 0 && preedit_area.y <= 0) {
Packit Service 1d8f1c
             XTranslateCoordinates (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), w,
Packit Service 1d8f1c
                xwa.root,
Packit Service 1d8f1c
                0,
Packit Service 1d8f1c
                xwa.height,
Packit Service 1d8f1c
                &preedit_area.x,
Packit Service 1d8f1c
                &preedit_area.y,
Packit Service 1d8f1c
                &child);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        else {
Packit Service 1d8f1c
            XTranslateCoordinates (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), w,
Packit Service 1d8f1c
                xwa.root,
Packit Service 1d8f1c
                preedit_area.x,
Packit Service 1d8f1c
                preedit_area.y,
Packit Service 1d8f1c
                &preedit_area.x,
Packit Service 1d8f1c
                &preedit_area.y,
Packit Service 1d8f1c
                &child);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_input_context_set_cursor_location (x11ic->context,
Packit Service 1d8f1c
            preedit_area.x,
Packit Service 1d8f1c
            preedit_area.y,
Packit Service 1d8f1c
            preedit_area.width,
Packit Service 1d8f1c
            preedit_area.height);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
static int
Packit Service 1d8f1c
xim_set_ic_values (XIMS xims, IMChangeICStruct *call_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    X11IC *x11ic;
Packit Service 1d8f1c
    gint i;
Packit Service 1d8f1c
Packit Service 1d8f1c
    LOG (1, "XIM_SET_IC_VALUES ic=%d connect_id=%d",
Packit Service 1d8f1c
                call_data->icid, call_data->connect_id);
Packit Service 1d8f1c
Packit Service 1d8f1c
    x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
Packit Service 1d8f1c
                                           GINT_TO_POINTER ((gint) call_data->icid));
Packit Service 1d8f1c
    g_return_val_if_fail (x11ic != NULL, 0);
Packit Service 1d8f1c
Packit Service 1d8f1c
    i = _xim_store_ic_values (x11ic, call_data);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (i) {
Packit Service 1d8f1c
        _xim_set_cursor_location (x11ic);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return 1;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static int
Packit Service 1d8f1c
xim_get_ic_values (XIMS xims, IMChangeICStruct *call_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    X11IC *x11ic;
Packit Service 1d8f1c
    gint i;
Packit Service 1d8f1c
Packit Service 1d8f1c
    LOG (1, "XIM_GET_IC_VALUES ic=%d connect_id=%d",
Packit Service 1d8f1c
                call_data->icid, call_data->connect_id);
Packit Service 1d8f1c
Packit Service 1d8f1c
    x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
Packit Service 1d8f1c
                                           GINT_TO_POINTER ((gint) call_data->icid));
Packit Service 1d8f1c
    g_return_val_if_fail (x11ic != NULL, 0);
Packit Service 1d8f1c
Packit Service 1d8f1c
    XICAttribute *ic_attr = call_data->ic_attr;
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (i = 0; i < (int) call_data->ic_attr_num; ++i, ++ic_attr) {
Packit Service 1d8f1c
        if (g_strcmp0 (XNFilterEvents, ic_attr->name) == 0) {
Packit Service 1d8f1c
            ic_attr->value = (void *) malloc (sizeof (CARD32));
Packit Service 1d8f1c
            *(CARD32 *) ic_attr->value = KeyPressMask | KeyReleaseMask;
Packit Service 1d8f1c
            ic_attr->value_length = sizeof (CARD32);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return 1;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
static int
Packit Service 1d8f1c
xim_reset_ic (XIMS xims, IMResetICStruct *call_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    X11IC *x11ic;
Packit Service 1d8f1c
Packit Service 1d8f1c
    LOG (1, "XIM_RESET_IC ic=%d connect_id=%d",
Packit Service 1d8f1c
                call_data->icid, call_data->connect_id);
Packit Service 1d8f1c
Packit Service 1d8f1c
    x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
Packit Service 1d8f1c
                                           GINT_TO_POINTER ((gint) call_data->icid));
Packit Service 1d8f1c
    g_return_val_if_fail (x11ic != NULL, 0);
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_input_context_reset (x11ic->context);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return 1;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
int
Packit Service 1d8f1c
ims_protocol_handler (XIMS xims, IMProtocol *call_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_val_if_fail (xims != NULL, 1);
Packit Service 1d8f1c
    g_return_val_if_fail (call_data != NULL, 1);
Packit Service 1d8f1c
Packit Service 1d8f1c
    switch (call_data->major_code) {
Packit Service 1d8f1c
    case XIM_OPEN:
Packit Service 1d8f1c
        return xim_open (xims, (IMOpenStruct *)call_data);
Packit Service 1d8f1c
    case XIM_CLOSE:
Packit Service 1d8f1c
        return xim_close (xims, (IMCloseStruct *)call_data);
Packit Service 1d8f1c
    case XIM_DISCONNECT:
Packit Service 1d8f1c
        return xim_disconnect_ic (xims, (IMDisConnectStruct *)call_data);
Packit Service 1d8f1c
    case XIM_CREATE_IC:
Packit Service 1d8f1c
        return xim_create_ic (xims, (IMChangeICStruct *)call_data);
Packit Service 1d8f1c
    case XIM_DESTROY_IC:
Packit Service 1d8f1c
        return xim_destroy_ic (xims, (IMChangeICStruct *)call_data);
Packit Service 1d8f1c
    case XIM_SET_IC_VALUES:
Packit Service 1d8f1c
        return xim_set_ic_values (xims, (IMChangeICStruct *)call_data);
Packit Service 1d8f1c
    case XIM_GET_IC_VALUES:
Packit Service 1d8f1c
        return xim_get_ic_values (xims, (IMChangeICStruct *)call_data);
Packit Service 1d8f1c
    case XIM_FORWARD_EVENT:
Packit Service 1d8f1c
        return xim_forward_event (xims, (IMForwardEventStruct *)call_data);
Packit Service 1d8f1c
    case XIM_SET_IC_FOCUS:
Packit Service 1d8f1c
        return xim_set_ic_focus (xims, (IMChangeFocusStruct *)call_data);
Packit Service 1d8f1c
    case XIM_UNSET_IC_FOCUS:
Packit Service 1d8f1c
        return xim_unset_ic_focus (xims, (IMChangeFocusStruct *)call_data);
Packit Service 1d8f1c
    case XIM_RESET_IC:
Packit Service 1d8f1c
        return xim_reset_ic (xims, (IMResetICStruct *)call_data);
Packit Service 1d8f1c
    case XIM_TRIGGER_NOTIFY:
Packit Service 1d8f1c
        LOG (1, "XIM_TRIGGER_NOTIFY");
Packit Service 1d8f1c
        return 0;
Packit Service 1d8f1c
    case XIM_PREEDIT_START_REPLY:
Packit Service 1d8f1c
        LOG (1, "XIM_PREEDIT_START_REPLY");
Packit Service 1d8f1c
        return 0;
Packit Service 1d8f1c
    case XIM_PREEDIT_CARET_REPLY:
Packit Service 1d8f1c
        LOG (1, "XIM_PREEDIT_CARET_REPLY");
Packit Service 1d8f1c
        return 0;
Packit Service 1d8f1c
    case XIM_SYNC_REPLY:
Packit Service 1d8f1c
        LOG (1, "XIM_SYNC_REPLY");
Packit Service 1d8f1c
        return 0;
Packit Service 1d8f1c
    default:
Packit Service 1d8f1c
        LOG (1, "Unknown (%d)", call_data->major_code);
Packit Service 1d8f1c
        return 0;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_xim_forward_key_event (X11IC   *x11ic,
Packit Service 1d8f1c
                        guint    keyval,
Packit Service 1d8f1c
                        guint    keycode,
Packit Service 1d8f1c
                        guint    state)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_if_fail (x11ic != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    IMForwardEventStruct fe = {0};
Packit Service 1d8f1c
    XEvent xkp = {0};
Packit Service 1d8f1c
Packit Service 1d8f1c
    xkp.xkey.type = (state & IBUS_RELEASE_MASK) ? KeyRelease : KeyPress;
Packit Service 1d8f1c
    xkp.xkey.serial = 0L;
Packit Service 1d8f1c
    xkp.xkey.send_event = False;
Packit Service 1d8f1c
    xkp.xkey.same_screen = True;
Packit Service 1d8f1c
    xkp.xkey.display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
Packit Service 1d8f1c
    xkp.xkey.window =
Packit Service 1d8f1c
        x11ic->focus_window ? x11ic->focus_window : x11ic->client_window;
Packit Service 1d8f1c
    xkp.xkey.subwindow = None;
Packit Service 1d8f1c
    xkp.xkey.root = DefaultRootWindow (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
Packit Service 1d8f1c
Packit Service 1d8f1c
    xkp.xkey.time = 0;
Packit Service 1d8f1c
    xkp.xkey.state = state;
Packit Service 1d8f1c
    xkp.xkey.keycode = (keycode == 0) ? 0 : keycode + 8;
Packit Service 1d8f1c
Packit Service 1d8f1c
    fe.major_code = XIM_FORWARD_EVENT;
Packit Service 1d8f1c
    fe.icid = x11ic->icid;
Packit Service 1d8f1c
    fe.connect_id = x11ic->connect_id;
Packit Service 1d8f1c
    fe.sync_bit = 0;
Packit Service 1d8f1c
    fe.serial_number = 0L;
Packit Service 1d8f1c
    fe.event = xkp;
Packit Service 1d8f1c
Packit Service 1d8f1c
    IMForwardEvent (_xims, (XPointer) & fe);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_bus_disconnected_cb (IBusBus  *bus,
Packit Service 1d8f1c
                      gpointer  user_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_warning ("Connection closed by ibus-daemon");
Packit Service 1d8f1c
    g_object_unref (_bus);
Packit Service 1d8f1c
    _bus = NULL;
Packit Service 1d8f1c
    exit(EXIT_SUCCESS);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_context_commit_text_cb (IBusInputContext *context,
Packit Service 1d8f1c
                         IBusText         *text,
Packit Service 1d8f1c
                         X11IC            *x11ic)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (IBUS_IS_INPUT_CONTEXT (context));
Packit Service 1d8f1c
    g_assert (IBUS_IS_TEXT (text));
Packit Service 1d8f1c
    g_assert (x11ic != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    XTextProperty tp;
Packit Service 1d8f1c
    IMCommitStruct cms = {0};
Packit Service 1d8f1c
Packit Service 1d8f1c
    Xutf8TextListToTextProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
Packit Service 1d8f1c
        (gchar **)&(text->text), 1, XCompoundTextStyle, &tp);
Packit Service 1d8f1c
Packit Service 1d8f1c
    cms.major_code = XIM_COMMIT;
Packit Service 1d8f1c
    cms.icid = x11ic->icid;
Packit Service 1d8f1c
    cms.connect_id = x11ic->connect_id;
Packit Service 1d8f1c
    cms.flag = XimLookupChars;
Packit Service 1d8f1c
    cms.commit_string = (gchar *)tp.value;
Packit Service 1d8f1c
    IMCommitString (_xims, (XPointer) & cms);
Packit Service 1d8f1c
Packit Service 1d8f1c
    XFree (tp.value);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_context_forward_key_event_cb (IBusInputContext *context,
Packit Service 1d8f1c
                               guint             keyval,
Packit Service 1d8f1c
                               guint             keycode,
Packit Service 1d8f1c
                               guint             state,
Packit Service 1d8f1c
                               X11IC            *x11ic)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (x11ic);
Packit Service 1d8f1c
Packit Service 1d8f1c
    _xim_forward_key_event (x11ic, keyval, keycode, state);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_update_preedit (X11IC *x11ic)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (x11ic->preedit_visible == FALSE && x11ic->preedit_started == TRUE) {
Packit Service 1d8f1c
        _xim_preedit_callback_draw (_xims, x11ic, "", NULL);
Packit Service 1d8f1c
        _xim_preedit_callback_done (_xims, x11ic);
Packit Service 1d8f1c
        x11ic->preedit_started = FALSE;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (x11ic->preedit_visible == TRUE && x11ic->preedit_started == FALSE) {
Packit Service 1d8f1c
        _xim_preedit_callback_start (_xims, x11ic);
Packit Service 1d8f1c
        x11ic->preedit_started = TRUE;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    if (x11ic->preedit_visible == TRUE) {
Packit Service 1d8f1c
        _xim_preedit_callback_draw (_xims, x11ic,
Packit Service 1d8f1c
            x11ic->preedit_string, x11ic->preedit_attrs);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_context_update_preedit_text_cb (IBusInputContext *context,
Packit Service 1d8f1c
                                 IBusText         *text,
Packit Service 1d8f1c
                                 gint              cursor_pos,
Packit Service 1d8f1c
                                 gboolean          visible,
Packit Service 1d8f1c
                                 X11IC            *x11ic)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (IBUS_IS_INPUT_CONTEXT (context));
Packit Service 1d8f1c
    g_assert (IBUS_IS_TEXT (text));
Packit Service 1d8f1c
    g_assert (x11ic);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (x11ic->preedit_string) {
Packit Service 1d8f1c
        g_free(x11ic->preedit_string);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    x11ic->preedit_string = g_strdup(text->text);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (x11ic->preedit_attrs) {
Packit Service 1d8f1c
        g_object_unref (x11ic->preedit_attrs);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_object_ref(text->attrs);
Packit Service 1d8f1c
    x11ic->preedit_attrs = text->attrs;
Packit Service 1d8f1c
Packit Service 1d8f1c
    x11ic->preedit_cursor = cursor_pos;
Packit Service 1d8f1c
    x11ic->preedit_visible = visible;
Packit Service 1d8f1c
Packit Service 1d8f1c
    _update_preedit (x11ic);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_context_show_preedit_text_cb (IBusInputContext *context,
Packit Service 1d8f1c
                               X11IC            *x11ic)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (IBUS_IS_INPUT_CONTEXT (context));
Packit Service 1d8f1c
    g_assert (x11ic);
Packit Service 1d8f1c
Packit Service 1d8f1c
    x11ic->preedit_visible = TRUE;
Packit Service 1d8f1c
    _update_preedit (x11ic);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_context_hide_preedit_text_cb (IBusInputContext *context,
Packit Service 1d8f1c
                               X11IC            *x11ic)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (IBUS_IS_INPUT_CONTEXT (context));
Packit Service 1d8f1c
    g_assert (x11ic);
Packit Service 1d8f1c
Packit Service 1d8f1c
    x11ic->preedit_visible = FALSE;
Packit Service 1d8f1c
    _update_preedit (x11ic);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_context_enabled_cb (IBusInputContext *context,
Packit Service 1d8f1c
                    X11IC            *x11ic)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (IBUS_IS_INPUT_CONTEXT (context));
Packit Service 1d8f1c
    g_assert (x11ic);
Packit Service 1d8f1c
Packit Service 1d8f1c
    _xim_preedit_start (_xims, x11ic);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_context_disabled_cb (IBusInputContext *context,
Packit Service 1d8f1c
                    X11IC            *x11ic)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (IBUS_IS_INPUT_CONTEXT (context));
Packit Service 1d8f1c
    g_assert (x11ic);
Packit Service 1d8f1c
Packit Service 1d8f1c
    _xim_preedit_end (_xims, x11ic);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
_get_boolean_env(const gchar *name,
Packit Service 1d8f1c
                 gboolean     defval)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    const gchar *value = g_getenv (name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (value == NULL)
Packit Service 1d8f1c
      return defval;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (value, "") == 0 ||
Packit Service 1d8f1c
        g_strcmp0 (value, "0") == 0 ||
Packit Service 1d8f1c
        g_strcmp0 (value, "false") == 0 ||
Packit Service 1d8f1c
        g_strcmp0 (value, "False") == 0 ||
Packit Service 1d8f1c
        g_strcmp0 (value, "FALSE") == 0)
Packit Service 1d8f1c
      return FALSE;
Packit Service 1d8f1c
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_init_ibus (void)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (_bus != NULL)
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_init ();
Packit Service 1d8f1c
Packit Service 1d8f1c
    _bus = ibus_bus_new ();
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_connect (_bus, "disconnected",
Packit Service 1d8f1c
                        G_CALLBACK (_bus_disconnected_cb), NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* https://github.com/ibus/ibus/issues/1713 */
Packit Service 1d8f1c
    _use_sync_mode = _get_boolean_env ("IBUS_ENABLE_SYNC_MODE", TRUE);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_xim_init_IMdkit ()
Packit Service 1d8f1c
{
Packit Service 1d8f1c
#if 0
Packit Service 1d8f1c
    XIMStyle ims_styles_overspot [] = {
Packit Service 1d8f1c
        XIMPreeditPosition  | XIMStatusNothing,
Packit Service 1d8f1c
        XIMPreeditNothing   | XIMStatusNothing,
Packit Service 1d8f1c
        XIMPreeditPosition  | XIMStatusCallbacks,
Packit Service 1d8f1c
        XIMPreeditNothing   | XIMStatusCallbacks,
Packit Service 1d8f1c
        0
Packit Service 1d8f1c
    };
Packit Service 1d8f1c
#endif
Packit Service 1d8f1c
Packit Service 1d8f1c
    XIMStyle ims_styles_onspot [] = {
Packit Service 1d8f1c
        XIMPreeditPosition  | XIMStatusNothing,
Packit Service 1d8f1c
        XIMPreeditCallbacks | XIMStatusNothing,
Packit Service 1d8f1c
        XIMPreeditNothing   | XIMStatusNothing,
Packit Service 1d8f1c
        XIMPreeditPosition  | XIMStatusCallbacks,
Packit Service 1d8f1c
        XIMPreeditCallbacks | XIMStatusCallbacks,
Packit Service 1d8f1c
        XIMPreeditNothing   | XIMStatusCallbacks,
Packit Service 1d8f1c
        0
Packit Service 1d8f1c
    };
Packit Service 1d8f1c
Packit Service 1d8f1c
    XIMEncoding ims_encodings[] = {
Packit Service 1d8f1c
        "COMPOUND_TEXT",
Packit Service 1d8f1c
        0
Packit Service 1d8f1c
    };
Packit Service 1d8f1c
Packit Service 1d8f1c
    GdkWindowAttr window_attr = {
Packit Service 1d8f1c
        .title              = "ibus-xim",
Packit Service 1d8f1c
        .event_mask         = GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
Packit Service 1d8f1c
        .wclass             = GDK_INPUT_OUTPUT,
Packit Service 1d8f1c
        .window_type        = GDK_WINDOW_TOPLEVEL,
Packit Service 1d8f1c
        .override_redirect   = 1,
Packit Service 1d8f1c
    };
Packit Service 1d8f1c
Packit Service 1d8f1c
    XIMStyles styles;
Packit Service 1d8f1c
    XIMEncodings encodings;
Packit Service 1d8f1c
Packit Service 1d8f1c
    GdkWindow *win;
Packit Service 1d8f1c
Packit Service 1d8f1c
    win = gdk_window_new (NULL, &window_attr, GDK_WA_TITLE);
Packit Service 1d8f1c
Packit Service 1d8f1c
    styles.count_styles =
Packit Service 1d8f1c
        sizeof (ims_styles_onspot)/sizeof (XIMStyle) - 1;
Packit Service 1d8f1c
    styles.supported_styles = ims_styles_onspot;
Packit Service 1d8f1c
Packit Service 1d8f1c
    encodings.count_encodings =
Packit Service 1d8f1c
        sizeof (ims_encodings)/sizeof (XIMEncoding) - 1;
Packit Service 1d8f1c
    encodings.supported_encodings = ims_encodings;
Packit Service 1d8f1c
Packit Service 1d8f1c
    _xims = IMOpenIM (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
Packit Service 1d8f1c
        IMModifiers, "Xi18n",
Packit Service 1d8f1c
#if GTK_CHECK_VERSION (3, 0, 0)
Packit Service 1d8f1c
        IMServerWindow, GDK_WINDOW_XID (win),
Packit Service 1d8f1c
#else
Packit Service 1d8f1c
        IMServerWindow, GDK_WINDOW_XWINDOW (win),
Packit Service 1d8f1c
#endif
Packit Service 1d8f1c
        IMServerName, _server_name != NULL ? _server_name : "ibus",
Packit Service 1d8f1c
        IMLocale, _locale != NULL ? _locale : LOCALES_STRING,
Packit Service 1d8f1c
        IMServerTransport, "X/",
Packit Service 1d8f1c
        IMInputStyles, &styles,
Packit Service 1d8f1c
        IMEncodingList, &encodings,
Packit Service 1d8f1c
        IMProtocolHandler, ims_protocol_handler,
Packit Service 1d8f1c
        IMFilterEventMask, KeyPressMask | KeyReleaseMask,
Packit Service 1d8f1c
        NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    _init_ibus ();
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!ibus_bus_is_connected (_bus)) {
Packit Service 1d8f1c
        g_warning ("Can not connect to ibus daemon");
Packit Service 1d8f1c
        exit (EXIT_FAILURE);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_atexit_cb ()
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (_bus && ibus_bus_is_connected (_bus)) {
Packit Service 1d8f1c
        ibus_bus_exit(_bus, False);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_sighandler (int sig)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    exit(EXIT_FAILURE);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_print_usage (FILE *fp, gchar *name)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    fprintf (fp,
Packit Service 1d8f1c
        "Usage:\n"
Packit Service 1d8f1c
        " %s --help               Show this message\n"
Packit Service 1d8f1c
        "    --server-name= -n    Setup xim sevrer name\n"
Packit Service 1d8f1c
        "    --locale= -l         Setup support locales\n"
Packit Service 1d8f1c
        "    --locale-append= -a  Append locales into the default support locales\n"
Packit Service 1d8f1c
        "    --kill-daemon -k     Kill ibus daemon when exit\n"
Packit Service 1d8f1c
        "    --debug= -v          Setup debug level\n",
Packit Service 1d8f1c
        name);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static int
Packit Service 1d8f1c
_xerror_handler (Display *dpy, XErrorEvent *e)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_debug (
Packit Service 1d8f1c
        "XError: "
Packit Service 1d8f1c
        "serial=%lu error_code=%d request_code=%d minor_code=%d resourceid=%lu",
Packit Service 1d8f1c
        e->serial, e->error_code, e->request_code, e->minor_code, e->resourceid);
Packit Service 1d8f1c
    return 1;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/* When log into GNOME3 desktop immediately after the system is booted,
Packit Service 1d8f1c
 * ibus-daemon is sometimes alive but ibus-x11 is dead after log out
Packit Service 1d8f1c
 * the session. Because gdk_x_io_error() is called as the callback of
Packit Service 1d8f1c
 * XSetIOErrorHandler() in gtk/gdk/x11/gdkmain-x11.c in ibus-x11.
Packit Service 1d8f1c
 * Now I assume the callback is called in logout.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static int
Packit Service 1d8f1c
_xerror_io_handler (Display *dpy)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (_kill_daemon)
Packit Service 1d8f1c
        _atexit_cb ();
Packit Service 1d8f1c
    return 0;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
int
Packit Service 1d8f1c
main (int argc, char **argv)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    gint option_index = 0;
Packit Service 1d8f1c
    gint c;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* GDK_DISPLAY_XDISPLAY() and GDK_WINDOW_XID() does not work
Packit Service 1d8f1c
     * with GdkWaylandDisplay.
Packit Service 1d8f1c
     */
Packit Service 1d8f1c
#if GTK_CHECK_VERSION (3, 10, 0)
Packit Service 1d8f1c
    gdk_set_allowed_backends ("x11");
Packit Service 1d8f1c
#endif
Packit Service 1d8f1c
Packit Service 1d8f1c
    gtk_init (&argc, &argv);
Packit Service 1d8f1c
    XSetErrorHandler (_xerror_handler);
Packit Service 1d8f1c
    XSetIOErrorHandler (_xerror_io_handler);
Packit Service 1d8f1c
Packit Service 1d8f1c
    while (1) {
Packit Service 1d8f1c
        static struct option long_options [] = {
Packit Service 1d8f1c
            { "debug", 1, 0, 0},
Packit Service 1d8f1c
            { "server-name", 1, 0, 0},
Packit Service 1d8f1c
            { "locale", 1, 0, 0},
Packit Service 1d8f1c
            { "locale-append", 1, 0, 0},
Packit Service 1d8f1c
            { "help", 0, 0, 0},
Packit Service 1d8f1c
            { "kill-daemon", 0, 0, 0},
Packit Service 1d8f1c
            { 0, 0, 0, 0},
Packit Service 1d8f1c
        };
Packit Service 1d8f1c
Packit Service 1d8f1c
        c = getopt_long (argc, argv, "v:n:l:k:a",
Packit Service 1d8f1c
            long_options, &option_index);
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (c == -1) break;
Packit Service 1d8f1c
Packit Service 1d8f1c
        switch (c) {
Packit Service 1d8f1c
        case 0:
Packit Service 1d8f1c
            if (g_strcmp0 (long_options[option_index].name, "debug") == 0) {
Packit Service 1d8f1c
                g_debug_level = atoi (optarg);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            else if (g_strcmp0 (long_options[option_index].name, "server-name") == 0) {
Packit Service 1d8f1c
                g_free (_server_name);
Packit Service 1d8f1c
                _server_name = g_strdup (optarg);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            else if (g_strcmp0 (long_options[option_index].name, "locale") == 0) {
Packit Service 1d8f1c
                g_free (_locale);
Packit Service 1d8f1c
                _locale = g_strdup (optarg);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            else if (g_strcmp0 (long_options[option_index].name, "locale-append") == 0) {
Packit Service 1d8f1c
                gchar *tmp = g_strdup_printf ("%s,%s",
Packit Service 1d8f1c
                                _locale != NULL ? _locale : LOCALES_STRING, optarg);
Packit Service 1d8f1c
                g_free (_locale);
Packit Service 1d8f1c
                _locale = tmp;
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            else if (g_strcmp0 (long_options[option_index].name, "help") == 0) {
Packit Service 1d8f1c
                _print_usage (stdout, argv[0]);
Packit Service 1d8f1c
                exit (EXIT_SUCCESS);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            else if (g_strcmp0 (long_options[option_index].name, "kill-daemon") == 0) {
Packit Service 1d8f1c
                _kill_daemon = TRUE;
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        case 'v':
Packit Service 1d8f1c
            g_debug_level = atoi (optarg);
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        case 'n':
Packit Service 1d8f1c
            g_free (_server_name);
Packit Service 1d8f1c
            _server_name = g_strdup (optarg);
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        case 'l':
Packit Service 1d8f1c
            g_free (_locale);
Packit Service 1d8f1c
            _locale = g_strdup (optarg);
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        case 'a': {
Packit Service 1d8f1c
                gchar *tmp = g_strdup_printf ("%s,%s",
Packit Service 1d8f1c
                                _locale != NULL ? _locale : LOCALES_STRING, optarg);
Packit Service 1d8f1c
                g_free (_locale);
Packit Service 1d8f1c
                _locale = tmp;
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        case 'k':
Packit Service 1d8f1c
            _kill_daemon = TRUE;
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        case '?':
Packit Service 1d8f1c
        default:
Packit Service 1d8f1c
            _print_usage (stderr, argv[0]);
Packit Service 1d8f1c
            exit (EXIT_FAILURE);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    _x11_ic_table = g_hash_table_new (g_direct_hash, g_direct_equal);
Packit Service 1d8f1c
    _connections = g_hash_table_new (g_direct_hash, g_direct_equal);
Packit Service 1d8f1c
Packit Service 1d8f1c
    signal (SIGINT, _sighandler);
Packit Service 1d8f1c
    signal (SIGTERM, _sighandler);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (_kill_daemon)
Packit Service 1d8f1c
        atexit (_atexit_cb);
Packit Service 1d8f1c
Packit Service 1d8f1c
    _xim_init_IMdkit ();
Packit Service 1d8f1c
    gtk_main();
Packit Service 1d8f1c
Packit Service 1d8f1c
    exit (EXIT_SUCCESS);
Packit Service 1d8f1c
}