21 #include "../../SDL_internal.h" 23 #ifdef HAVE_FCITX_FRONTEND_H 25 #include <fcitx/frontend.h> 31 #include "../../events/SDL_keyboard_c.h" 34 #if SDL_VIDEO_DRIVER_X11 35 # include "../../video/x11/SDL_x11video.h" 39 #define FCITX_DBUS_SERVICE "org.fcitx.Fcitx" 41 #define FCITX_IM_DBUS_PATH "/inputmethod" 42 #define FCITX_IC_DBUS_PATH "/inputcontext_%d" 44 #define FCITX_IM_DBUS_INTERFACE "org.fcitx.Fcitx.InputMethod" 45 #define FCITX_IC_DBUS_INTERFACE "org.fcitx.Fcitx.InputContext" 47 #define IC_NAME_MAX 64 48 #define DBUS_TIMEOUT 500 50 typedef struct _FcitxClient
52 SDL_DBusContext *dbus;
54 char servicename[IC_NAME_MAX];
55 char icname[IC_NAME_MAX];
62 static FcitxClient fcitx_client;
84 buffer[p - display] =
'\0';
95 #if defined(__LINUX__) || defined(__FREEBSD__) 101 #if defined(__LINUX__) 102 SDL_snprintf(procfile,
sizeof(procfile),
"/proc/%d/exe", getpid());
103 #elif defined(__FREEBSD__) 104 SDL_snprintf(procfile,
sizeof(procfile),
"/proc/%d/file", getpid());
106 linksize = readlink(procfile, linkfile,
sizeof(linkfile) - 1);
108 linkfile[linksize] =
'\0';
124 #define CONT(i) ISUTF8_CB(in[i]) 125 #define VAL(i, s) ((in[i]&0x3f) << s) 128 _fcitx_utf8_get_char(
const char *
i,
uint32_t *chr)
130 const unsigned char*
in = (
const unsigned char *)i;
131 if (!(in[0] & 0x80)) {
133 return (
char *)in + 1;
137 if ((in[0] & 0xe0) == 0xc0 && CONT(1)) {
138 *chr = ((in[0] & 0x1f) << 6) | VAL(1, 0);
139 return (
char *)in + 2;
143 if ((in[0] & 0xf0) == 0xe0 && CONT(1) && CONT(2)) {
144 *chr = ((in[0] & 0xf) << 12) | VAL(1, 6) | VAL(2, 0);
145 return (
char *)in + 3;
149 if ((in[0] & 0xf8) == 0xf0 && CONT(1) && CONT(2) && CONT(3)) {
150 *chr = ((in[0] & 0x7) << 18) | VAL(1, 12) | VAL(2, 6) | VAL(3, 0);
151 return (
char *)in + 4;
155 if ((in[0] & 0xfc) == 0xf8 && CONT(1) && CONT(2) && CONT(3) && CONT(4)) {
156 *chr = ((in[0] & 0x3) << 24) | VAL(1, 18) | VAL(2, 12) | VAL(3, 6) | VAL(4, 0);
157 return (
char *)in + 5;
161 if ((in[0] & 0xfe) == 0xfc && CONT(1) && CONT(2) && CONT(3) && CONT(4) && CONT(5)) {
162 *chr = ((in[0] & 0x1) << 30) | VAL(1, 24) | VAL(2, 18) | VAL(3, 12) | VAL(4, 6) | VAL(5, 0);
163 return (
char *)in + 6;
168 return (
char *)in + 1;
172 _fcitx_utf8_strlen(
const char *
s)
179 s = _fcitx_utf8_get_char(s, &chr);
186 static DBusHandlerResult
187 DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg,
void *
data)
189 SDL_DBusContext *dbus = (SDL_DBusContext *)data;
191 if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE,
"CommitString")) {
192 DBusMessageIter iter;
195 dbus->message_iter_init(msg, &iter);
196 dbus->message_iter_get_basic(&iter, &text);
201 return DBUS_HANDLER_RESULT_HANDLED;
204 if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE,
"UpdatePreedit")) {
205 DBusMessageIter iter;
208 dbus->message_iter_init(msg, &iter);
209 dbus->message_iter_get_basic(&iter, &text);
216 while (i < text_bytes) {
218 size_t chars = _fcitx_utf8_strlen(buf);
228 return DBUS_HANDLER_RESULT_HANDLED;
231 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
235 FcitxClientICNewMethod(FcitxClient *client,
238 SDL_DBusContext *dbus = client->dbus;
239 return dbus->message_new_method_call(
242 FCITX_IC_DBUS_INTERFACE,
247 FcitxClientICCallMethod(FcitxClient *client,
250 SDL_DBusContext *dbus = client->dbus;
251 DBusMessage *msg = FcitxClientICNewMethod(client, method);
256 if (dbus->connection_send(dbus->session_conn, msg,
NULL)) {
257 dbus->connection_flush(dbus->session_conn);
260 dbus->message_unref(msg);
264 Fcitx_SetCapabilities(
void *data,
267 const char *internal_editing)
269 FcitxClient *client = (FcitxClient *)data;
270 SDL_DBusContext *dbus = client->dbus;
271 Uint32 caps = CAPACITY_NONE;
273 DBusMessage *msg = FcitxClientICNewMethod(client,
"SetCapacity");
277 if (!(internal_editing && *internal_editing ==
'1')) {
278 caps |= CAPACITY_PREEDIT;
281 dbus->message_append_args(msg,
282 DBUS_TYPE_UINT32, &caps,
284 if (dbus->connection_send(dbus->session_conn, msg,
NULL)) {
285 dbus->connection_flush(dbus->session_conn);
288 dbus->message_unref(msg);
292 FcitxClientCreateIC(FcitxClient *client)
294 char *appname =
NULL;
300 SDL_DBusContext *dbus = client->dbus;
301 DBusMessage *reply =
NULL;
302 DBusMessage *msg = dbus->message_new_method_call(
305 FCITX_IM_DBUS_INTERFACE,
312 appname = GetAppName();
314 dbus->message_append_args(msg,
315 DBUS_TYPE_STRING, &appname,
316 DBUS_TYPE_INT32, &pid,
320 reply = dbus->connection_send_with_reply_and_block(
328 if (!dbus->message_get_args(reply,
NULL,
329 DBUS_TYPE_INT32, &
id,
330 DBUS_TYPE_BOOLEAN, &enable,
331 DBUS_TYPE_UINT32, &arg1,
332 DBUS_TYPE_UINT32, &arg2,
333 DBUS_TYPE_UINT32, &arg3,
334 DBUS_TYPE_UINT32, &arg4,
343 FCITX_IC_DBUS_PATH, client->id);
345 dbus->bus_add_match(dbus->session_conn,
346 "type='signal', interface='org.fcitx.Fcitx.InputContext'",
348 dbus->connection_add_filter(dbus->session_conn,
349 &DBus_MessageFilter, dbus,
351 dbus->connection_flush(dbus->session_conn);
358 dbus->message_unref(reply);
359 dbus->message_unref(msg);
369 if (sdl_mods &
KMOD_SHIFT) fcitx_mods |= FcitxKeyState_Shift;
370 if (sdl_mods &
KMOD_CAPS) fcitx_mods |= FcitxKeyState_CapsLock;
371 if (sdl_mods &
KMOD_CTRL) fcitx_mods |= FcitxKeyState_Ctrl;
372 if (sdl_mods &
KMOD_ALT) fcitx_mods |= FcitxKeyState_Alt;
373 if (sdl_mods &
KMOD_NUM) fcitx_mods |= FcitxKeyState_NumLock;
374 if (sdl_mods &
KMOD_LGUI) fcitx_mods |= FcitxKeyState_Super;
375 if (sdl_mods &
KMOD_RGUI) fcitx_mods |= FcitxKeyState_Meta;
383 fcitx_client.dbus = SDL_DBus_GetContext();
385 fcitx_client.cursor_rect.x = -1;
386 fcitx_client.cursor_rect.y = -1;
387 fcitx_client.cursor_rect.w = 0;
388 fcitx_client.cursor_rect.h = 0;
392 FCITX_DBUS_SERVICE, GetDisplayNumber());
394 FcitxClientCreateIC(&fcitx_client);
402 FcitxClientICCallMethod(&fcitx_client,
"DestroyIC");
409 FcitxClientICCallMethod(&fcitx_client,
"FocusIn");
411 FcitxClientICCallMethod(&fcitx_client,
"FocusOut");
418 FcitxClientICCallMethod(&fcitx_client,
"Reset");
419 FcitxClientICCallMethod(&fcitx_client,
"CloseIC");
425 DBusMessage *msg =
NULL;
426 DBusMessage *reply =
NULL;
427 SDL_DBusContext *dbus = fcitx_client.dbus;
431 int type = FCITX_PRESS_KEY;
434 msg = FcitxClientICNewMethod(&fcitx_client,
"ProcessKeyEvent");
438 state = Fcitx_ModState();
439 dbus->message_append_args(msg,
440 DBUS_TYPE_UINT32, &keysym,
441 DBUS_TYPE_UINT32, &keycode,
442 DBUS_TYPE_UINT32, &state,
443 DBUS_TYPE_INT32, &type,
444 DBUS_TYPE_UINT32, &event_time,
447 reply = dbus->connection_send_with_reply_and_block(dbus->session_conn,
453 dbus->message_get_args(reply,
455 DBUS_TYPE_INT32, &handled,
458 dbus->message_unref(reply);
476 SDL_DBusContext *dbus = fcitx_client.dbus;
477 DBusMessage *msg =
NULL;
478 DBusConnection *conn;
496 #if SDL_VIDEO_DRIVER_X11 500 Display *x_disp = info.
info.
x11.display;
501 Window x_win = info.
info.
x11.window;
502 int x_screen = displaydata->
screen;
504 X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &
y, &unused);
508 if (cursor->
x == -1 && cursor->
y == -1 && cursor->
w == 0 && cursor->
h == 0) {
519 msg = FcitxClientICNewMethod(&fcitx_client,
"SetCursorRect");
523 dbus->message_append_args(msg,
526 DBUS_TYPE_INT32, &cursor->
w,
527 DBUS_TYPE_INT32, &cursor->
h,
530 conn = dbus->session_conn;
531 if (dbus->connection_send(conn, msg,
NULL))
532 dbus->connection_flush(conn);
534 dbus->message_unref(msg);
540 SDL_DBusContext *dbus = fcitx_client.dbus;
541 DBusConnection *conn = dbus->session_conn;
543 dbus->connection_read_write(conn, 0);
545 while (dbus->connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS) {
void SDL_Fcitx_UpdateTextRect(SDL_Rect *rect)
GLuint GLuint GLuint GLuint arg1
GLint GLint GLint GLint GLint x
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
GLuint const GLchar * name
#define SDL_GetKeyboardFocus
uint32_t Uint32
An unsigned 32-bit integer type.
SDL_bool SDL_Fcitx_Init(void)
#define SDL_VERSION(x)
Macro to determine SDL version program was compiled against.
#define SDL_GetWindowSize
GLuint GLuint GLsizei GLenum type
void SDL_Fcitx_PumpEvents()
GLint GLint GLint GLint GLint GLint y
void SDL_Fcitx_Reset(void)
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
void SDL_Fcitx_Quit(void)
static char text[MAX_TEXT_LENGTH]
SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
The type used to identify a window.
GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg3
#define SDL_AddHintCallback
void SDL_Fcitx_SetFocus(SDL_bool focused)
union SDL_SysWMinfo::@18 info
GLubyte GLubyte GLubyte GLubyte w
GLfloat GLfloat GLfloat GLfloat h
int SDL_SendEditingText(const char *text, int start, int length)
A rectangle, with the origin at the upper left.
#define SDL_TEXTEDITINGEVENT_TEXT_SIZE