SDL  2.0
SDL_fcitx.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #ifdef HAVE_FCITX_FRONTEND_H
24 
25 #include <fcitx/frontend.h>
26 #include <unistd.h>
27 
28 #include "SDL_fcitx.h"
29 #include "SDL_keycode.h"
30 #include "SDL_keyboard.h"
31 #include "../../events/SDL_keyboard_c.h"
32 #include "SDL_dbus.h"
33 #include "SDL_syswm.h"
34 #if SDL_VIDEO_DRIVER_X11
35 # include "../../video/x11/SDL_x11video.h"
36 #endif
37 #include "SDL_hints.h"
38 
39 #define FCITX_DBUS_SERVICE "org.fcitx.Fcitx"
40 
41 #define FCITX_IM_DBUS_PATH "/inputmethod"
42 #define FCITX_IC_DBUS_PATH "/inputcontext_%d"
43 
44 #define FCITX_IM_DBUS_INTERFACE "org.fcitx.Fcitx.InputMethod"
45 #define FCITX_IC_DBUS_INTERFACE "org.fcitx.Fcitx.InputContext"
46 
47 #define IC_NAME_MAX 64
48 #define DBUS_TIMEOUT 500
49 
50 typedef struct _FcitxClient
51 {
52  SDL_DBusContext *dbus;
53 
54  char servicename[IC_NAME_MAX];
55  char icname[IC_NAME_MAX];
56 
57  int id;
58 
59  SDL_Rect cursor_rect;
60 } FcitxClient;
61 
62 static FcitxClient fcitx_client;
63 
64 static int
65 GetDisplayNumber()
66 {
67  const char *display = SDL_getenv("DISPLAY");
68  const char *p = NULL;
69  int number = 0;
70 
71  if (display == NULL)
72  return 0;
73 
74  display = SDL_strchr(display, ':');
75  if (display == NULL)
76  return 0;
77 
78  display++;
79  p = SDL_strchr(display, '.');
80  if (p == NULL && display != NULL) {
81  number = SDL_strtod(display, NULL);
82  } else {
83  char *buffer = SDL_strdup(display);
84  buffer[p - display] = '\0';
85  number = SDL_strtod(buffer, NULL);
86  SDL_free(buffer);
87  }
88 
89  return number;
90 }
91 
92 static char*
93 GetAppName()
94 {
95 #if defined(__LINUX__) || defined(__FREEBSD__)
96  char *spot;
97  char procfile[1024];
98  char linkfile[1024];
99  int linksize;
100 
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());
105 #endif
106  linksize = readlink(procfile, linkfile, sizeof(linkfile) - 1);
107  if (linksize > 0) {
108  linkfile[linksize] = '\0';
109  spot = SDL_strrchr(linkfile, '/');
110  if (spot) {
111  return SDL_strdup(spot + 1);
112  } else {
113  return SDL_strdup(linkfile);
114  }
115  }
116 #endif /* __LINUX__ || __FREEBSD__ */
117 
118  return SDL_strdup("SDL_App");
119 }
120 
121 static DBusHandlerResult
122 DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data)
123 {
124  SDL_DBusContext *dbus = (SDL_DBusContext *)data;
125 
126  if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE, "CommitString")) {
127  DBusMessageIter iter;
128  const char *text = NULL;
129 
130  dbus->message_iter_init(msg, &iter);
131  dbus->message_iter_get_basic(&iter, &text);
132 
133  if (text)
134  SDL_SendKeyboardText(text);
135 
136  return DBUS_HANDLER_RESULT_HANDLED;
137  }
138 
139  if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE, "UpdatePreedit")) {
140  DBusMessageIter iter;
141  const char *text;
142 
143  dbus->message_iter_init(msg, &iter);
144  dbus->message_iter_get_basic(&iter, &text);
145 
146  if (text && *text) {
148  size_t text_bytes = SDL_strlen(text), i = 0;
149  size_t cursor = 0;
150 
151  while (i < text_bytes) {
152  const size_t sz = SDL_utf8strlcpy(buf, text + i, sizeof(buf));
153  const size_t chars = SDL_utf8strlen(buf);
154 
155  SDL_SendEditingText(buf, cursor, chars);
156 
157  i += sz;
158  cursor += chars;
159  }
160  }
161 
163  return DBUS_HANDLER_RESULT_HANDLED;
164  }
165 
166  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
167 }
168 
169 static void
170 FcitxClientICCallMethod(FcitxClient *client, const char *method)
171 {
172  SDL_DBus_CallVoidMethod(client->servicename, client->icname, FCITX_IC_DBUS_INTERFACE, method, DBUS_TYPE_INVALID);
173 }
174 
175 static void SDLCALL
176 Fcitx_SetCapabilities(void *data,
177  const char *name,
178  const char *old_val,
179  const char *internal_editing)
180 {
181  FcitxClient *client = (FcitxClient *)data;
182  Uint32 caps = CAPACITY_NONE;
183 
184  if (!(internal_editing && *internal_editing == '1')) {
185  caps |= CAPACITY_PREEDIT;
186  }
187 
188  SDL_DBus_CallVoidMethod(client->servicename, client->icname, FCITX_IC_DBUS_INTERFACE, "SetCapacity", DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID);
189 }
190 
191 static SDL_bool
192 FcitxClientCreateIC(FcitxClient *client)
193 {
194  char *appname = GetAppName();
195  pid_t pid = getpid();
196  int id = -1;
197  Uint32 enable, arg1, arg2, arg3, arg4;
198 
199  if (!SDL_DBus_CallMethod(client->servicename, FCITX_IM_DBUS_PATH, FCITX_IM_DBUS_INTERFACE, "CreateICv3",
200  DBUS_TYPE_STRING, &appname, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID,
201  DBUS_TYPE_INT32, &id, DBUS_TYPE_BOOLEAN, &enable, DBUS_TYPE_UINT32, &arg1, DBUS_TYPE_UINT32, &arg2, DBUS_TYPE_UINT32, &arg3, DBUS_TYPE_UINT32, &arg4, DBUS_TYPE_INVALID)) {
202  id = -1; /* just in case. */
203  }
204 
205  SDL_free(appname);
206 
207  if (id >= 0) {
208  SDL_DBusContext *dbus = client->dbus;
209 
210  client->id = id;
211 
212  SDL_snprintf(client->icname, IC_NAME_MAX, FCITX_IC_DBUS_PATH, client->id);
213 
214  dbus->bus_add_match(dbus->session_conn,
215  "type='signal', interface='org.fcitx.Fcitx.InputContext'",
216  NULL);
217  dbus->connection_add_filter(dbus->session_conn,
218  &DBus_MessageFilter, dbus,
219  NULL);
220  dbus->connection_flush(dbus->session_conn);
221 
222  SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, Fcitx_SetCapabilities, client);
223  return SDL_TRUE;
224  }
225 
226  return SDL_FALSE;
227 }
228 
229 static Uint32
230 Fcitx_ModState(void)
231 {
232  Uint32 fcitx_mods = 0;
233  SDL_Keymod sdl_mods = SDL_GetModState();
234 
235  if (sdl_mods & KMOD_SHIFT) fcitx_mods |= FcitxKeyState_Shift;
236  if (sdl_mods & KMOD_CAPS) fcitx_mods |= FcitxKeyState_CapsLock;
237  if (sdl_mods & KMOD_CTRL) fcitx_mods |= FcitxKeyState_Ctrl;
238  if (sdl_mods & KMOD_ALT) fcitx_mods |= FcitxKeyState_Alt;
239  if (sdl_mods & KMOD_NUM) fcitx_mods |= FcitxKeyState_NumLock;
240  if (sdl_mods & KMOD_LGUI) fcitx_mods |= FcitxKeyState_Super;
241  if (sdl_mods & KMOD_RGUI) fcitx_mods |= FcitxKeyState_Meta;
242 
243  return fcitx_mods;
244 }
245 
246 SDL_bool
248 {
249  fcitx_client.dbus = SDL_DBus_GetContext();
250 
251  fcitx_client.cursor_rect.x = -1;
252  fcitx_client.cursor_rect.y = -1;
253  fcitx_client.cursor_rect.w = 0;
254  fcitx_client.cursor_rect.h = 0;
255 
256  SDL_snprintf(fcitx_client.servicename, IC_NAME_MAX,
257  "%s-%d",
258  FCITX_DBUS_SERVICE, GetDisplayNumber());
259 
260  return FcitxClientCreateIC(&fcitx_client);
261 }
262 
263 void
265 {
266  FcitxClientICCallMethod(&fcitx_client, "DestroyIC");
267 }
268 
269 void
271 {
272  if (focused) {
273  FcitxClientICCallMethod(&fcitx_client, "FocusIn");
274  } else {
275  FcitxClientICCallMethod(&fcitx_client, "FocusOut");
276  }
277 }
278 
279 void
280 SDL_Fcitx_Reset(void)
281 {
282  FcitxClientICCallMethod(&fcitx_client, "Reset");
283  FcitxClientICCallMethod(&fcitx_client, "CloseIC");
284 }
285 
286 SDL_bool
287 SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
288 {
289  Uint32 state = Fcitx_ModState();
290  Uint32 handled = SDL_FALSE;
291  int type = FCITX_PRESS_KEY;
292  Uint32 event_time = 0;
293 
294  if (SDL_DBus_CallMethod(fcitx_client.servicename, fcitx_client.icname, FCITX_IC_DBUS_INTERFACE, "ProcessKeyEvent",
295  DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INT32, &type, DBUS_TYPE_UINT32, &event_time, DBUS_TYPE_INVALID,
296  DBUS_TYPE_INT32, &handled, DBUS_TYPE_INVALID)) {
297  if (handled) {
299  return SDL_TRUE;
300  }
301  }
302 
303  return SDL_FALSE;
304 }
305 
306 void
308 {
309  SDL_Window *focused_win = NULL;
310  SDL_SysWMinfo info;
311  int x = 0, y = 0;
312  SDL_Rect *cursor = &fcitx_client.cursor_rect;
313 
314  if (rect) {
315  SDL_memcpy(cursor, rect, sizeof(SDL_Rect));
316  }
317 
318  focused_win = SDL_GetKeyboardFocus();
319  if (!focused_win) {
320  return ;
321  }
322 
323  SDL_VERSION(&info.version);
324  if (!SDL_GetWindowWMInfo(focused_win, &info)) {
325  return;
326  }
327 
328  SDL_GetWindowPosition(focused_win, &x, &y);
329 
330 #if SDL_VIDEO_DRIVER_X11
331  if (info.subsystem == SDL_SYSWM_X11) {
332  SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(focused_win)->driverdata;
333 
334  Display *x_disp = info.info.x11.display;
335  Window x_win = info.info.x11.window;
336  int x_screen = displaydata->screen;
337  Window unused;
338  X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &y, &unused);
339  }
340 #endif
341 
342  if (cursor->x == -1 && cursor->y == -1 && cursor->w == 0 && cursor->h == 0) {
343  /* move to bottom left */
344  int w = 0, h = 0;
345  SDL_GetWindowSize(focused_win, &w, &h);
346  cursor->x = 0;
347  cursor->y = h;
348  }
349 
350  x += cursor->x;
351  y += cursor->y;
352 
353  SDL_DBus_CallVoidMethod(fcitx_client.servicename, fcitx_client.icname, FCITX_IC_DBUS_INTERFACE, "SetCursorRect",
354  DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_INT32, &cursor->w, DBUS_TYPE_INT32, &cursor->h, DBUS_TYPE_INVALID);
355 }
356 
357 void
359 {
360  SDL_DBusContext *dbus = fcitx_client.dbus;
361  DBusConnection *conn = dbus->session_conn;
362 
363  dbus->connection_read_write(conn, 0);
364 
365  while (dbus->connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS) {
366  /* Do nothing, actual work happens in DBus_MessageFilter */
367  usleep(10);
368  }
369 }
370 
371 #endif /* HAVE_FCITX_FRONTEND_H */
372 
373 /* vi: set ts=4 sw=4 expandtab: */
GLuint id
void SDL_Fcitx_UpdateTextRect(SDL_Rect *rect)
#define SDL_utf8strlen
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
GLuint GLuint GLuint GLuint arg1
SDL_Rect rect
Definition: testrelative.c:27
#define KMOD_CTRL
Definition: SDL_keycode.h:342
GLfloat GLfloat GLfloat GLfloat h
struct xkb_state * state
GLfloat GLfloat p
#define SDL_utf8strlcpy
SDL_version version
Definition: SDL_syswm.h:196
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
#define KMOD_ALT
Definition: SDL_keycode.h:344
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:197
#define SDL_GetKeyboardFocus
GLuint const GLchar * name
#define SDL_strchr
SDL_bool SDL_Fcitx_Init(void)
#define SDL_VERSION(x)
Macro to determine SDL version program was compiled against.
Definition: SDL_version.h:79
#define SDL_GetWindowSize
#define SDL_memcpy
#define KMOD_SHIFT
Definition: SDL_keycode.h:343
void SDL_Fcitx_Reset(void)
int SDL_SendKeyboardText(const char *text)
Definition: SDL_keyboard.c:789
#define SDL_free
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
GLubyte GLubyte GLubyte GLubyte w
#define SDL_GetWindowPosition
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
int x
Definition: SDL_rect.h:66
void SDL_Fcitx_PumpEvents(void)
SDL_Cursor * cursor
Definition: testwm2.c:40
GLenum GLuint GLenum GLsizei const GLchar * buf
int w
Definition: SDL_rect.h:67
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...
Definition: SDL_hints.h:837
SDL_Keymod
Enumeration of valid key mods (possibly OR&#39;d together).
Definition: SDL_keycode.h:325
#define SDL_getenv
#define SDL_strtod
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)
Definition: SDL_x11sym.h:50
#define SDL_GetWindowWMInfo
#define NULL
Definition: begin_code.h:164
void SDL_Fcitx_Quit(void)
SDL_bool
Definition: SDL_stdinc.h:161
GLuint buffer
GLboolean enable
static char text[MAX_TEXT_LENGTH]
Definition: testime.c:47
SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1092
#define SDL_strlen
int h
Definition: SDL_rect.h:67
#define SDL_strdup
The type used to identify a window.
Definition: SDL_sysvideo.h:73
GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg3
uint32_t Uint32
Definition: SDL_stdinc.h:203
#define SDL_AddHintCallback
void SDL_Fcitx_SetFocus(SDL_bool focused)
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
#define SDL_snprintf
union SDL_SysWMinfo::@18 info
#define SDLCALL
Definition: SDL_internal.h:45
#define SDL_strrchr
#define SDL_GetModState
int y
Definition: SDL_rect.h:66
int SDL_SendEditingText(const char *text, int start, int length)
Definition: SDL_keyboard.c:812
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
#define SDL_TEXTEDITINGEVENT_TEXT_SIZE
Definition: SDL_events.h:223