src/core/linux/SDL_fcitx.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 07 Oct 2016 18:57:40 -0700
changeset 10496 6660aa9120d6
child 10500 c3874aa1f2d1
permissions -rw-r--r--
Fixed bug 2824 - Add Fcitx Input Method Support

Weitian Leung

Just moved ibus direct call to SDL_IME_* related functions, and adds fcitx IME support (uses DBus, too),
enable with env: SDL_IM_MODULE=fcitx (ibus still the default one)
slouken@10496
     1
/*
slouken@10496
     2
  Simple DirectMedia Layer
slouken@10496
     3
  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
slouken@10496
     4
slouken@10496
     5
  This software is provided 'as-is', without any express or implied
slouken@10496
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@10496
     7
  arising from the use of this software.
slouken@10496
     8
slouken@10496
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@10496
    10
  including commercial applications, and to alter it and redistribute it
slouken@10496
    11
  freely, subject to the following restrictions:
slouken@10496
    12
slouken@10496
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@10496
    14
     claim that you wrote the original software. If you use this software
slouken@10496
    15
     in a product, an acknowledgment in the product documentation would be
slouken@10496
    16
     appreciated but is not required.
slouken@10496
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@10496
    18
     misrepresented as being the original software.
slouken@10496
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@10496
    20
*/
slouken@10496
    21
slouken@10496
    22
#include <fcitx/frontend.h>
slouken@10496
    23
#include <unistd.h>
slouken@10496
    24
slouken@10496
    25
#include "SDL_fcitx.h"
slouken@10496
    26
#include "SDL_keycode.h"
slouken@10496
    27
#include "SDL_keyboard.h"
slouken@10496
    28
#include "../../events/SDL_keyboard_c.h"
slouken@10496
    29
#include "SDL_dbus.h"
slouken@10496
    30
#include "SDL_syswm.h"
slouken@10496
    31
#if SDL_VIDEO_DRIVER_X11
slouken@10496
    32
#  include "../../video/x11/SDL_x11video.h"
slouken@10496
    33
#endif
slouken@10496
    34
#include "SDL_hints.h"
slouken@10496
    35
slouken@10496
    36
#define FCITX_DBUS_SERVICE "org.fcitx.Fcitx"
slouken@10496
    37
slouken@10496
    38
#define FCITX_IM_DBUS_PATH "/inputmethod"
slouken@10496
    39
#define FCITX_IC_DBUS_PATH "/inputcontext_%d"
slouken@10496
    40
slouken@10496
    41
#define FCITX_IM_DBUS_INTERFACE "org.fcitx.Fcitx.InputMethod"
slouken@10496
    42
#define FCITX_IC_DBUS_INTERFACE "org.fcitx.Fcitx.InputContext"
slouken@10496
    43
slouken@10496
    44
#define IC_NAME_MAX 64
slouken@10496
    45
#define DBUS_TIMEOUT 500
slouken@10496
    46
slouken@10496
    47
typedef struct _FcitxClient
slouken@10496
    48
{
slouken@10496
    49
    SDL_DBusContext *dbus;
slouken@10496
    50
slouken@10496
    51
    char servicename[IC_NAME_MAX];
slouken@10496
    52
    char icname[IC_NAME_MAX];
slouken@10496
    53
slouken@10496
    54
    int id;
slouken@10496
    55
slouken@10496
    56
    SDL_Rect cursor_rect;
slouken@10496
    57
} FcitxClient;
slouken@10496
    58
slouken@10496
    59
static FcitxClient fcitx_client;
slouken@10496
    60
slouken@10496
    61
static int
slouken@10496
    62
GetDisplayNumber()
slouken@10496
    63
{
slouken@10496
    64
    const char *display = SDL_getenv("DISPLAY");
slouken@10496
    65
    const char *p = NULL;;
slouken@10496
    66
    int number = 0;
slouken@10496
    67
slouken@10496
    68
    if (display == NULL)
slouken@10496
    69
        return 0;
slouken@10496
    70
slouken@10496
    71
    display = SDL_strchr(display, ':');
slouken@10496
    72
    if (display == NULL)
slouken@10496
    73
        return 0;
slouken@10496
    74
slouken@10496
    75
    display++;
slouken@10496
    76
    p = SDL_strchr(display, '.');
slouken@10496
    77
    if (p == NULL && display != NULL) {
slouken@10496
    78
        number = SDL_strtod(display, NULL);
slouken@10496
    79
    } else {
slouken@10496
    80
        char *buffer = SDL_strdup(display);
slouken@10496
    81
        buffer[p - display] = '\0';
slouken@10496
    82
        number = SDL_strtod(buffer, NULL);
slouken@10496
    83
        SDL_free(buffer);
slouken@10496
    84
    }
slouken@10496
    85
slouken@10496
    86
    return number;
slouken@10496
    87
}
slouken@10496
    88
