Skip to content

Latest commit

 

History

History
669 lines (531 loc) · 19.2 KB

SDL_ibus.c

File metadata and controls

669 lines (531 loc) · 19.2 KB
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
Simple DirectMedia Layer
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#ifdef HAVE_IBUS_IBUS_H
#include "SDL.h"
Aug 19, 2014
Aug 19, 2014
25
#include "SDL_syswm.h"
26
27
28
29
#include "SDL_ibus.h"
#include "SDL_dbus.h"
#include "../../video/SDL_sysvideo.h"
#include "../../events/SDL_keyboard_c.h"
Aug 19, 2014
Aug 19, 2014
30
31
32
33
34
#if SDL_VIDEO_DRIVER_X11
#include "../../video/x11/SDL_x11video.h"
#endif
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <sys/inotify.h>
#include <unistd.h>
#include <fcntl.h>
static const char IBUS_SERVICE[] = "org.freedesktop.IBus";
static const char IBUS_PATH[] = "/org/freedesktop/IBus";
static const char IBUS_INTERFACE[] = "org.freedesktop.IBus";
static const char IBUS_INPUT_INTERFACE[] = "org.freedesktop.IBus.InputContext";
static char *input_ctx_path = NULL;
static SDL_Rect ibus_cursor_rect = {0};
static DBusConnection *ibus_conn = NULL;
static char *ibus_addr_file = NULL;
Aug 19, 2014
Aug 19, 2014
48
int inotify_fd = -1, inotify_wd = -1;
49
50
51
52
53
54
55
56
static Uint32
IBus_ModState(void)
{
Uint32 ibus_mods = 0;
SDL_Keymod sdl_mods = SDL_GetModState();
/* Not sure about MOD3, MOD4 and HYPER mappings */
Aug 22, 2014
Aug 22, 2014
57
58
59
60
61
62
63
64
if (sdl_mods & KMOD_LSHIFT) ibus_mods |= IBUS_SHIFT_MASK;
if (sdl_mods & KMOD_CAPS) ibus_mods |= IBUS_LOCK_MASK;
if (sdl_mods & KMOD_LCTRL) ibus_mods |= IBUS_CONTROL_MASK;
if (sdl_mods & KMOD_LALT) ibus_mods |= IBUS_MOD1_MASK;
if (sdl_mods & KMOD_NUM) ibus_mods |= IBUS_MOD2_MASK;
if (sdl_mods & KMOD_MODE) ibus_mods |= IBUS_MOD5_MASK;
if (sdl_mods & KMOD_LGUI) ibus_mods |= IBUS_SUPER_MASK;
if (sdl_mods & KMOD_RGUI) ibus_mods |= IBUS_META_MASK;
65
66
67
68
69
70
71
72
73
return ibus_mods;
}
static const char *
IBus_GetVariantText(DBusConnection *conn, DBusMessageIter *iter, SDL_DBusContext *dbus)
{
/* The text we need is nested weirdly, use dbus-monitor to see the structure better */
const char *text = NULL;
Aug 22, 2014
Aug 22, 2014
74
const char *struct_id = NULL;
75
76
DBusMessageIter sub1, sub2;
Aug 22, 2014
Aug 22, 2014
77
if (dbus->message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT) {
78
79
80
81
82
return NULL;
}
dbus->message_iter_recurse(iter, &sub1);
Aug 22, 2014
Aug 22, 2014
83
if (dbus->message_iter_get_arg_type(&sub1) != DBUS_TYPE_STRUCT) {
84
85
86
87
88
return NULL;
}
dbus->message_iter_recurse(&sub1, &sub2);
Aug 22, 2014
Aug 22, 2014
89
if (dbus->message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
90
91
92
93
return NULL;
}
dbus->message_iter_get_basic(&sub2, &struct_id);
Aug 22, 2014
Aug 22, 2014
94
if (!struct_id || SDL_strncmp(struct_id, "IBusText", sizeof("IBusText")) != 0) {
95
96
97
98
99
100
return NULL;
}
dbus->message_iter_next(&sub2);
dbus->message_iter_next(&sub2);
Aug 22, 2014
Aug 22, 2014
101
if (dbus->message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
102
103
104
105
106
107
108
109
110
111
112
113
114
115
return NULL;
}
dbus->message_iter_get_basic(&sub2, &text);
return text;
}
static size_t
IBus_utf8_strlen(const char *str)
{
size_t utf8_len = 0;
const char *p;
Aug 22, 2014
Aug 22, 2014
116
117
for (p = str; *p; ++p) {
if (!((*p & 0x80) && !(*p & 0x40))) {
118
119
120
121
122
123
124
125
126
127
128
129
++utf8_len;
}
}
return utf8_len;
}
static DBusHandlerResult
IBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *user_data)
{
SDL_DBusContext *dbus = (SDL_DBusContext *)user_data;
Aug 22, 2014
Aug 22, 2014
130
if (dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE, "CommitText")) {
131
DBusMessageIter iter;
Aug 22, 2014
Aug 22, 2014
132
const char *text;
Aug 22, 2014
Aug 22, 2014
133
134
135
dbus->message_iter_init(msg, &iter);
Aug 22, 2014
Aug 22, 2014
136
text = IBus_GetVariantText(conn, &iter, dbus);
Aug 22, 2014
Aug 22, 2014
137
if (text && *text) {
138
139
140
char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
size_t text_bytes = SDL_strlen(text), i = 0;
Aug 22, 2014
Aug 22, 2014
141
while (i < text_bytes) {
142
143
144
145
146
147
148
149
150
151
size_t sz = SDL_utf8strlcpy(buf, text+i, sizeof(buf));
SDL_SendKeyboardText(buf);
i += sz;
}
}
return DBUS_HANDLER_RESULT_HANDLED;
}
Aug 22, 2014
Aug 22, 2014
152
if (dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE, "UpdatePreeditText")) {
153
DBusMessageIter iter;
Aug 22, 2014
Aug 22, 2014
154
155
const char *text;
156
dbus->message_iter_init(msg, &iter);
Aug 22, 2014
Aug 22, 2014
157
text = IBus_GetVariantText(conn, &iter, dbus);
Aug 22, 2014
Aug 22, 2014
159
if (text && *text) {
160
161
162
163
char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
size_t text_bytes = SDL_strlen(text), i = 0;
size_t cursor = 0;
Aug 22, 2014
Aug 22, 2014
164
while (i < text_bytes) {
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
size_t sz = SDL_utf8strlcpy(buf, text+i, sizeof(buf));
size_t chars = IBus_utf8_strlen(buf);
SDL_SendEditingText(buf, cursor, chars);
i += sz;
cursor += chars;
}
}
SDL_IBus_UpdateTextRect(NULL);
return DBUS_HANDLER_RESULT_HANDLED;
}
Aug 22, 2014
Aug 22, 2014
180
181
182
if (dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE, "HidePreeditText")) {
SDL_SendEditingText("", 0, 0);
return DBUS_HANDLER_RESULT_HANDLED;
Aug 19, 2014
Aug 19, 2014
183
184
}
185
186
187
188
189
190
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
static char *
IBus_ReadAddressFromFile(const char *file_path)
{
Aug 22, 2014
Aug 22, 2014
191
192
193
194
195
char addr_buf[1024];
SDL_bool success = SDL_FALSE;
FILE *addr_file;
addr_file = fopen(file_path, "r");
Aug 22, 2014
Aug 22, 2014
196
if (!addr_file) {
197
198
199
return NULL;
}
Aug 22, 2014
Aug 22, 2014
200
201
while (fgets(addr_buf, sizeof(addr_buf), addr_file)) {
if (SDL_strncmp(addr_buf, "IBUS_ADDRESS=", sizeof("IBUS_ADDRESS=")-1) == 0) {
202
size_t sz = SDL_strlen(addr_buf);
Aug 22, 2014
Aug 22, 2014
203
204
if (addr_buf[sz-1] == '\n') addr_buf[sz-1] = 0;
if (addr_buf[sz-2] == '\r') addr_buf[sz-2] = 0;
205
206
207
208
209
210
211
success = SDL_TRUE;
break;
}
}
fclose(addr_file);
Aug 22, 2014
Aug 22, 2014
212
if (success) {
213
214
215
216
217
218
219
220
221
return SDL_strdup(addr_buf + (sizeof("IBUS_ADDRESS=") - 1));
} else {
return NULL;
}
}
static char *
IBus_GetDBusAddressFilename(void)
{
Aug 22, 2014
Aug 22, 2014
222
223
224
225
226
227
228
229
230
SDL_DBusContext *dbus;
const char *disp_env;
char config_dir[PATH_MAX];
char *display = NULL;
const char *addr;
const char *conf_env;
char *key;
char file_path[PATH_MAX];
Aug 22, 2014
Aug 22, 2014
231
if (ibus_addr_file) {
232
233
234
return SDL_strdup(ibus_addr_file);
}
Aug 22, 2014
Aug 22, 2014
235
dbus = SDL_DBus_GetContext();
Aug 22, 2014
Aug 22, 2014
236
if (!dbus) {
237
238
239
240
return NULL;
}
/* Use this environment variable if it exists. */
Aug 22, 2014
Aug 22, 2014
241
addr = SDL_getenv("IBUS_ADDRESS");
Aug 22, 2014
Aug 22, 2014
242
if (addr && *addr) {
243
244
245
246
247
return SDL_strdup(addr);
}
/* Otherwise, we have to get the hostname, display, machine id, config dir
and look up the address from a filepath using all those bits, eek. */
Aug 22, 2014
Aug 22, 2014
248
249
disp_env = SDL_getenv("DISPLAY");
Aug 22, 2014
Aug 22, 2014
250
if (!disp_env || !*disp_env) {
251
252
253
254
255
256
257
258
259
display = SDL_strdup(":0.0");
} else {
display = SDL_strdup(disp_env);
}
const char *host = display;
char *disp_num = SDL_strrchr(display, ':'),
*screen_num = SDL_strrchr(display, '.');
Aug 22, 2014
Aug 22, 2014
260
if (!disp_num) {
261
262
263
264
265
266
267
SDL_free(display);
return NULL;
}
*disp_num = 0;
disp_num++;
Aug 22, 2014
Aug 22, 2014
268
if (screen_num) {
269
270
271
*screen_num = 0;
}
Aug 22, 2014
Aug 22, 2014
272
if (!*host) {
273
274
275
276
277
host = "unix";
}
SDL_memset(config_dir, 0, sizeof(config_dir));
Aug 22, 2014
Aug 22, 2014
278
conf_env = SDL_getenv("XDG_CONFIG_HOME");
Aug 22, 2014
Aug 22, 2014
279
if (conf_env && *conf_env) {
280
281
282
SDL_strlcpy(config_dir, conf_env, sizeof(config_dir));
} else {
const char *home_env = SDL_getenv("HOME");
Aug 22, 2014
Aug 22, 2014
283
if (!home_env || !*home_env) {
284
285
286
287
288
289
SDL_free(display);
return NULL;
}
SDL_snprintf(config_dir, sizeof(config_dir), "%s/.config", home_env);
}
Aug 22, 2014
Aug 22, 2014
290
291
key = dbus->get_local_machine_id();
292
293
294
295
296
297
298
299
300
SDL_memset(file_path, 0, sizeof(file_path));
SDL_snprintf(file_path, sizeof(file_path), "%s/ibus/bus/%s-%s-%s",
config_dir, key, host, disp_num);
dbus->free(key);
SDL_free(display);
return SDL_strdup(file_path);
}
Aug 19, 2014
Aug 19, 2014
301
302
303
304
305
306
307
308
static SDL_bool IBus_CheckConnection(SDL_DBusContext *dbus);
static void
IBus_SetCapabilities(void *data, const char *name, const char *old_val,
const char *internal_editing)
{
SDL_DBusContext *dbus = SDL_DBus_GetContext();
Aug 22, 2014
Aug 22, 2014
309
if (IBus_CheckConnection(dbus)) {
Aug 19, 2014
Aug 19, 2014
310
311
312
313
314
DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
input_ctx_path,
IBUS_INPUT_INTERFACE,
"SetCapabilities");
Aug 22, 2014
Aug 22, 2014
315
if (msg) {
Aug 19, 2014
Aug 19, 2014
316
Uint32 caps = IBUS_CAP_FOCUS;
Aug 22, 2014
Aug 22, 2014
317
if (!(internal_editing && *internal_editing == '1')) {
Aug 19, 2014
Aug 19, 2014
318
319
320
321
322
323
324
325
caps |= IBUS_CAP_PREEDIT_TEXT;
}
dbus->message_append_args(msg,
DBUS_TYPE_UINT32, &caps,
DBUS_TYPE_INVALID);
}
Aug 22, 2014
Aug 22, 2014
326
327
if (msg) {
if (dbus->connection_send(ibus_conn, msg, NULL)) {
Aug 19, 2014
Aug 19, 2014
328
329
330
331
332
333
334
335
dbus->connection_flush(ibus_conn);
}
dbus->message_unref(msg);
}
}
}
336
337
338
339
340
static SDL_bool
IBus_SetupConnection(SDL_DBusContext *dbus, const char* addr)
{
const char *path = NULL;
SDL_bool result = SDL_FALSE;
Aug 22, 2014
Aug 22, 2014
341
342
DBusMessage *msg;
343
344
ibus_conn = dbus->connection_open_private(addr, NULL);
Aug 22, 2014
Aug 22, 2014
345
if (!ibus_conn) {
346
347
348
349
350
return SDL_FALSE;
}
dbus->connection_flush(ibus_conn);
Aug 22, 2014
Aug 22, 2014
351
if (!dbus->bus_register(ibus_conn, NULL)) {
352
353
354
355
356
357
ibus_conn = NULL;
return SDL_FALSE;
}
dbus->connection_flush(ibus_conn);
Aug 22, 2014
Aug 22, 2014
358
msg = dbus->message_new_method_call(IBUS_SERVICE, IBUS_PATH, IBUS_INTERFACE, "CreateInputContext");
Aug 22, 2014
Aug 22, 2014
359
if (msg) {
360
361
362
363
364
365
const char *client_name = "SDL2_Application";
dbus->message_append_args(msg,
DBUS_TYPE_STRING, &client_name,
DBUS_TYPE_INVALID);
}
Aug 22, 2014
Aug 22, 2014
366
if (msg) {
367
368
369
DBusMessage *reply;
reply = dbus->connection_send_with_reply_and_block(ibus_conn, msg, 1000, NULL);
Aug 22, 2014
Aug 22, 2014
370
371
if (reply) {
if (dbus->message_get_args(reply, NULL,
372
DBUS_TYPE_OBJECT_PATH, &path,
Aug 22, 2014
Aug 22, 2014
373
374
DBUS_TYPE_INVALID)) {
if (input_ctx_path) {
375
376
377
378
379
380
381
382
383
384
SDL_free(input_ctx_path);
}
input_ctx_path = SDL_strdup(path);
result = SDL_TRUE;
}
dbus->message_unref(reply);
}
dbus->message_unref(msg);
}
Aug 22, 2014
Aug 22, 2014
385
if (result) {
Aug 20, 2014
Aug 20, 2014
386
SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, &IBus_SetCapabilities, NULL);
387
388
389
390
391
392
dbus->bus_add_match(ibus_conn, "type='signal',interface='org.freedesktop.IBus.InputContext'", NULL);
dbus->connection_add_filter(ibus_conn, &IBus_MessageFilter, dbus, NULL);
dbus->connection_flush(ibus_conn);
}
Aug 19, 2014
Aug 19, 2014
393
SDL_IBus_SetFocus(SDL_GetKeyboardFocus() != NULL);
394
395
396
397
398
399
400
401
SDL_IBus_UpdateTextRect(NULL);
return result;
}
static SDL_bool
IBus_CheckConnection(SDL_DBusContext *dbus)
{
Aug 22, 2014
Aug 22, 2014
402
if (!dbus) return SDL_FALSE;
Aug 22, 2014
Aug 22, 2014
404
if (ibus_conn && dbus->connection_get_is_connected(ibus_conn)) {
405
406
407
return SDL_TRUE;
}
Aug 22, 2014
Aug 22, 2014
408
if (inotify_fd > 0 && inotify_wd > 0) {
409
410
char buf[1024];
ssize_t readsize = read(inotify_fd, buf, sizeof(buf));
Aug 22, 2014
Aug 22, 2014
411
if (readsize > 0) {
412
413
414
415
char *p;
SDL_bool file_updated = SDL_FALSE;
Aug 22, 2014
Aug 22, 2014
416
for (p = buf; p < buf + readsize; /**/) {
417
struct inotify_event *event = (struct inotify_event*) p;
Aug 22, 2014
Aug 22, 2014
418
if (event->len > 0) {
419
char *addr_file_no_path = SDL_strrchr(ibus_addr_file, '/');
Aug 22, 2014
Aug 22, 2014
420
if (!addr_file_no_path) return SDL_FALSE;
Aug 22, 2014
Aug 22, 2014
422
if (SDL_strcmp(addr_file_no_path + 1, event->name) == 0) {
423
424
425
426
427
428
429
430
file_updated = SDL_TRUE;
break;
}
}
p += sizeof(struct inotify_event) + event->len;
}
Aug 22, 2014
Aug 22, 2014
431
if (file_updated) {
432
char *addr = IBus_ReadAddressFromFile(ibus_addr_file);
Aug 22, 2014
Aug 22, 2014
433
if (addr) {
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
SDL_bool result = IBus_SetupConnection(dbus, addr);
SDL_free(addr);
return result;
}
}
}
}
return SDL_FALSE;
}
SDL_bool
SDL_IBus_Init(void)
{
SDL_bool result = SDL_FALSE;
SDL_DBusContext *dbus = SDL_DBus_GetContext();
Aug 22, 2014
Aug 22, 2014
451
if (dbus) {
452
char *addr_file = IBus_GetDBusAddressFilename();
Aug 22, 2014
Aug 22, 2014
453
454
455
char *addr;
char *addr_file_dir;
Aug 22, 2014
Aug 22, 2014
456
if (!addr_file) {
457
458
459
460
461
return SDL_FALSE;
}
ibus_addr_file = SDL_strdup(addr_file);
Aug 22, 2014
Aug 22, 2014
462
addr = IBus_ReadAddressFromFile(addr_file);
Aug 22, 2014
Aug 22, 2014
464
if (inotify_fd < 0) {
Aug 19, 2014
Aug 19, 2014
465
466
467
inotify_fd = inotify_init();
fcntl(inotify_fd, F_SETFL, O_NONBLOCK);
}
Aug 22, 2014
Aug 22, 2014
469
addr_file_dir = SDL_strrchr(addr_file, '/');
Aug 22, 2014
Aug 22, 2014
470
if (addr_file_dir) {
471
472
473
*addr_file_dir = 0;
}
Aug 19, 2014
Aug 19, 2014
474
inotify_wd = inotify_add_watch(inotify_fd, addr_file, IN_CREATE | IN_MODIFY);
475
476
477
478
479
480
481
482
483
484
485
486
SDL_free(addr_file);
result = IBus_SetupConnection(dbus, addr);
SDL_free(addr);
}
return result;
}
void
SDL_IBus_Quit(void)
{
Aug 22, 2014
Aug 22, 2014
487
488
SDL_DBusContext *dbus;
Aug 22, 2014
Aug 22, 2014
489
if (input_ctx_path) {
490
491
492
493
SDL_free(input_ctx_path);
input_ctx_path = NULL;
}
Aug 22, 2014
Aug 22, 2014
494
if (ibus_addr_file) {
495
496
497
498
SDL_free(ibus_addr_file);
ibus_addr_file = NULL;
}
Aug 22, 2014
Aug 22, 2014
499
dbus = SDL_DBus_GetContext();
Aug 22, 2014
Aug 22, 2014
501
if (dbus && ibus_conn) {
502
503
504
505
dbus->connection_close(ibus_conn);
dbus->connection_unref(ibus_conn);
}
Aug 22, 2014
Aug 22, 2014
506
if (inotify_fd > 0 && inotify_wd > 0) {
Aug 19, 2014
Aug 19, 2014
507
508
509
510
inotify_rm_watch(inotify_fd, inotify_wd);
inotify_wd = -1;
}
Aug 20, 2014
Aug 20, 2014
511
SDL_DelHintCallback(SDL_HINT_IME_INTERNAL_EDITING, &IBus_SetCapabilities, NULL);
Aug 19, 2014
Aug 19, 2014
512
513
514
515
516
517
518
519
520
SDL_memset(&ibus_cursor_rect, 0, sizeof(ibus_cursor_rect));
}
static void
IBus_SimpleMessage(const char *method)
{
SDL_DBusContext *dbus = SDL_DBus_GetContext();
Aug 22, 2014
Aug 22, 2014
521
if (IBus_CheckConnection(dbus)) {
522
523
524
525
DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
input_ctx_path,
IBUS_INPUT_INTERFACE,
method);
Aug 22, 2014
Aug 22, 2014
526
527
if (msg) {
if (dbus->connection_send(ibus_conn, msg, NULL)) {
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
dbus->connection_flush(ibus_conn);
}
dbus->message_unref(msg);
}
}
}
void
SDL_IBus_SetFocus(SDL_bool focused)
{
const char *method = focused ? "FocusIn" : "FocusOut";
IBus_SimpleMessage(method);
}
void
SDL_IBus_Reset(void)
{
IBus_SimpleMessage("Reset");
}
SDL_bool
SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
{
SDL_bool result = SDL_FALSE;
SDL_DBusContext *dbus = SDL_DBus_GetContext();
Aug 22, 2014
Aug 22, 2014
554
if (IBus_CheckConnection(dbus)) {
555
556
557
558
DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
input_ctx_path,
IBUS_INPUT_INTERFACE,
"ProcessKeyEvent");
Aug 22, 2014
Aug 22, 2014
559
if (msg) {
560
561
562
563
564
565
566
567
Uint32 mods = IBus_ModState();
dbus->message_append_args(msg,
DBUS_TYPE_UINT32, &keysym,
DBUS_TYPE_UINT32, &keycode,
DBUS_TYPE_UINT32, &mods,
DBUS_TYPE_INVALID);
}
Aug 22, 2014
Aug 22, 2014
568
if (msg) {
569
570
571
DBusMessage *reply;
reply = dbus->connection_send_with_reply_and_block(ibus_conn, msg, 300, NULL);
Aug 22, 2014
Aug 22, 2014
572
573
if (reply) {
if (!dbus->message_get_args(reply, NULL,
574
DBUS_TYPE_BOOLEAN, &result,
Aug 22, 2014
Aug 22, 2014
575
DBUS_TYPE_INVALID)) {
576
577
578
579
580
581
582
583
584
result = SDL_FALSE;
}
dbus->message_unref(reply);
}
dbus->message_unref(msg);
}
}
Aug 19, 2014
Aug 19, 2014
585
586
SDL_IBus_UpdateTextRect(NULL);
587
588
589
590
591
592
return result;
}
void
SDL_IBus_UpdateTextRect(SDL_Rect *rect)
{
Aug 22, 2014
Aug 22, 2014
593
594
595
596
SDL_Window *focused_win = SDL_GetKeyboardFocus();
int x = 0, y = 0;
SDL_DBusContext *dbus;
Aug 22, 2014
Aug 22, 2014
597
if (rect) {
598
599
600
SDL_memcpy(&ibus_cursor_rect, rect, sizeof(ibus_cursor_rect));
}
Aug 22, 2014
Aug 22, 2014
601
602
603
604
if (!focused_win) {
return;
}
Aug 19, 2014
Aug 19, 2014
605
606
607
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
Aug 22, 2014
Aug 22, 2014
608
609
610
if (!SDL_GetWindowWMInfo(focused_win, &info)) {
return;
}
Aug 22, 2014
Aug 22, 2014
611
612
SDL_GetWindowPosition(focused_win, &x, &y);
Aug 19, 2014
Aug 19, 2014
613
614
#if SDL_VIDEO_DRIVER_X11
Aug 22, 2014
Aug 22, 2014
615
616
if (info.subsystem == SDL_SYSWM_X11) {
SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(focused_win)->driverdata;
Aug 19, 2014
Aug 19, 2014
617
618
619
620
621
622
Display *x_disp = info.info.x11.display;
Window x_win = info.info.x11.window;
int x_screen = displaydata->screen;
Window unused;
Aug 22, 2014
Aug 22, 2014
623
X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &y, &unused);
Aug 19, 2014
Aug 19, 2014
624
625
626
}
#endif
627
628
629
x += ibus_cursor_rect.x;
y += ibus_cursor_rect.y;
Aug 22, 2014
Aug 22, 2014
630
dbus = SDL_DBus_GetContext();
Aug 22, 2014
Aug 22, 2014
632
if (IBus_CheckConnection(dbus)) {
633
634
635
636
DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
input_ctx_path,
IBUS_INPUT_INTERFACE,
"SetCursorLocation");
Aug 22, 2014
Aug 22, 2014
637
if (msg) {
638
639
640
641
642
643
644
645
dbus->message_append_args(msg,
DBUS_TYPE_INT32, &x,
DBUS_TYPE_INT32, &y,
DBUS_TYPE_INT32, &ibus_cursor_rect.w,
DBUS_TYPE_INT32, &ibus_cursor_rect.h,
DBUS_TYPE_INVALID);
}
Aug 22, 2014
Aug 22, 2014
646
647
if (msg) {
if (dbus->connection_send(ibus_conn, msg, NULL)) {
648
649
650
651
652
653
654
655
656
657
658
659
dbus->connection_flush(ibus_conn);
}
dbus->message_unref(msg);
}
}
}
void
SDL_IBus_PumpEvents(void)
{
SDL_DBusContext *dbus = SDL_DBus_GetContext();
Aug 22, 2014
Aug 22, 2014
660
if (IBus_CheckConnection(dbus)) {
661
662
dbus->connection_read_write(ibus_conn, 0);
Aug 22, 2014
Aug 22, 2014
663
while (dbus->connection_dispatch(ibus_conn) == DBUS_DISPATCH_DATA_REMAINS) {
664
665
666
667
668
669
/* Do nothing, actual work happens in IBus_MessageFilter */
}
}
}
#endif