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;
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';
121 static DBusHandlerResult
122 DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg,
void *
data)
124 SDL_DBusContext *dbus = (SDL_DBusContext *)
data;
126 if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE,
"CommitString")) {
127 DBusMessageIter iter;
130 dbus->message_iter_init(msg, &iter);
131 dbus->message_iter_get_basic(&iter, &
text);
136 return DBUS_HANDLER_RESULT_HANDLED;
139 if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE,
"UpdatePreedit")) {
140 DBusMessageIter iter;
143 dbus->message_iter_init(msg, &iter);
144 dbus->message_iter_get_basic(&iter, &
text);
151 while (
i < text_bytes) {
163 return DBUS_HANDLER_RESULT_HANDLED;
166 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
170 FcitxClientICCallMethod(FcitxClient *client,
const char *method)
172 SDL_DBus_CallVoidMethod(client->servicename, client->icname, FCITX_IC_DBUS_INTERFACE, method, DBUS_TYPE_INVALID);
176 Fcitx_SetCapabilities(
void *
data,
179 const char *internal_editing)
181 FcitxClient *client = (FcitxClient *)
data;
182 Uint32 caps = CAPACITY_NONE;
184 if (!(internal_editing && *internal_editing ==
'1')) {
185 caps |= CAPACITY_PREEDIT;
188 SDL_DBus_CallVoidMethod(client->servicename, client->icname, FCITX_IC_DBUS_INTERFACE,
"SetCapacity", DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID);
192 FcitxClientCreateIC(FcitxClient *client)
194 char *appname = GetAppName();
195 pid_t pid = getpid();
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)) {
208 SDL_DBusContext *dbus = client->dbus;
212 SDL_snprintf(client->icname, IC_NAME_MAX, FCITX_IC_DBUS_PATH, client->id);
214 dbus->bus_add_match(dbus->session_conn,
215 "type='signal', interface='org.fcitx.Fcitx.InputContext'",
217 dbus->connection_add_filter(dbus->session_conn,
218 &DBus_MessageFilter, dbus,
220 dbus->connection_flush(dbus->session_conn);
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;
249 fcitx_client.dbus = SDL_DBus_GetContext();
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;
258 FCITX_DBUS_SERVICE, GetDisplayNumber());
260 return FcitxClientCreateIC(&fcitx_client);
266 FcitxClientICCallMethod(&fcitx_client,
"DestroyIC");
273 FcitxClientICCallMethod(&fcitx_client,
"FocusIn");
275 FcitxClientICCallMethod(&fcitx_client,
"FocusOut");
282 FcitxClientICCallMethod(&fcitx_client,
"Reset");
283 FcitxClientICCallMethod(&fcitx_client,
"CloseIC");
291 int type = FCITX_PRESS_KEY;
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)) {
330 #if SDL_VIDEO_DRIVER_X11
334 Display *x_disp = info.
info.
x11.display;
335 Window x_win = info.
info.
x11.window;
336 int x_screen = displaydata->
screen;
338 X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &
x, &
y, &unused);
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);
360 SDL_DBusContext *dbus = fcitx_client.dbus;
361 DBusConnection *conn = dbus->session_conn;
363 dbus->connection_read_write(conn, 0);
365 while (dbus->connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS) {