slouken@10496
    89
static char*
slouken@10496
    90
GetAppName()
slouken@10496
    91
{
slouken@10496
    92
#if defined(__LINUX__) || defined(__FREEBSD__)
slouken@10496
    93
    char *spot;
slouken@10496
    94
    char procfile[1024];
slouken@10496
    95
    char linkfile[1024];
slouken@10496
    96
    int linksize;
slouken@10496
    97
slouken@10496
    98
#if defined(__LINUX__)
slouken@10496
    99
    SDL_snprintf(procfile, sizeof(procfile), "/proc/%d/exe", getpid());
slouken@10496
   100
#elif defined(__FREEBSD__)
slouken@10496
   101
    SDL_snprintf(procfile, sizeof(procfile), "/proc/%d/file", getpid());
slouken@10496
   102
#endif
slouken@10496
   103
    linksize = readlink(procfile, linkfile, sizeof(linkfile) - 1);
slouken@10496
   104
    if (linksize > 0) {
slouken@10496
   105
        linkfile[linksize] = '\0';
slouken@10496
   106
        spot = SDL_strrchr(linkfile, '/');
slouken@10496
   107
        if (spot) {
slouken@10496
   108
            return SDL_strdup(spot + 1);
slouken@10496
   109
        } else {
slouken@10496
   110
            return SDL_strdup(linkfile);
slouken@10496
   111
        }
slouken@10496
   112
    }
slouken@10496
   113
#endif /* __LINUX__ || __FREEBSD__ */
slouken@10496
   114
slouken@10496
   115
    return SDL_strdup("SDL_App");
slouken@10496
   116
}
slouken@10496
   117
slouken@10496
   118
/*
slouken@10496
   119
 * Copied from fcitx source
slouken@10496
   120
 */
slouken@10496
   121
#define CONT(i)   ISUTF8_CB(in[i])
slouken@10496
   122
#define VAL(i, s) ((in[i]&0x3f) << s)
slouken@10496
   123
slouken@10496
   124
static char *
slouken@10496
   125
_fcitx_utf8_get_char(const char *i, uint32_t *chr)
slouken@10496
   126
{
slouken@10496
   127
    const unsigned char* in = (const unsigned char *)i;
slouken@10496
   128
    if (!(in[0] & 0x80)) {
slouken@10496
   129
        *(chr) = *(in);
slouken@10496
   130
        return (char *)in + 1;
slouken@10496
   131
    }
slouken@10496
   132
slouken@10496
   133
    /* 2-byte, 0x80-0x7ff */
slouken@10496
   134
    if ((in[0] & 0xe0) == 0xc0 && CONT(1)) {
slouken@10496
   135
        *chr = ((in[0] & 0x1f) << 6) | VAL(1, 0);
slouken@10496
   136
        return (char *)in + 2;
slouken@10496
   137
    }
slouken@10496
   138
slouken@10496
   139
    /* 3-byte, 0x800-0xffff */
slouken@10496
   140
    if ((in[0] & 0xf0) == 0xe0 && CONT(1) && CONT(2)) {
slouken@10496
   141
        *chr = ((in[0] & 0xf) << 12) | VAL(1, 6) | VAL(2, 0);
slouken@10496
   142
        return (char *)in + 3;
slouken@10496
   143
    }
slouken@10496
   144
slouken@10496
   145
    /* 4-byte, 0x10000-0x1FFFFF */
slouken@10496
   146
    if ((in[0] & 0xf8) == 0xf0 && CONT(1) && CONT(2) && CONT(3)) {
slouken@10496
   147
        *chr = ((in[0] & 0x7) << 18) | VAL(1, 12) | VAL(2, 6) | VAL(3, 0);
slouken@10496
   148
        return (char *)in + 4;
slouken@10496
   149
    }
slouken@10496
   150
slouken@10496
   151
    /* 5-byte, 0x200000-0x3FFFFFF */
slouken@10496
   152
    if ((in[0] & 0xfc) == 0xf8 && CONT(1) && CONT(2) && CONT(3) && CONT(4)) {
slouken@10496
   153
        *chr = ((in[0] & 0x3) << 24) | VAL(1, 18) | VAL(2, 12) | VAL(3, 6) | VAL(4, 0);
slouken@10496
   154
        return (char *)in + 5;
slouken@10496
   155
    }
slouken@10496
   156
slouken@10496
   157
    /* 6-byte, 0x400000-0x7FFFFFF */
slouken@10496
   158
    if ((in[0] & 0xfe) == 0xfc && CONT(1) && CONT(2) && CONT(3) && CONT(4) && CONT(5)) {
slouken@10496
   159
        *chr = ((in[0] & 0x1) << 30) | VAL(1, 24) | VAL(2, 18) | VAL(3, 12) | VAL(4, 6) | VAL(5, 0);
slouken@10496
   160
        return (char *)in + 6;
slouken@10496
   161
    }
slouken@10496
   162
slouken@10496
   163
    *chr = *in;
slouken@10496
   164
slouken@10496
   165
    return (char *)in + 1;
slouken@10496
   166
}
slouken@10496
   167
