Skip to content

Latest commit

 

History

History
671 lines (534 loc) · 19.2 KB

SDL_ibus.c

File metadata and controls

671 lines (534 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
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 24, 2014
Aug 24, 2014
230
231
const char *host;
char *disp_num, *screen_num;
Aug 22, 2014
Aug 22, 2014
232
Aug 22, 2014
Aug 22, 2014
233
if (ibus_addr_file) {
234
235
236
return SDL_strdup(ibus_addr_file);
}
Aug 22, 2014
Aug 22, 2014
237
dbus = SDL_DBus_GetContext();
Aug 22, 2014
Aug 22, 2014
238
if (!dbus) {
239
240
241
242
return NULL;
}
/* Use this environment variable if it exists. */
Aug 22, 2014
Aug 22, 2014
243
addr = SDL_getenv("IBUS_ADDRESS");
Aug 22, 2014
Aug 22, 2014
244
if (addr && *addr) {
245
246
247
248
249
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
250
251
disp_env = SDL_getenv("DISPLAY");
Aug 22, 2014
Aug 22, 2014
252
if (!disp_env || !*disp_env) {
253
254
255
256
257
display = SDL_strdup(":0.0");
} else {
display = SDL_strdup(disp_env);
}
Aug 24, 2014
Aug 24, 2014
258
259
260
host = display;
disp_num = SDL_strrchr(display, ':');
screen_num = SDL_strrchr(display, '.');
Aug 22, 2014
Aug 22, 2014
262
if (!disp_num) {
263
264
265
266
267
268
269
SDL_free(display);
return NULL;
}
*disp_num = 0;
disp_num++;
Aug 22, 2014
Aug 22, 2014
270
if (screen_num) {
271
272
273
*screen_num = 0;
}
Aug 22, 2014
Aug 22, 2014
274
if (!*host) {
275
276
277
278
279
host = "unix";
}
SDL_memset(config_dir, 0, sizeof(config_dir));
Aug 22, 2014
Aug 22, 2014
280
conf_env = SDL_getenv("XDG_CONFIG_HOME");
Aug 22, 2014
Aug 22, 2014
281
if (conf_env && *conf_env) {
282
283
284
SDL_strlcpy(config_dir, conf_env, sizeof(config_dir));
} else {
const char *home_env = SDL_getenv("HOME");
Aug 22, 2014
Aug 22, 2014
285
if (!home_env || !*home_env) {
286
287
288
289
290
291
SDL_free(display);
return NULL;
}
SDL_snprintf(config_dir, sizeof(config_dir), "%s/.config", home_env);
}
Aug 22, 2014
Aug 22, 2014
292
293
key = dbus->get_local_machine_id();
294
295
296
297
298
299
300
301
302
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
303
304
305
306
307
308
309
310
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
311
if (IBus_CheckConnection(dbus)) {
Aug 19, 2014
Aug 19, 2014
312
313
314
315
316
DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
input_ctx_path,
IBUS_INPUT_INTERFACE,
"SetCapabilities");
Aug 22, 2014
Aug 22, 2014
317
if (msg) {
Aug 19, 2014
Aug 19, 2014
318
Uint32 caps = IBUS_CAP_FOCUS;
Aug 22, 2014
Aug 22, 2014
319
if (!(internal_editing && *internal_editing == '1')) {
Aug 19, 2014
Aug 19, 2014
320
321
322
323
324
325
326
327
caps |= IBUS_CAP_PREEDIT_TEXT;
}
dbus->message_append_args(msg,
DBUS_TYPE_UINT32, &caps,
DBUS_TYPE_INVALID);
}
Aug 22, 2014
Aug 22, 2014
328
329
if (msg) {
if (dbus->connection_send(ibus_conn, msg, NULL)) {
Aug 19, 2014
Aug 19, 2014
330
331
332
333
334
335
336
337
dbus->connection_flush(ibus_conn);
}
dbus->message_unref(msg);
}
}
}
338
339
340
341
342
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
343
344
DBusMessage *msg;
345
346
ibus_conn = dbus->connection_open_private(addr, NULL);
Aug 22, 2014
Aug 22, 2014
347
if (!ibus_conn) {
348
349
350
351
352
return SDL_FALSE;
}
dbus->connection_flush(ibus_conn);
Aug 22, 2014
Aug 22, 2014
353
if (!dbus->bus_register(ibus_conn, NULL)) {
354
355
356
357
358
359
ibus_conn = NULL;
return SDL_FALSE;
}
dbus->connection_flush(ibus_conn);
Aug 22, 2014
Aug 22, 2014
360
msg = dbus->message_new_method_call(IBUS_SERVICE, IBUS_PATH, IBUS_INTERFACE, "CreateInputContext");
Aug 22, 2014
Aug 22, 2014
361
if (msg) {
362
363
364
365
366
367
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
368
if (msg) {
369
370
371
DBusMessage *reply;
reply = dbus->connection_send_with_reply_and_block(ibus_conn, msg, 1000, NULL);
Aug 22, 2014
Aug 22, 2014
372
373
if (reply) {
if (dbus->message_get_args(reply, NULL,
374
DBUS_TYPE_OBJECT_PATH, &path,
Aug 22, 2014
Aug 22, 2014
375
376
DBUS_TYPE_INVALID)) {
if (input_ctx_path) {
377
378
379
380
381
382
383
384
385
386
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
387
if (result) {
Aug 20, 2014
Aug 20, 2014
388
SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, &IBus_SetCapabilities, NULL);
389
390
391
392
393
394
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
395
SDL_IBus_SetFocus(SDL_GetKeyboardFocus() != NULL);
396
397
398
399
400
401
402
403
SDL_IBus_UpdateTextRect(NULL);
return result;
}
static SDL_bool
IBus_CheckConnection(SDL_DBusContext *dbus)
{
Aug 22, 2014
Aug 22, 2014
404
if (!dbus) return SDL_FALSE;
Aug 22, 2014
Aug 22, 2014
406
if (ibus_conn && dbus->connection_get_is_connected(ibus_conn)) {
407
408
409
return SDL_TRUE;
}
Aug 22, 2014
Aug 22, 2014
410
if (inotify_fd > 0 && inotify_wd > 0) {
411
412
char buf[1024];
ssize_t readsize = read(inotify_fd, buf, sizeof(buf));
Aug 22, 2014
Aug 22, 2014
413
if (readsize > 0) {
414
415
416
417
char *p;
SDL_bool file_updated = SDL_FALSE;
Aug 22, 2014
Aug 22, 2014
418
for (p = buf; p < buf + readsize; /**/) {
419
struct inotify_event *event = (struct inotify_event*) p;
Aug 22, 2014
Aug 22, 2014
420
if (event->len > 0) {
421
char *addr_file_no_path = SDL_strrchr(ibus_addr_file, '/');
Aug 22, 2014
Aug 22, 2014
422
if (!addr_file_no_path) return SDL_FALSE;
Aug 22, 2014
Aug 22, 2014
424
if (SDL_strcmp(addr_file_no_path + 1, event->name) == 0) {
425
426
427
428
429
430
431
432
file_updated = SDL_TRUE;
break;
}
}
p += sizeof(struct inotify_event) + event->len;
}
Aug 22, 2014
Aug 22, 2014
433
if (file_updated) {
434
char *addr = IBus_ReadAddressFromFile(ibus_addr_file);
Aug 22, 2014
Aug 22, 2014
435
if (addr) {
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
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
453
if (dbus) {
454
char *addr_file = IBus_GetDBusAddressFilename();
Aug 22, 2014
Aug 22, 2014
455
456
457
char *addr;
char *addr_file_dir;
Aug 22, 2014
Aug 22, 2014
458
if (!addr_file) {
459
460
461
462
463
return SDL_FALSE;
}
ibus_addr_file = SDL_strdup(addr_file);
Aug 22, 2014
Aug 22, 2014
464
addr = IBus_ReadAddressFromFile(addr_file);
Aug 22, 2014
Aug 22, 2014
466
if (inotify_fd < 0) {
Aug 19, 2014
Aug 19, 2014
467
468
469
inotify_fd = inotify_init();
fcntl(inotify_fd, F_SETFL, O_NONBLOCK);
}
Aug 22, 2014
Aug 22, 2014
471
addr_file_dir = SDL_strrchr(addr_file, '/');
Aug 22, 2014
Aug 22, 2014
472
if (addr_file_dir) {
473
474
475
*addr_file_dir = 0;
}
Aug 19, 2014
Aug 19, 2014
476
inotify_wd = inotify_add_watch(inotify_fd, addr_file, IN_CREATE | IN_MODIFY);
477
478
479
480
481
482
483
484
485
486
487
488
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
489
490
SDL_DBusContext *dbus;
Aug 22, 2014
Aug 22, 2014
491
if (input_ctx_path) {
492
493
494
495
SDL_free(input_ctx_path);
input_ctx_path = NULL;
}
Aug 22, 2014
Aug 22, 2014
496
if (ibus_addr_file) {
497
498
499
500
SDL_free(ibus_addr_file);
ibus_addr_file = NULL;
}
Aug 22, 2014
Aug 22, 2014
501
dbus = SDL_DBus_GetContext();
Aug 22, 2014
Aug 22, 2014
503
if (dbus && ibus_conn) {
504
505
506
507
dbus->connection_close(ibus_conn);
dbus->connection_unref(ibus_conn);
}
Aug 22, 2014
Aug 22, 2014
508
if (inotify_fd > 0 && inotify_wd > 0) {
Aug 19, 2014
Aug 19, 2014
509
510
511
512
inotify_rm_watch(inotify_fd, inotify_wd);
inotify_wd = -1;
}
Aug 20, 2014
Aug 20, 2014
513
SDL_DelHintCallback(SDL_HINT_IME_INTERNAL_EDITING, &IBus_SetCapabilities, NULL);
Aug 19, 2014
Aug 19, 2014
514
515
516
517
518
519
520
521
522
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
523
if (IBus_CheckConnection(dbus)) {
524
525
526
527
DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
input_ctx_path,
IBUS_INPUT_INTERFACE,
method);
Aug 22, 2014
Aug 22, 2014
528
529
if (msg) {
if (dbus->connection_send(ibus_conn, msg, NULL)) {
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
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
556
if (IBus_CheckConnection(dbus)) {
557
558
559
560
DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
input_ctx_path,
IBUS_INPUT_INTERFACE,
"ProcessKeyEvent");
Aug 22, 2014
Aug 22, 2014
561
if (msg) {
562
563
564
565
566
567
568
569
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
570
if (msg) {
571
572
573
DBusMessage *reply;
reply = dbus->connection_send_with_reply_and_block(ibus_conn, msg, 300, NULL);
Aug 22, 2014
Aug 22, 2014
574
575
if (reply) {
if (!dbus->message_get_args(reply, NULL,
576
DBUS_TYPE_BOOLEAN, &result,
Aug 22, 2014
Aug 22, 2014
577
DBUS_TYPE_INVALID)) {
578
579
580
581
582
583
584
585
586
result = SDL_FALSE;
}
dbus->message_unref(reply);
}
dbus->message_unref(msg);
}
}
Aug 19, 2014
Aug 19, 2014
587
588
SDL_IBus_UpdateTextRect(NULL);
589
590
591
592
593
594
return result;
}
void
SDL_IBus_UpdateTextRect(SDL_Rect *rect)
{
Aug 23, 2014
Aug 23, 2014
595
596
SDL_Window *focused_win;
SDL_SysWMinfo info;
Aug 22, 2014
Aug 22, 2014
597
598
599
int x = 0, y = 0;
SDL_DBusContext *dbus;
Aug 22, 2014
Aug 22, 2014
600
if (rect) {
601
602
603
SDL_memcpy(&ibus_cursor_rect, rect, sizeof(ibus_cursor_rect));
}
Aug 23, 2014
Aug 23, 2014
604
focused_win = SDL_GetKeyboardFocus();
Aug 22, 2014
Aug 22, 2014
605
606
607
608
if (!focused_win) {
return;
}
Aug 19, 2014
Aug 19, 2014
609
SDL_VERSION(&info.version);
Aug 22, 2014
Aug 22, 2014
610
611
612
if (!SDL_GetWindowWMInfo(focused_win, &info)) {
return;
}
Aug 22, 2014
Aug 22, 2014
613
614
SDL_GetWindowPosition(focused_win, &x, &y);
Aug 19, 2014
Aug 19, 2014
615
616
#if SDL_VIDEO_DRIVER_X11
Aug 22, 2014
Aug 22, 2014
617
618
if (info.subsystem == SDL_SYSWM_X11) {
SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(focused_win)->driverdata;
Aug 19, 2014
Aug 19, 2014
619
620
621
622
623
624
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
625
X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &y, &unused);
Aug 19, 2014
Aug 19, 2014
626
627
628
}
#endif
629
630
631
x += ibus_cursor_rect.x;
y += ibus_cursor_rect.y;
Aug 22, 2014
Aug 22, 2014
632
dbus = SDL_DBus_GetContext();
Aug 22, 2014
Aug 22, 2014
634
if (IBus_CheckConnection(dbus)) {
635
636
637
638
DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
input_ctx_path,
IBUS_INPUT_INTERFACE,
"SetCursorLocation");
Aug 22, 2014
Aug 22, 2014
639
if (msg) {
640
641
642
643
644
645
646
647
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
648
649
if (msg) {
if (dbus->connection_send(ibus_conn, msg, NULL)) {
650
651
652
653
654
655
656
657
658
659
660
661
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
662
if (IBus_CheckConnection(dbus)) {
663
664
dbus->connection_read_write(ibus_conn, 0);
Aug 22, 2014
Aug 22, 2014
665
while (dbus->connection_dispatch(ibus_conn) == DBUS_DISPATCH_DATA_REMAINS) {
666
667
668
669
670
671
/* Do nothing, actual work happens in IBus_MessageFilter */
}
}
}
#endif