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)
#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