slouken@10496
   168
static size_t
slouken@10496
   169
_fcitx_utf8_strlen(const char *s)
slouken@10496
   170
{
slouken@10496
   171
    unsigned int l = 0;
slouken@10496
   172
slouken@10496
   173
    while (*s) {
slouken@10496
   174
        uint32_t chr;
slouken@10496
   175
slouken@10496
   176
        s = _fcitx_utf8_get_char(s, &chr);
slouken@10496
   177
        l++;
slouken@10496
   178
    }
slouken@10496
   179
slouken@10496
   180
    return l;
slouken@10496
   181
}
slouken@10496
   182
slouken@10496
   183
static DBusHandlerResult
slouken@10496
   184
DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data)
slouken@10496
   185
{
slouken@10496
   186
    SDL_DBusContext *dbus = (SDL_DBusContext *)data;
slouken@10496
   187
slouken@10496
   188
    if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE, "CommitString")) {
slouken@10496
   189
        DBusMessageIter iter;
slouken@10496
   190
        const char *text = NULL;
slouken@10496
   191
slouken@10496
   192
        dbus->message_iter_init(msg, &iter);
slouken@10496
   193
        dbus->message_iter_get_basic(&iter, &text);
slouken@10496
   194
slouken@10496
   195
        if (text)
slouken@10496
   196
            SDL_SendKeyboardText(text);
slouken@10496
   197
slouken@10496
   198
        return DBUS_HANDLER_RESULT_HANDLED;
slouken@10496
   199
    }
slouken@10496
   200
slouken@10496
   201
    if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE, "UpdatePreedit")) {
slouken@10496
   202
        DBusMessageIter iter;
slouken@10496
   203
        const char *text;
slouken@10496
   204
slouken@10496
   205
        dbus->message_iter_init(msg, &iter);
slouken@10496
   206
        dbus->message_iter_get_basic(&iter, &text);
slouken@10496
   207
slouken@10496
   208
        if (text && *text) {
slouken@10496
   209
            char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
slouken@10496
   210
            size_t text_bytes = SDL_strlen(text), i = 0;
slouken@10496
   211
            size_t cursor = 0;
slouken@10496
   212
slouken@10496
   213
            while (i < text_bytes) {
slouken@10496
   214
                size_t sz = SDL_utf8strlcpy(buf, text + i, sizeof(buf));
slouken@10496
   215
                size_t chars = _fcitx_utf8_strlen(buf);
slouken@10496
   216
slouken@10496
   217
                SDL_SendEditingText(buf, cursor, chars);
slouken@10496
   218
slouken@10496
   219
                i += sz;
slouken@10496
   220
                cursor += chars;
slouken@10496
   221
            }
slouken@10496
   222
        }
slouken@10496
   223
slouken@10496
   224
        SDL_Fcitx_UpdateTextRect(NULL);
slouken@10496
   225
        return DBUS_HANDLER_RESULT_HANDLED;
slouken@10496
   226
    }
slouken@10496
   227
slouken@10496
   228
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
slouken@10496
   229
}
slouken@10496
   230
slouken@10496
   231
static DBusMessage*
slouken@10496
   232
FcitxClientICNewMethod(FcitxClient *client,
slouken@10496
   233
        const char *method)
