21 #include "../../SDL_internal.h" 23 #ifdef HAVE_IBUS_IBUS_H 28 #include "../../video/SDL_sysvideo.h" 29 #include "../../events/SDL_keyboard_c.h" 31 #if SDL_VIDEO_DRIVER_X11 32 #include "../../video/x11/SDL_x11video.h" 35 #include <sys/inotify.h> 39 static const char IBUS_SERVICE[] =
"org.freedesktop.IBus";
40 static const char IBUS_PATH[] =
"/org/freedesktop/IBus";
41 static const char IBUS_INTERFACE[] =
"org.freedesktop.IBus";
42 static const char IBUS_INPUT_INTERFACE[] =
"org.freedesktop.IBus.InputContext";
44 static char *input_ctx_path =
NULL;
45 static SDL_Rect ibus_cursor_rect = { 0, 0, 0, 0 };
46 static DBusConnection *ibus_conn =
NULL;
47 static char *ibus_addr_file =
NULL;
48 int inotify_fd = -1, inotify_wd = -1;
57 if (sdl_mods &
KMOD_LSHIFT) ibus_mods |= IBUS_SHIFT_MASK;
58 if (sdl_mods &
KMOD_CAPS) ibus_mods |= IBUS_LOCK_MASK;
59 if (sdl_mods &
KMOD_LCTRL) ibus_mods |= IBUS_CONTROL_MASK;
60 if (sdl_mods &
KMOD_LALT) ibus_mods |= IBUS_MOD1_MASK;
61 if (sdl_mods &
KMOD_NUM) ibus_mods |= IBUS_MOD2_MASK;
62 if (sdl_mods &
KMOD_MODE) ibus_mods |= IBUS_MOD5_MASK;
63 if (sdl_mods &
KMOD_LGUI) ibus_mods |= IBUS_SUPER_MASK;
64 if (sdl_mods &
KMOD_RGUI) ibus_mods |= IBUS_META_MASK;
70 IBus_GetVariantText(DBusConnection *conn, DBusMessageIter *iter, SDL_DBusContext *dbus)
74 const char *struct_id =
NULL;
75 DBusMessageIter sub1, sub2;
77 if (dbus->message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT) {
81 dbus->message_iter_recurse(iter, &sub1);
83 if (dbus->message_iter_get_arg_type(&sub1) != DBUS_TYPE_STRUCT) {
87 dbus->message_iter_recurse(&sub1, &sub2);
89 if (dbus->message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
93 dbus->message_iter_get_basic(&sub2, &struct_id);
94 if (!struct_id ||
SDL_strncmp(struct_id,
"IBusText",
sizeof(
"IBusText")) != 0) {
98 dbus->message_iter_next(&sub2);
99 dbus->message_iter_next(&sub2);
101 if (dbus->message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
105 dbus->message_iter_get_basic(&sub2, &text);
111 IBus_utf8_strlen(
const char *str)
116 for (p = str; *
p; ++
p) {
117 if (!((*p & 0x80) && !(*p & 0x40))) {
125 static DBusHandlerResult
126 IBus_MessageHandler(DBusConnection *conn, DBusMessage *msg,
void *user_data)
128 SDL_DBusContext *dbus = (SDL_DBusContext *)user_data;
130 if (dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE,
"CommitText")) {
131 DBusMessageIter iter;
134 dbus->message_iter_init(msg, &iter);
136 text = IBus_GetVariantText(conn, &iter, dbus);
141 while (
i < text_bytes) {
149 return DBUS_HANDLER_RESULT_HANDLED;
152 if (dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE,
"UpdatePreeditText")) {
153 DBusMessageIter iter;
156 dbus->message_iter_init(msg, &iter);
157 text = IBus_GetVariantText(conn, &iter, dbus);
166 size_t chars = IBus_utf8_strlen(buf);
172 }
while (
i < text_bytes);
175 SDL_IBus_UpdateTextRect(
NULL);
177 return DBUS_HANDLER_RESULT_HANDLED;
180 if (dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE,
"HidePreeditText")) {
182 return DBUS_HANDLER_RESULT_HANDLED;
185 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
189 IBus_ReadAddressFromFile(
const char *file_path)
195 addr_file = fopen(file_path,
"r");
200 while (fgets(addr_buf,
sizeof(addr_buf), addr_file)) {
201 if (
SDL_strncmp(addr_buf,
"IBUS_ADDRESS=",
sizeof(
"IBUS_ADDRESS=")-1) == 0) {
203 if (addr_buf[sz-1] ==
'\n') addr_buf[sz-1] = 0;
204 if (addr_buf[sz-2] ==
'\r') addr_buf[sz-2] = 0;
213 return SDL_strdup(addr_buf + (
sizeof(
"IBUS_ADDRESS=") - 1));
220 IBus_GetDBusAddressFilename(
void)
222 SDL_DBusContext *dbus;
223 const char *disp_env;
224 char config_dir[PATH_MAX];
225 char *display =
NULL;
227 const char *conf_env;
229 char file_path[PATH_MAX];
231 char *disp_num, *screen_num;
233 if (ibus_addr_file) {
237 dbus = SDL_DBus_GetContext();
252 if (!disp_env || !*disp_env) {
278 SDL_memset(config_dir, 0,
sizeof(config_dir));
281 if (conf_env && *conf_env) {
282 SDL_strlcpy(config_dir, conf_env,
sizeof(config_dir));
285 if (!home_env || !*home_env) {
289 SDL_snprintf(config_dir,
sizeof(config_dir),
"%s/.config", home_env);
292 key = dbus->get_local_machine_id();
295 SDL_snprintf(file_path,
sizeof(file_path),
"%s/ibus/bus/%s-%s-%s",
296 config_dir, key, host, disp_num);
303 static SDL_bool IBus_CheckConnection(SDL_DBusContext *dbus);
306 IBus_SetCapabilities(
void *
data,
const char *
name,
const char *old_val,
307 const char *internal_editing)
309 SDL_DBusContext *dbus = SDL_DBus_GetContext();
311 if (IBus_CheckConnection(dbus)) {
313 DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
315 IBUS_INPUT_INTERFACE,
318 Uint32 caps = IBUS_CAP_FOCUS;
319 if (!(internal_editing && *internal_editing ==
'1')) {
320 caps |= IBUS_CAP_PREEDIT_TEXT;
323 dbus->message_append_args(msg,
324 DBUS_TYPE_UINT32, &caps,
329 if (dbus->connection_send(ibus_conn, msg,
NULL)) {
330 dbus->connection_flush(ibus_conn);
332 dbus->message_unref(msg);
339 IBus_SetupConnection(SDL_DBusContext *dbus,
const char* addr)
344 DBusObjectPathVTable ibus_vtable;
347 ibus_vtable.message_function = &IBus_MessageHandler;
349 ibus_conn = dbus->connection_open_private(addr,
NULL);
355 dbus->connection_flush(ibus_conn);
357 if (!dbus->bus_register(ibus_conn,
NULL)) {
362 dbus->connection_flush(ibus_conn);
364 msg = dbus->message_new_method_call(IBUS_SERVICE, IBUS_PATH, IBUS_INTERFACE,
"CreateInputContext");
366 const char *client_name =
"SDL2_Application";
367 dbus->message_append_args(msg,
368 DBUS_TYPE_STRING, &client_name,
375 reply = dbus->connection_send_with_reply_and_block(ibus_conn, msg, 1000,
NULL);
377 if (dbus->message_get_args(reply,
NULL,
378 DBUS_TYPE_OBJECT_PATH, &path,
379 DBUS_TYPE_INVALID)) {
380 if (input_ctx_path) {
386 dbus->message_unref(reply);
388 dbus->message_unref(msg);
394 dbus->bus_add_match(ibus_conn,
"type='signal',interface='org.freedesktop.IBus.InputContext'",
NULL);
395 dbus->connection_try_register_object_path(ibus_conn, input_ctx_path, &ibus_vtable, dbus,
NULL);
396 dbus->connection_flush(ibus_conn);
400 SDL_IBus_UpdateTextRect(
NULL);
406 IBus_CheckConnection(SDL_DBusContext *dbus)
410 if (ibus_conn && dbus->connection_get_is_connected(ibus_conn)) {
414 if (inotify_fd > 0 && inotify_wd > 0) {
416 ssize_t readsize = read(inotify_fd, buf,
sizeof(buf));
422 for (p = buf; p < buf + readsize; ) {
423 struct inotify_event *
event = (
struct inotify_event*) p;
424 if (
event->len > 0) {
425 char *addr_file_no_path =
SDL_strrchr(ibus_addr_file,
'/');
426 if (!addr_file_no_path)
return SDL_FALSE;
434 p +=
sizeof(
struct inotify_event) +
event->
len;
438 char *addr = IBus_ReadAddressFromFile(ibus_addr_file);
440 SDL_bool result = IBus_SetupConnection(dbus, addr);
455 SDL_DBusContext *dbus = SDL_DBus_GetContext();
458 char *addr_file = IBus_GetDBusAddressFilename();
469 addr = IBus_ReadAddressFromFile(addr_file);
475 if (inotify_fd < 0) {
476 inotify_fd = inotify_init();
477 fcntl(inotify_fd, F_SETFL, O_NONBLOCK);
485 inotify_wd = inotify_add_watch(inotify_fd, addr_file, IN_CREATE | IN_MODIFY);
489 result = IBus_SetupConnection(dbus, addr);
500 SDL_DBusContext *dbus;
502 if (input_ctx_path) {
504 input_ctx_path =
NULL;
507 if (ibus_addr_file) {
509 ibus_addr_file =
NULL;
512 dbus = SDL_DBus_GetContext();
514 if (dbus && ibus_conn) {
515 dbus->connection_close(ibus_conn);
516 dbus->connection_unref(ibus_conn);
519 if (inotify_fd > 0 && inotify_wd > 0) {
520 inotify_rm_watch(inotify_fd, inotify_wd);
526 SDL_memset(&ibus_cursor_rect, 0,
sizeof(ibus_cursor_rect));
530 IBus_SimpleMessage(
const char *method)
532 SDL_DBusContext *dbus = SDL_DBus_GetContext();
534 if (IBus_CheckConnection(dbus)) {
535 DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
537 IBUS_INPUT_INTERFACE,
540 if (dbus->connection_send(ibus_conn, msg,
NULL)) {
541 dbus->connection_flush(ibus_conn);
543 dbus->message_unref(msg);
551 const char *method = focused ?
"FocusIn" :
"FocusOut";
552 IBus_SimpleMessage(method);
558 IBus_SimpleMessage(
"Reset");
565 SDL_DBusContext *dbus = SDL_DBus_GetContext();
567 if (IBus_CheckConnection(dbus)) {
568 DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
570 IBUS_INPUT_INTERFACE,
573 Uint32 mods = IBus_ModState();
574 dbus->message_append_args(msg,
575 DBUS_TYPE_UINT32, &keysym,
576 DBUS_TYPE_UINT32, &keycode,
577 DBUS_TYPE_UINT32, &mods,
584 reply = dbus->connection_send_with_reply_and_block(ibus_conn, msg, 300,
NULL);
586 if (!dbus->message_get_args(reply,
NULL,
587 DBUS_TYPE_BOOLEAN, &result,
588 DBUS_TYPE_INVALID)) {
591 dbus->message_unref(reply);
593 dbus->message_unref(msg);
598 SDL_IBus_UpdateTextRect(
NULL);
609 SDL_DBusContext *dbus;
612 SDL_memcpy(&ibus_cursor_rect, rect,
sizeof(ibus_cursor_rect));
627 #if SDL_VIDEO_DRIVER_X11 631 Display *x_disp = info.
info.
x11.display;
632 Window x_win = info.
info.
x11.window;
633 int x_screen = displaydata->
screen;
636 X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &
y, &unused);
640 x += ibus_cursor_rect.
x;
641 y += ibus_cursor_rect.
y;
643 dbus = SDL_DBus_GetContext();
645 if (IBus_CheckConnection(dbus)) {
646 DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
648 IBUS_INPUT_INTERFACE,
649 "SetCursorLocation");
651 dbus->message_append_args(msg,
654 DBUS_TYPE_INT32, &ibus_cursor_rect.
w,
655 DBUS_TYPE_INT32, &ibus_cursor_rect.
h,
660 if (dbus->connection_send(ibus_conn, msg,
NULL)) {
661 dbus->connection_flush(ibus_conn);
663 dbus->message_unref(msg);
669 SDL_IBus_PumpEvents(
void)
671 SDL_DBusContext *dbus = SDL_DBus_GetContext();
673 if (IBus_CheckConnection(dbus)) {
674 dbus->connection_read_write(ibus_conn, 0);
676 while (dbus->connection_dispatch(ibus_conn) == DBUS_DISPATCH_DATA_REMAINS) {
GLint GLint GLint GLint GLint x
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLuint const GLchar * name
#define SDL_GetKeyboardFocus
uint32_t Uint32
An unsigned 32-bit integer type.
#define SDL_VERSION(x)
Macro to determine SDL version program was compiled against.
GLint GLint GLint GLint GLint GLint y
int SDL_SendKeyboardText(const char *text)
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst op &r &cond WK op &r &cond WK op &r &cond WK else op &m &cond &ia op &r &cond WK else op &m &cond &ia elseif elseif else error unsupported base if elseif elseif else error unsupported unaligned pixldst unaligned endm macro pixst base base else pixldst base endif endm macro PF base if bpp PF set rept prefetch_distance PF set OFFSET endr endif endm macro preload_leading_step2 base if bpp ifc DST PF PF else if bpp lsl PF PF lsl PF PF lsl PF PF PF else PF lsl PF lsl PF lsl PF endif SIZE macro preload_middle scratch_holds_offset if bpp if else PF PF endif endif endif endm macro preload_trailing base if bpp if bpp *pix_per_block PF PF lsl PF PF PF PF PF else PF lsl PF lsl PF PF PF PF PF base if bpp if narrow_case &&bpp<=dst_w_bpp) PF bic, WK0, base, #31 PF pld, [WK0] PF add, WK1, base, X, LSL #bpp_shift PF sub, WK1, WK1, #1 PF bic, WK1, WK1, #31 PF cmp, WK1, WK0 PF beq, 90f PF pld, [WK1]90:.else PF bic, WK0, base, #31 PF pld, [WK0] PF add, WK1, base, X, lsl #bpp_shift PF sub, WK1, WK1, #1 PF bic, WK1, WK1, #31 PF cmp, WK1, WK0 PF beq, 92f91:PF add, WK0, WK0, #32 PF cmp, WK0, WK1 PF pld, [WK0] PF bne, 91b92:.endif .endif.endm.macro conditional_process1_helper cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, 0 .if decrementx sub &cond X, X, #8 *numbytes/dst_w_bpp .endif process_tail cond, numbytes, firstreg .if !((flags) &FLAG_PROCESS_DOES_STORE) pixst cond, numbytes, firstreg, DST .endif.endm.macro conditional_process1 cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx .if(flags) &FLAG_BRANCH_OVER .ifc cond, mi bpl 100f .endif .ifc cond, cs bcc 100f .endif .ifc cond, ne beq 100f .endif conditional_process1_helper, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx100:.else conditional_process1_helper cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx .endif.endm.macro conditional_process2 test, cond1, cond2, process_head, process_tail, numbytes1, numbytes2, firstreg1, firstreg2, unaligned_src, unaligned_mask, decrementx .if(flags) &(FLAG_DST_READWRITE|FLAG_BRANCH_OVER|FLAG_PROCESS_CORRUPTS_PSR|FLAG_PROCESS_DOES_STORE) test conditional_process1 cond1, process_head, process_tail, numbytes1, firstreg1, unaligned_src, unaligned_mask, decrementx .if(flags) &FLAG_PROCESS_CORRUPTS_PSR test .endif conditional_process1 cond2, process_head, process_tail, numbytes2, firstreg2, unaligned_src, unaligned_mask, decrementx .else test process_head cond1, numbytes1, firstreg1, unaligned_src, unaligned_mask, 0 process_head cond2, numbytes2, firstreg2, unaligned_src, unaligned_mask, 0 .if decrementx sub &cond1 X, X, #8 *numbytes1/dst_w_bpp sub &cond2 X, X, #8 *numbytes2/dst_w_bpp .endif process_tail cond1, numbytes1, firstreg1 process_tail cond2, numbytes2, firstreg2 pixst cond1, numbytes1, firstreg1, DST pixst cond2, numbytes2, firstreg2, DST .endif.endm.macro test_bits_1_0_ptr .if(flags) &FLAG_PROCESS_CORRUPTS_WK0 movs SCRATCH, X, lsl #32-1 .else movs SCRATCH, WK0, lsl #32-1 .endif.endm.macro test_bits_3_2_ptr .if(flags) &FLAG_PROCESS_CORRUPTS_WK0 movs SCRATCH, X, lsl #32-3 .else movs SCRATCH, WK0, lsl #32-3 .endif.endm.macro leading_15bytes process_head, process_tail .set DECREMENT_X, 1 .if(flags) &FLAG_PROCESS_CORRUPTS_WK0 .set DECREMENT_X, 0 sub X, X, WK0, lsr #dst_bpp_shift str X, [sp, #LINE_SAVED_REG_COUNT *4] mov X, WK0 .endif .if dst_w_bpp==8 conditional_process2 test_bits_1_0_ptr, mi, cs, process_head, process_tail, 1, 2, 1, 2, 1, 1, DECREMENT_X .elseif dst_w_bpp==16 test_bits_1_0_ptr conditional_process1 cs, process_head, process_tail, 2, 2, 1, 1, DECREMENT_X .endif conditional_process2 test_bits_3_2_ptr, mi, cs, process_head, process_tail, 4, 8, 1, 2, 1, 1, DECREMENT_X .if(flags) &FLAG_PROCESS_CORRUPTS_WK0 ldr X, [sp, #LINE_SAVED_REG_COUNT *4] .endif.endm.macro test_bits_3_2_pix movs SCRATCH, X, lsl #dst_bpp_shift+32-3.endm.macro test_bits_1_0_pix .if dst_w_bpp==8 movs SCRATCH, X, lsl #dst_bpp_shift+32-1 .else movs SCRATCH, X, lsr #1 .endif.endm.macro trailing_15bytes process_head, process_tail, unaligned_src, unaligned_mask conditional_process2 test_bits_3_2_pix, cs, mi, process_head, process_tail, 8, 4, 0, 2, unaligned_src, unaligned_mask, 0 .if dst_w_bpp==16 test_bits_1_0_pix conditional_process1 cs, process_head, process_tail, 2, 0, unaligned_src, unaligned_mask, 0 .elseif dst_w_bpp==8 conditional_process2 test_bits_1_0_pix, cs, mi, process_head, process_tail, 2, 1, 0, 1, unaligned_src, unaligned_mask, 0 .endif.endm.macro wide_case_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, dst_alignment110:.set SUBBLOCK, 0 .rept pix_per_block *dst_w_bpp/128 process_head, 16, 0, unaligned_src, unaligned_mask, 1 .if(src_bpp > 0) &&(mask_bpp==0) &&((flags) &FLAG_PROCESS_PRESERVES_SCRATCH) preload_middle src_bpp, SRC, 1 .elseif(src_bpp==0) &&(mask_bpp > 0) &&((flags) &FLAG_PROCESS_PRESERVES_SCRATCH) preload_middle mask_bpp, MASK, 1 .else preload_middle src_bpp, SRC, 0 preload_middle mask_bpp, MASK, 0 .endif .if(dst_r_bpp > 0) &&((SUBBLOCK % 2)==0) &&(((flags) &FLAG_NO_PRELOAD_DST)==0) PF pld, [DST, #32 *prefetch_distance - dst_alignment] .endif process_tail, 16, 0 .if !((flags) &FLAG_PROCESS_DOES_STORE) pixst, 16, 0, DST .endif .set SUBBLOCK, SUBBLOCK+1 .endr subs X, X, #pix_per_block bhs 110b.endm.macro wide_case_inner_loop_and_trailing_pixels process_head, process_tail, process_inner_loop, exit_label, unaligned_src, unaligned_mask .if dst_r_bpp > tst bne process_inner_loop DST_PRELOAD_BIAS endif preload_trailing SRC preload_trailing MASK DST endif add medium_case_inner_loop_and_trailing_pixels unaligned_mask endm macro medium_case_inner_loop_and_trailing_pixels unused
#define SDL_GetWindowPosition
GLenum GLuint GLenum GLsizei const GLchar * buf
struct SDL_SysWMinfo::@18::@19 x11
#define SDL_HINT_IME_INTERNAL_EDITING
A variable to control whether certain IMEs should handle text editing internally instead of sending S...
SDL_Keymod
Enumeration of valid key mods (possibly OR'd together).
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
#define SDL_GetWindowWMInfo
static char text[MAX_TEXT_LENGTH]
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
The type used to identify a window.
#define SDL_AddHintCallback
#define SDL_DelHintCallback
union SDL_SysWMinfo::@18 info
GLsizei const GLchar *const * path
int SDL_SendEditingText(const char *text, int start, int length)
A rectangle, with the origin at the upper left.
#define SDL_TEXTEDITINGEVENT_TEXT_SIZE