slouken@10496
   234
{
slouken@10496
   235
    SDL_DBusContext *dbus = client->dbus;
slouken@10496
   236
    return dbus->message_new_method_call(
slouken@10496
   237
            client->servicename,
slouken@10496
   238
            client->icname,
slouken@10496
   239
            FCITX_IC_DBUS_INTERFACE,
slouken@10496
   240
            method);
slouken@10496
   241
}
slouken@10496
   242
slouken@10496
   243
static void
slouken@10496
   244
FcitxClientICCallMethod(FcitxClient *client,
slouken@10496
   245
        const char *method)
slouken@10496
   246
{
slouken@10496
   247
    SDL_DBusContext *dbus = client->dbus;
slouken@10496
   248
    DBusMessage *msg = FcitxClientICNewMethod(client, method);
slouken@10496
   249
slouken@10496
   250
    if (msg == NULL)
slouken@10496
   251
        return ;
slouken@10496
   252
slouken@10496
   253
    if (dbus->connection_send(dbus->session_conn, msg, NULL)) {
slouken@10496
   254
        dbus->connection_flush(dbus->session_conn);
slouken@10496
   255
    }
slouken@10496
   256
slouken@10496
   257
    dbus->message_unref(msg);
slouken@10496
   258
}
slouken@10496
   259
slouken@10496
   260
static void
slouken@10496
   261
Fcitx_SetCapabilities(void *data,
slouken@10496
   262
        const char *name,
slouken@10496
   263
        const char *old_val,
slouken@10496
   264
        const char *internal_editing)
slouken@10496
   265
{
slouken@10496
   266
    FcitxClient *client = (FcitxClient *)data;
slouken@10496
   267
    SDL_DBusContext *dbus = client->dbus;
slouken@10496
   268
    Uint32 caps = CAPACITY_NONE;
slouken@10496
   269
slouken@10496
   270
    DBusMessage *msg = FcitxClientICNewMethod(client, "SetCapacity");
slouken@10496
   271
    if (msg == NULL)
slouken@10496
   272
        return ;
slouken@10496
   273
slouken@10496
   274
    if (!(internal_editing && *internal_editing == '1')) {
slouken@10496
   275
        caps |= CAPACITY_PREEDIT;
slouken@10496
   276
    }
slouken@10496
   277
slouken@10496
   278
    dbus->message_append_args(msg,
slouken@10496
   279
            DBUS_TYPE_UINT32, &caps,
slouken@10496
   280
            DBUS_TYPE_INVALID);
slouken@10496
   281
    if (dbus->connection_send(dbus->session_conn, msg, NULL)) {
slouken@10496
   282
        dbus->connection_flush(dbus->session_conn);
slouken@10496
   283
    }
slouken@10496
   284
slouken@10496
   285
    dbus->message_unref(msg);
slouken@10496
   286
}
slouken@10496
   287
slouken@10496
   288
static void
slouken@10496
   289
FcitxClientCreateIC(FcitxClient *client)
slouken@10496
   290
{
slouken@10496
   291
    char *appname = NULL;
slouken@10496
   292
    pid_t pid = 0;
slouken@10496
   293
    int id = 0;
slouken@10496
   294
    SDL_bool enable;
slouken@10496
   295
    Uint32 arg1, arg2, arg3, arg4;
slouken@10496
   296
slouken@10496
   297
    SDL_DBusContext *dbus = client->dbus;
slouken@10496
   298
    DBusMessage *reply = NULL;
slouken@10496
   299
    DBusMessage *msg = dbus->message_new_method_call(
slouken@10496
   300
            client->servicename,
slouken@10496
   301
            FCITX_IM_DBUS_PATH,
slouken@10496
   302
            FCITX_IM_DBUS_INTERFACE,
slouken@10496
   303
            "CreateICv3"
slouken@10496
   304
            );
slouken@10496
   305
slouken@10496
   306
    if (msg == NULL)
slouken@10496
   307
        return ;
slouken@10496
   308
slouken@10496
   309
    appname = GetAppName();
slouken@10496
   310
    pid = getpid();
slouken@10496
   311
    dbus->message_append_args(msg,
slouken@10496
   312
            DBUS_TYPE_STRING, &appname,
slouken@10496
   313
            DBUS_TYPE_INT32, &pid,
slouken@10496
   314
            DBUS_TYPE_INVALID);
slouken@10496
   315
slouken@10496
   316
    do {
slouken@10496
   317
        reply = dbus->connection_send_with_reply_and_block(
slouken@10496
   318
                dbus->session_conn,
slouken@10496
   319
                msg,
slouken@10496
   320
                DBUS_TIMEOUT,
slouken@10496
   321
                NULL);
slouken@10496
   322
slouken@10496
   323
        if (!reply)
slouken@10496
   324
            break;
slouken@10496
   325
        if (!dbus->message_get_args(reply, NULL,
slouken@10496
   326
                DBUS_TYPE_INT32, &id,
slouken@10496
   327
                DBUS_TYPE_BOOLEAN, &enable,
slouken@10496
   328
                DBUS_TYPE_UINT32, &arg1,
slouken@10496
   329
                DBUS_TYPE_UINT32, &arg2,
slouken@10496
   330
                DBUS_TYPE_UINT32, &arg3,
slouken@10496
   331
                DBUS_TYPE_UINT32, &arg4,
slouken@10496
   332
                DBUS_TYPE_INVALID))
slouken@10496
   333
            break;
slouken@10496
   334
slouken@10496
   335
        if (id < 0)
slouken@10496
   336
            break;
slouken@10496
   337
        client->id = id;
slouken@10496
   338
slouken@10496
   339
        SDL_snprintf(client->icname, IC_NAME_MAX,
slouken@10496
   340
                FCITX_IC_DBUS_PATH, client->id);
slouken@10496
   341
slouken@10496
   342
        dbus->bus_add_match(dbus->session_conn,
slouken@10496
   343
                "type='signal', interface='org.fcitx.Fcitx.InputContext'",
slouken@10496
   344
                NULL);
slouken@10496
   345
        dbus->connection_add_filter(dbus->session_conn,
slouken@10496
   346
                &DBus_MessageFilter, dbus,
slouken@10496
   347
                NULL);
slouken@10496
   348
        dbus->connection_flush(dbus->session_conn);
slouken@10496
   349
slouken@10496
   350
        SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, &Fcitx_SetCapabilities, client);
slouken@10496
   351
    }
slouken@10496
   352
    while (0);
slouken@10496
   353
slouken@10496
   354
    if (reply)
slouken@10496
   355
        dbus->message_unref(reply);
slouken@10496
   356
    dbus->message_unref(msg);
slouken@10496
   357
    SDL_free(appname);
slouken@10496
   358
}
slouken@10496
   359
slouken@10496
   360
static Uint32
slouken@10496
   361
Fcitx_ModState(void)
slouken@10496
   362
{
slouken@10496
   363
    Uint32 fcitx_mods = 0;
slouken@10496
   364
    SDL_Keymod sdl_mods = SDL_GetModState();
slouken@10496
   365
slouken@10496
   366
    if (sdl_mods & KMOD_SHIFT) fcitx_mods |= FcitxKeyState_Shift;
slouken@10496
   367
    if (sdl_mods & KMOD_CAPS)   fcitx_mods |= FcitxKeyState_CapsLock;
slouken@10496
   368
    if (sdl_mods & KMOD_CTRL)  fcitx_mods |= FcitxKeyState_Ctrl;
slouken@10496
   369
    if (sdl_mods & KMOD_ALT)   fcitx_mods |= FcitxKeyState_Alt;
slouken@10496
   370
    if (sdl_mods & KMOD_NUM)    fcitx_mods |= FcitxKeyState_NumLock;
slouken@10496
   371
    if (sdl_mods & KMOD_LGUI)   fcitx_mods |= FcitxKeyState_Super;
slouken@10496
   372
    if (sdl_mods & KMOD_RGUI)   fcitx_mods |= FcitxKeyState_Meta;
slouken@10496
   373
slouken@10496
   374
    return fcitx_mods;
slouken@10496
   375
}
slouken@10496
   376
slouken@10496
   377
SDL_bool
slouken@10496
   378
SDL_Fcitx_Init()
slouken@10496
   379
{
slouken@10496
   380
    fcitx_client.dbus = SDL_DBus_GetContext();
slouken@10496
   381
slouken@10496
   382
    fcitx_client.cursor_rect.x = -1;
slouken@10496
   383
    fcitx_client.cursor_rect.y = -1;
slouken@10496
   384
    fcitx_client.cursor_rect.w = 0;
slouken@10496
   385
    fcitx_client.cursor_rect.h = 0;
slouken@10496
   386
slouken@10496
   387
    SDL_snprintf(fcitx_client.servicename, IC_NAME_MAX,
slouken@10496
   388
            "%s-%d",
slouken@10496
   389
            FCITX_DBUS_SERVICE, GetDisplayNumber());
slouken@10496
   390
slouken@10496
   391
    FcitxClientCreateIC(&fcitx_client);
slouken@10496
   392
slouken@10496
   393
    return SDL_TRUE;
slouken@10496
   394
}
slouken@10496
   395
slouken@10496
   396
void
slouken@10496
   397
SDL_Fcitx_Quit()
slouken@10496
   398
{
slouken@10496
   399
    FcitxClientICCallMethod(&fcitx_client, "DestroyIC");
slouken@10496
   400
}
slouken@10496
   401
slouken@10496
   402
void
slouken@10496
   403
SDL_Fcitx_SetFocus(SDL_bool focused)
slouken@10496
   404
{
slouken@10496
   405
    if (focused) {
slouken@10496
   406
        FcitxClientICCallMethod(&fcitx_client, "FocusIn");
slouken@10496
   407
    } else {
slouken@10496
   408
        FcitxClientICCallMethod(&fcitx_client, "FocusOut");
slouken@10496
   409
    }
slouken@10496
   410
}
slouken@10496
   411
slouken@10496
   412
void
slouken@10496
   413
SDL_Fcitx_Reset(void)
slouken@10496
   414
{
slouken@10496
   415
    FcitxClientICCallMethod(&fcitx_client, "Reset");
slouken@10496
   416
    FcitxClientICCallMethod(&fcitx_client, "CloseIC");
slouken@10496
   417
}
slouken@10496
   418
slouken@10496
   419
SDL_bool
slouken@10496
   420
SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
slouken@10496
   421
{
slouken@10496
   422
    DBusMessage *msg = NULL;
slouken@10496
   423
    DBusMessage *reply = NULL;
slouken@10496
   424
    SDL_DBusContext *dbus = fcitx_client.dbus;
slouken@10496
   425
slouken@10496
   426
    Uint32 state = 0;
slouken@10496
   427
    SDL_bool handled = SDL_FALSE;
slouken@10496
   428
    int type = FCITX_PRESS_KEY;
slouken@10496
   429
    Uint32 event_time = 0;
slouken@10496
   430
slouken@10496
   431
    msg = FcitxClientICNewMethod(&fcitx_client, "ProcessKeyEvent");
slouken@10496
   432
    if (msg == NULL)
slouken@10496
   433
        return SDL_FALSE;
slouken@10496
   434
slouken@10496
   435
    state = Fcitx_ModState();
slouken@10496
   436
    dbus->message_append_args(msg,
slouken@10496
   437
            DBUS_TYPE_UINT32, &keysym,
slouken@10496
   438
            DBUS_TYPE_UINT32, &keycode,
slouken@10496
   439
            DBUS_TYPE_UINT32, &state,
slouken@10496
   440
            DBUS_TYPE_INT32, &type,
slouken@10496
   441
            DBUS_TYPE_UINT32, &event_time,
slouken@10496
   442
            DBUS_TYPE_INVALID);
slouken@10496
   443
slouken@10496
   444
    reply = dbus->connection_send_with_reply_and_block(dbus->session_conn,
slouken@10496
   445
            msg,
slouken@10496
   446
            -1,
slouken@10496
   447
            NULL);
slouken@10496
   448
slouken@10496
   449
    if (reply) {
slouken@10496
   450
        dbus->message_get_args(reply,
slouken@10496
   451
                NULL,
slouken@10496
   452
                DBUS_TYPE_INT32, &handled,
slouken@10496
   453
                DBUS_TYPE_INVALID);
slouken@10496
   454
slouken@10496
   455
        dbus->message_unref(reply);
slouken@10496
   456
    }
slouken@10496
   457
slouken@10496
   458
    if (handled) {
slouken@10496
   459
        SDL_Fcitx_UpdateTextRect(NULL);
slouken@10496
   460
    }
slouken@10496
   461
slouken@10496
   462
    return handled;
slouken@10496
   463
}
slouken@10496
   464
slouken@10496
   465
void
slouken@10496
   466
SDL_Fcitx_UpdateTextRect(SDL_Rect *rect)
slouken@10496
   467
{
slouken@10496
   468
    SDL_Window *focused_win = NULL;
slouken@10496
   469
    SDL_SysWMinfo info;
slouken@10496
   470
    int x = 0, y = 0;
slouken@10496
   471
    SDL_Rect *cursor = &fcitx_client.cursor_rect;
slouken@10496
   472
slouken@10496
   473
    SDL_DBusContext *dbus = fcitx_client.dbus;
slouken@10496
   474
    DBusMessage *msg = NULL;
slouken@10496
   475
    DBusConnection *conn;
slouken@10496
   476
slouken@10496
   477
    if (rect) {
slouken@10496
   478
        SDL_memcpy(cursor, rect, sizeof(SDL_Rect));
slouken@10496
   479
    }
slouken@10496
   480
slouken@10496
   481
    focused_win = SDL_GetKeyboardFocus();
slouken@10496
   482
    if (!focused_win) {
slouken@10496
   483
        return ;
slouken@10496
   484
    }
slouken@10496
   485
slouken@10496
   486
    SDL_VERSION(&info.version);
slouken@10496
   487
    if (!SDL_GetWindowWMInfo(focused_win, &info)) {
slouken@10496
   488
        return;
slouken@10496
   489
    }
slouken@10496
   490
slouken@10496
   491
    SDL_GetWindowPosition(focused_win, &x, &y);
slouken@10496
   492
slouken@10496
   493
#if SDL_VIDEO_DRIVER_X11
slouken@10496
   494
    if (info.subsystem == SDL_SYSWM_X11) {
slouken@10496
   495
        SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(focused_win)->driverdata;
slouken@10496
   496
slouken@10496
   497
        Display *x_disp = info.info.x11.display;
slouken@10496
   498
        Window x_win = info.info.x11.window;
slouken@10496
   499
        int x_screen = displaydata->screen;
slouken@10496
   500
        Window unused;
slouken@10496
   501
        X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &y, &unused);
slouken@10496
   502
    }
slouken@10496
   503
#endif
slouken@10496
   504
slouken@10496
   505
    if (cursor->x == -1 && cursor->y == -1 && cursor->w == 0 && cursor->h == 0) {
slouken@10496
   506
        // move to bottom left
slouken@10496
   507
        int w = 0, h = 0;
slouken@10496
   508
        SDL_GetWindowSize(focused_win, &w, &h);
slouken@10496
   509
        cursor->x = 0;
slouken@10496
   510
        cursor->y = h;
slouken@10496
   511
    }
slouken@10496
   512
slouken@10496
   513
    x += cursor->x;
slouken@10496
   514
    y += cursor->y;
slouken@10496
   515
slouken@10496
   516
    msg = FcitxClientICNewMethod(&fcitx_client, "SetCursorRect");
slouken@10496
   517
    if (msg == NULL)
slouken@10496
   518
        return ;
slouken@10496
   519
slouken@10496
   520
    dbus->message_append_args(msg,
slouken@10496
   521
            DBUS_TYPE_INT32, &x,
slouken@10496
   522
            DBUS_TYPE_INT32, &y,
slouken@10496
   523
            DBUS_TYPE_INT32, &cursor->w,
slouken@10496
   524
            DBUS_TYPE_INT32, &cursor->h,
slouken@10496
   525
            DBUS_TYPE_INVALID);
slouken@10496
   526
slouken@10496
   527
    conn = dbus->session_conn;
slouken@10496
   528
    if (dbus->connection_send(conn, msg, NULL))
slouken@10496
   529
        dbus->connection_flush(conn);
slouken@10496
   530
slouken@10496
   531
    dbus->message_unref(msg);
slouken@10496
   532
}
slouken@10496
   533
slouken@10496
   534
void
slouken@10496
   535
SDL_Fcitx_PumpEvents()
slouken@10496
   536
{
slouken@10496
   537
    SDL_DBusContext *dbus = fcitx_client.dbus;
slouken@10496
   538
    DBusConnection *conn = dbus->session_conn;
slouken@10496
   539
slouken@10496
   540
    dbus->connection_read_write(conn, 0);
slouken@10496
   541
slouken@10496
   542
    while (dbus->connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS) {
slouken@10496
   543
        /* Do nothing, actual work happens in DBus_MessageFilter */
slouken@10496
   544
        usleep(10);
slouken@10496
   545
    }
slouken@10496
   546
}
slouken@10496
   547
slouken@10496
   548
/* vi: set ts=4 sw=4 expandtab: */