Fixed bug 5103 - Port fcitx support to both fcitx 4 & 5
authorSam Lantinga <slouken@libsdl.org>
Mon, 11 May 2020 14:31:04 -0700
changeset 13803a73b49512ba2
parent 13801 4298bf108b06
child 13804 ccd76043c80e
Fixed bug 5103 - Port fcitx support to both fcitx 4 & 5

wengxt

Due to the new major fcitx version is coming close, the existing code need to be ported to use new Fcitx dbus interface.

The new dbus interface is supported by both fcitx 4 and 5, and has a good side effect, which is that it will work with flatpak for free. Also the patch remove the dependency on fcitx header. Instead, it just hardcodes a few enum value in the code so need to handle the different header for fcitx4 or 5.
CMakeLists.txt
configure.ac
include/SDL_config.h.cmake
include/SDL_config.h.in
src/core/linux/SDL_dbus.c
src/core/linux/SDL_dbus.h
src/core/linux/SDL_fcitx.c
src/core/linux/SDL_ime.c
src/video/x11/SDL_x11events.c
     1.1 --- a/CMakeLists.txt	Fri May 08 21:50:23 2020 +0200
     1.2 +++ b/CMakeLists.txt	Mon May 11 14:31:04 2020 -0700
     1.3 @@ -1213,6 +1213,8 @@
     1.4          set(HAVE_DBUS_DBUS_H TRUE)
     1.5          include_directories(${DBUS_INCLUDE_DIRS})
     1.6          list(APPEND EXTRA_LIBS ${DBUS_LIBRARIES})
     1.7 +        # Fcitx need only dbus.
     1.8 +        set(HAVE_FCITX TRUE)
     1.9        endif()
    1.10  
    1.11        pkg_search_module(IBUS ibus-1.0 ibus)
    1.12 @@ -1220,6 +1222,9 @@
    1.13          set(HAVE_IBUS_IBUS_H TRUE)
    1.14          include_directories(${IBUS_INCLUDE_DIRS})
    1.15          list(APPEND EXTRA_LIBS ${IBUS_LIBRARIES})
    1.16 +      endif()
    1.17 +
    1.18 +      if (HAVE_IBUS_IBUS_H OR HAVE_FCITX)
    1.19          add_definitions(-DSDL_USE_IME)
    1.20        endif()
    1.21        if(HAVE_LIBUNWIND_H)
    1.22 @@ -1229,8 +1234,6 @@
    1.23          list(APPEND EXTRA_LIBS ${UNWIND_LIBRARIES} ${UNWIND_GENERIC_LIBRARIES})
    1.24        endif()
    1.25      endif()
    1.26 -
    1.27 -    check_include_file("fcitx/frontend.h" HAVE_FCITX_FRONTEND_H)
    1.28    endif()
    1.29  
    1.30    if(INPUT_TSLIB)
     2.1 --- a/configure.ac	Fri May 08 21:50:23 2020 +0200
     2.2 +++ b/configure.ac	Mon May 11 14:31:04 2020 -0700
     2.3 @@ -2731,24 +2731,13 @@
     2.4  AS_HELP_STRING([--enable-fcitx], [enable fcitx support [[default=yes]]]),
     2.5                    , enable_fcitx=yes)
     2.6      if test x$enable_fcitx = xyes; then
     2.7 -        PKG_CHECK_MODULES([FCITX], [fcitx], have_fcitx=yes, have_fcitx=no)
     2.8 -        CFLAGS="$CFLAGS $FCITX_CFLAGS"
     2.9 -        AC_CHECK_HEADER(fcitx/frontend.h,
    2.10 -                        have_fcitx_frontend_h_hdr=yes,
    2.11 -                        have_fcitx_frontend_h_hdr=no)
    2.12 -        CFLAGS="$save_CFLAGS"
    2.13 -        if test x$have_fcitx_frontend_h_hdr = xyes; then
    2.14 -            if test x$enable_ime != xyes; then
    2.15 -                AC_MSG_WARN([IME support is required for fcitx.])
    2.16 -                have_fcitx_frontend_h_hdr=no
    2.17 -            elif test x$enable_dbus != xyes; then
    2.18 -                AC_MSG_WARN([DBus support is required for fcitx.])
    2.19 -                have_fcitx_frontend_h_hdr=no
    2.20 -            else
    2.21 -                AC_DEFINE(HAVE_FCITX_FRONTEND_H, 1, [ ])
    2.22 -                EXTRA_CFLAGS="$EXTRA_CFLAGS $FCITX_CFLAGS"
    2.23 -                SOURCES="$SOURCES $srcdir/src/core/linux/SDL_fcitx.c"
    2.24 -            fi
    2.25 +        if test x$enable_ime != xyes; then
    2.26 +            AC_MSG_WARN([IME support is required for fcitx.])
    2.27 +        elif test x$enable_dbus != xyes; then
    2.28 +            AC_MSG_WARN([DBus support is required for fcitx.])
    2.29 +        else
    2.30 +            AC_DEFINE(HAVE_FCITX, 1, [ ])
    2.31 +            SOURCES="$SOURCES $srcdir/src/core/linux/SDL_fcitx.c"
    2.32          fi
    2.33      fi
    2.34  }
    2.35 @@ -4408,7 +4397,7 @@
    2.36  else
    2.37      SUMMARY="${SUMMARY}Using ibus          : NO\n"
    2.38  fi
    2.39 -if test x$have_fcitx_frontend_h_hdr = xyes; then
    2.40 +if test x$enable_fcitx = xyes; then
    2.41      SUMMARY="${SUMMARY}Using fcitx         : YES\n"
    2.42  else
    2.43      SUMMARY="${SUMMARY}Using fcitx         : NO\n"
     3.1 --- a/include/SDL_config.h.cmake	Fri May 08 21:50:23 2020 +0200
     3.2 +++ b/include/SDL_config.h.cmake	Mon May 11 14:31:04 2020 -0700
     3.3 @@ -203,7 +203,7 @@
     3.4  
     3.5  #cmakedefine HAVE_ALTIVEC_H 1
     3.6  #cmakedefine HAVE_DBUS_DBUS_H 1
     3.7 -#cmakedefine HAVE_FCITX_FRONTEND_H 1
     3.8 +#cmakedefine HAVE_FCITX 1
     3.9  #cmakedefine HAVE_IBUS_IBUS_H 1
    3.10  #cmakedefine HAVE_IMMINTRIN_H 1
    3.11  #cmakedefine HAVE_LIBSAMPLERATE_H 1
     4.1 --- a/include/SDL_config.h.in	Fri May 08 21:50:23 2020 +0200
     4.2 +++ b/include/SDL_config.h.in	Mon May 11 14:31:04 2020 -0700
     4.3 @@ -204,7 +204,7 @@
     4.4  
     4.5  #undef HAVE_ALTIVEC_H
     4.6  #undef HAVE_DBUS_DBUS_H
     4.7 -#undef HAVE_FCITX_FRONTEND_H
     4.8 +#undef HAVE_FCITX
     4.9  #undef HAVE_IBUS_IBUS_H
    4.10  #undef HAVE_IMMINTRIN_H
    4.11  #undef HAVE_LIBSAMPLERATE_H
     5.1 --- a/src/core/linux/SDL_dbus.c	Fri May 08 21:50:23 2020 +0200
     5.2 +++ b/src/core/linux/SDL_dbus.c	Mon May 11 14:31:04 2020 -0700
     5.3 @@ -57,6 +57,10 @@
     5.4      SDL_DBUS_SYM(message_new_method_call);
     5.5      SDL_DBUS_SYM(message_append_args);
     5.6      SDL_DBUS_SYM(message_append_args_valist);
     5.7 +    SDL_DBUS_SYM(message_iter_init_append);
     5.8 +    SDL_DBUS_SYM(message_iter_open_container);
     5.9 +    SDL_DBUS_SYM(message_iter_append_basic);
    5.10 +    SDL_DBUS_SYM(message_iter_close_container);
    5.11      SDL_DBUS_SYM(message_get_args);
    5.12      SDL_DBUS_SYM(message_get_args_valist);
    5.13      SDL_DBUS_SYM(message_iter_init);
     6.1 --- a/src/core/linux/SDL_dbus.h	Fri May 08 21:50:23 2020 +0200
     6.2 +++ b/src/core/linux/SDL_dbus.h	Mon May 11 14:31:04 2020 -0700
     6.3 @@ -54,6 +54,10 @@
     6.4      DBusMessage *(*message_new_method_call)(const char *, const char *, const char *, const char *);
     6.5      dbus_bool_t (*message_append_args)(DBusMessage *, int, ...);
     6.6      dbus_bool_t (*message_append_args_valist)(DBusMessage *, int, va_list);
     6.7 +    void (*message_iter_init_append)(DBusMessage *, DBusMessageIter *);
     6.8 +    dbus_bool_t (*message_iter_open_container)(DBusMessageIter *, int, const char *, DBusMessageIter *);
     6.9 +    dbus_bool_t (*message_iter_append_basic)(DBusMessageIter *, int, const void *);
    6.10 +    dbus_bool_t (*message_iter_close_container)(DBusMessageIter *, DBusMessageIter *);
    6.11      dbus_bool_t (*message_get_args)(DBusMessage *, DBusError *, int, ...);
    6.12      dbus_bool_t (*message_get_args_valist)(DBusMessage *, DBusError *, int, va_list);
    6.13      dbus_bool_t (*message_iter_init)(DBusMessage *, DBusMessageIter *);
     7.1 --- a/src/core/linux/SDL_fcitx.c	Fri May 08 21:50:23 2020 +0200
     7.2 +++ b/src/core/linux/SDL_fcitx.c	Mon May 11 14:31:04 2020 -0700
     7.3 @@ -20,9 +20,6 @@
     7.4  */
     7.5  #include "../../SDL_internal.h"
     7.6  
     7.7 -#ifdef HAVE_FCITX_FRONTEND_H
     7.8 -
     7.9 -#include <fcitx/frontend.h>
    7.10  #include <unistd.h>
    7.11  
    7.12  #include "SDL_fcitx.h"
    7.13 @@ -36,23 +33,20 @@
    7.14  #endif
    7.15  #include "SDL_hints.h"
    7.16  
    7.17 -#define FCITX_DBUS_SERVICE "org.fcitx.Fcitx"
    7.18 +#define FCITX_DBUS_SERVICE "org.freedesktop.portal.Fcitx"
    7.19  
    7.20 -#define FCITX_IM_DBUS_PATH "/inputmethod"
    7.21 -#define FCITX_IC_DBUS_PATH "/inputcontext_%d"
    7.22 +#define FCITX_IM_DBUS_PATH "/org/freedesktop/portal/inputmethod"
    7.23  
    7.24 -#define FCITX_IM_DBUS_INTERFACE "org.fcitx.Fcitx.InputMethod"
    7.25 -#define FCITX_IC_DBUS_INTERFACE "org.fcitx.Fcitx.InputContext"
    7.26 +#define FCITX_IM_DBUS_INTERFACE "org.fcitx.Fcitx.InputMethod1"
    7.27 +#define FCITX_IC_DBUS_INTERFACE "org.fcitx.Fcitx.InputContext1"
    7.28  
    7.29 -#define IC_NAME_MAX 64
    7.30  #define DBUS_TIMEOUT 500
    7.31  
    7.32  typedef struct _FcitxClient
    7.33  {
    7.34      SDL_DBusContext *dbus;
    7.35  
    7.36 -    char servicename[IC_NAME_MAX];
    7.37 -    char icname[IC_NAME_MAX];
    7.38 +    char *ic_path;
    7.39  
    7.40      int id;
    7.41  
    7.42 @@ -61,34 +55,6 @@
    7.43  
    7.44  static FcitxClient fcitx_client;
    7.45  
    7.46 -static int
    7.47 -GetDisplayNumber()
    7.48 -{
    7.49 -    const char *display = SDL_getenv("DISPLAY");
    7.50 -    const char *p = NULL;
    7.51 -    int number = 0;
    7.52 -
    7.53 -    if (display == NULL)
    7.54 -        return 0;
    7.55 -
    7.56 -    display = SDL_strchr(display, ':');
    7.57 -    if (display == NULL)
    7.58 -        return 0;
    7.59 -
    7.60 -    display++;
    7.61 -    p = SDL_strchr(display, '.');
    7.62 -    if (p == NULL && display != NULL) {
    7.63 -        number = SDL_strtod(display, NULL);
    7.64 -    } else {
    7.65 -        char *buffer = SDL_strdup(display);
    7.66 -        buffer[p - display] = '\0';
    7.67 -        number = SDL_strtod(buffer, NULL);
    7.68 -        SDL_free(buffer);
    7.69 -    }
    7.70 -
    7.71 -    return number;
    7.72 -}
    7.73 -
    7.74  static char*
    7.75  GetAppName()
    7.76  {
    7.77 @@ -118,6 +84,54 @@
    7.78      return SDL_strdup("SDL_App");
    7.79  }
    7.80  
    7.81 +size_t Fcitx_GetPreeditString(SDL_DBusContext *dbus, DBusMessage *msg, char **ret) {
    7.82 +    char *text = NULL, *subtext;
    7.83 +    size_t text_bytes = 0;
    7.84 +    DBusMessageIter iter, array, sub;
    7.85 +
    7.86 +    dbus->message_iter_init(msg, &iter);
    7.87 +    /* Message type is a(si)i, we only need string part */
    7.88 +    if (dbus->message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) {
    7.89 +        /* First pass: calculate string length */
    7.90 +        dbus->message_iter_recurse(&iter, &array);
    7.91 +        while (dbus->message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
    7.92 +            dbus->message_iter_recurse(&array, &sub);
    7.93 +            if (dbus->message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
    7.94 +                dbus->message_iter_get_basic(&sub, &subtext);
    7.95 +                if (subtext && *subtext) {
    7.96 +                    text_bytes += SDL_strlen(subtext);
    7.97 +                }
    7.98 +            }
    7.99 +            dbus->message_iter_next(&array);
   7.100 +        }
   7.101 +        if (text_bytes) {
   7.102 +            text = SDL_malloc(text_bytes + 1);
   7.103 +        }
   7.104 +
   7.105 +        if (text) {
   7.106 +            char* pivot = text;
   7.107 +            /* Second pass: join all the sub string */
   7.108 +            dbus->message_iter_recurse(&iter, &array);
   7.109 +            while (dbus->message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
   7.110 +                dbus->message_iter_recurse(&array, &sub);
   7.111 +                if (dbus->message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
   7.112 +                    dbus->message_iter_get_basic(&sub, &subtext);
   7.113 +                    if (subtext && *subtext) {
   7.114 +                        size_t length = SDL_strlen(subtext);
   7.115 +                        SDL_strlcpy(pivot, subtext, length + 1);
   7.116 +                        pivot += length;
   7.117 +                    }
   7.118 +                }
   7.119 +                dbus->message_iter_next(&array);
   7.120 +            }
   7.121 +        } else {
   7.122 +            text_bytes = 0;
   7.123 +        }
   7.124 +    }
   7.125 +    *ret= text;
   7.126 +    return text_bytes;
   7.127 +}
   7.128 +
   7.129  static DBusHandlerResult
   7.130  DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data)
   7.131  {
   7.132 @@ -136,16 +150,12 @@
   7.133          return DBUS_HANDLER_RESULT_HANDLED;
   7.134      }
   7.135  
   7.136 -    if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE, "UpdatePreedit")) {
   7.137 -        DBusMessageIter iter;
   7.138 -        const char *text;
   7.139 -
   7.140 -        dbus->message_iter_init(msg, &iter);
   7.141 -        dbus->message_iter_get_basic(&iter, &text);
   7.142 -
   7.143 -        if (text && *text) {
   7.144 +    if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE, "UpdateFormattedPreedit")) {
   7.145 +        char *text = NULL;
   7.146 +        size_t text_bytes = Fcitx_GetPreeditString(dbus, msg, &text);
   7.147 +        if (text_bytes) {
   7.148              char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
   7.149 -            size_t text_bytes = SDL_strlen(text), i = 0;
   7.150 +            size_t i = 0;
   7.151              size_t cursor = 0;
   7.152  
   7.153              while (i < text_bytes) {
   7.154 @@ -157,6 +167,9 @@
   7.155                  i += sz;
   7.156                  cursor += chars;
   7.157              }
   7.158 +            SDL_free(text);
   7.159 +        } else {
   7.160 +            SDL_SendEditingText("", 0, 0);
   7.161          }
   7.162  
   7.163          SDL_Fcitx_UpdateTextRect(NULL);
   7.164 @@ -169,7 +182,10 @@
   7.165  static void
   7.166  FcitxClientICCallMethod(FcitxClient *client, const char *method)
   7.167  {
   7.168 -    SDL_DBus_CallVoidMethod(client->servicename, client->icname, FCITX_IC_DBUS_INTERFACE, method, DBUS_TYPE_INVALID);
   7.169 +    if (!client->ic_path) {
   7.170 +        return;
   7.171 +    }
   7.172 +    SDL_DBus_CallVoidMethod(FCITX_DBUS_SERVICE, client->ic_path, FCITX_IC_DBUS_INTERFACE, method, DBUS_TYPE_INVALID);
   7.173  }
   7.174  
   7.175  static void SDLCALL
   7.176 @@ -179,40 +195,68 @@
   7.177          const char *internal_editing)
   7.178  {
   7.179      FcitxClient *client = (FcitxClient *)data;
   7.180 -    Uint32 caps = CAPACITY_NONE;
   7.181 +    Uint32 caps = 0;
   7.182 +    if (!client->ic_path) {
   7.183 +        return;
   7.184 +    }
   7.185  
   7.186      if (!(internal_editing && *internal_editing == '1')) {
   7.187 -        caps |= CAPACITY_PREEDIT;
   7.188 +        caps |= (1 << 1); /* Preedit Flag */
   7.189 +        caps |= (1 << 4); /* Formatted Preedit Flag */
   7.190      }
   7.191  
   7.192 -    SDL_DBus_CallVoidMethod(client->servicename, client->icname, FCITX_IC_DBUS_INTERFACE, "SetCapacity", DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID);
   7.193 +    SDL_DBus_CallVoidMethod(FCITX_DBUS_SERVICE, client->ic_path, FCITX_IC_DBUS_INTERFACE, "SetCapability", DBUS_TYPE_UINT64, &caps, DBUS_TYPE_INVALID);
   7.194 +}
   7.195 +
   7.196 +static SDL_bool
   7.197 +FcitxCreateInputContext(SDL_DBusContext* dbus, const char *appname, char **ic_path) {
   7.198 +    const char *program = "program";
   7.199 +    SDL_bool retval = SDL_FALSE;
   7.200 +    if (dbus->session_conn) {
   7.201 +        DBusMessage *msg = dbus->message_new_method_call(FCITX_DBUS_SERVICE, FCITX_IM_DBUS_PATH, FCITX_IM_DBUS_INTERFACE, "CreateInputContext");
   7.202 +        if (msg) {
   7.203 +            DBusMessage *reply = NULL;
   7.204 +            DBusMessageIter args, array, sub;
   7.205 +            dbus->message_iter_init_append(msg, &args);
   7.206 +            dbus->message_iter_open_container(&args, DBUS_TYPE_ARRAY, "(ss)", &array);
   7.207 +            dbus->message_iter_open_container(&array, DBUS_TYPE_STRUCT, 0, &sub);
   7.208 +            dbus->message_iter_append_basic(&sub, DBUS_TYPE_STRING, &program);
   7.209 +            dbus->message_iter_append_basic(&sub, DBUS_TYPE_STRING, &appname);
   7.210 +            dbus->message_iter_close_container(&array, &sub);
   7.211 +            dbus->message_iter_close_container(&args, &array);
   7.212 +            reply = dbus->connection_send_with_reply_and_block(dbus->session_conn, msg, 300, NULL);
   7.213 +            if (reply) {
   7.214 +                if (dbus->message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, ic_path, DBUS_TYPE_INVALID)) {
   7.215 +                    retval = SDL_TRUE;
   7.216 +                }
   7.217 +                dbus->message_unref(reply);
   7.218 +            }
   7.219 +            dbus->message_unref(msg);
   7.220 +        }
   7.221 +    }
   7.222 +    return retval;
   7.223  }
   7.224  
   7.225  static SDL_bool
   7.226  FcitxClientCreateIC(FcitxClient *client)
   7.227  {
   7.228      char *appname = GetAppName();
   7.229 -    pid_t pid = getpid();
   7.230 -    int id = -1;
   7.231 -    Uint32 enable, arg1, arg2, arg3, arg4;
   7.232 +    char *ic_path = NULL;
   7.233 +    SDL_DBusContext *dbus = client->dbus;
   7.234  
   7.235 -    if (!SDL_DBus_CallMethod(client->servicename, FCITX_IM_DBUS_PATH, FCITX_IM_DBUS_INTERFACE, "CreateICv3",
   7.236 -            DBUS_TYPE_STRING, &appname, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID,
   7.237 -            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)) {
   7.238 -        id = -1;  /* just in case. */
   7.239 +    /* SDL_DBus_CallMethod cannot handle a(ss) type, call dbus function directly */
   7.240 +    if (!FcitxCreateInputContext(dbus, appname, &ic_path)) {
   7.241 +        ic_path = NULL;  /* just in case. */
   7.242      }
   7.243  
   7.244      SDL_free(appname);
   7.245  
   7.246 -    if (id >= 0) {
   7.247 -        SDL_DBusContext *dbus = client->dbus;
   7.248 -
   7.249 -        client->id = id;
   7.250 -
   7.251 -        SDL_snprintf(client->icname, IC_NAME_MAX, FCITX_IC_DBUS_PATH, client->id);
   7.252 +    if (ic_path) {
   7.253 +        SDL_free(client->ic_path);
   7.254 +        client->ic_path = SDL_strdup(ic_path);
   7.255  
   7.256          dbus->bus_add_match(dbus->session_conn,
   7.257 -                "type='signal', interface='org.fcitx.Fcitx.InputContext'",
   7.258 +                "type='signal', interface='org.fcitx.Fcitx.InputContext1'",
   7.259                  NULL);
   7.260          dbus->connection_add_filter(dbus->session_conn,
   7.261                  &DBus_MessageFilter, dbus,
   7.262 @@ -232,13 +276,14 @@
   7.263      Uint32 fcitx_mods = 0;
   7.264      SDL_Keymod sdl_mods = SDL_GetModState();
   7.265  
   7.266 -    if (sdl_mods & KMOD_SHIFT) fcitx_mods |= FcitxKeyState_Shift;
   7.267 -    if (sdl_mods & KMOD_CAPS)   fcitx_mods |= FcitxKeyState_CapsLock;
   7.268 -    if (sdl_mods & KMOD_CTRL)  fcitx_mods |= FcitxKeyState_Ctrl;
   7.269 -    if (sdl_mods & KMOD_ALT)   fcitx_mods |= FcitxKeyState_Alt;
   7.270 -    if (sdl_mods & KMOD_NUM)    fcitx_mods |= FcitxKeyState_NumLock;
   7.271 -    if (sdl_mods & KMOD_LGUI)   fcitx_mods |= FcitxKeyState_Super;
   7.272 -    if (sdl_mods & KMOD_RGUI)   fcitx_mods |= FcitxKeyState_Meta;
   7.273 +    if (sdl_mods & KMOD_SHIFT) fcitx_mods |= (1 << 0);
   7.274 +    if (sdl_mods & KMOD_CAPS)   fcitx_mods |= (1 << 1);
   7.275 +    if (sdl_mods & KMOD_CTRL)  fcitx_mods |= (1 << 2);
   7.276 +    if (sdl_mods & KMOD_ALT)   fcitx_mods |= (1 << 3);
   7.277 +    if (sdl_mods & KMOD_NUM)    fcitx_mods |= (1 << 4);
   7.278 +    if (sdl_mods & KMOD_MODE)   fcitx_mods |= (1 << 7);
   7.279 +    if (sdl_mods & KMOD_LGUI)   fcitx_mods |= (1 << 6);
   7.280 +    if (sdl_mods & KMOD_RGUI)   fcitx_mods |= (1 << 28);
   7.281  
   7.282      return fcitx_mods;
   7.283  }
   7.284 @@ -253,10 +298,6 @@
   7.285      fcitx_client.cursor_rect.w = 0;
   7.286      fcitx_client.cursor_rect.h = 0;
   7.287  
   7.288 -    SDL_snprintf(fcitx_client.servicename, IC_NAME_MAX,
   7.289 -            "%s-%d",
   7.290 -            FCITX_DBUS_SERVICE, GetDisplayNumber());
   7.291 -
   7.292      return FcitxClientCreateIC(&fcitx_client);
   7.293  }
   7.294  
   7.295 @@ -264,6 +305,10 @@
   7.296  SDL_Fcitx_Quit()
   7.297  {
   7.298      FcitxClientICCallMethod(&fcitx_client, "DestroyIC");
   7.299 +    if (fcitx_client.ic_path) {
   7.300 +        SDL_free(fcitx_client.ic_path);
   7.301 +        fcitx_client.ic_path = NULL;
   7.302 +    }
   7.303  }
   7.304  
   7.305  void
   7.306 @@ -288,12 +333,16 @@
   7.307  {
   7.308      Uint32 state = Fcitx_ModState();
   7.309      Uint32 handled = SDL_FALSE;
   7.310 -    int type = FCITX_PRESS_KEY;
   7.311 +    Uint32 is_release = SDL_FALSE;
   7.312      Uint32 event_time = 0;
   7.313  
   7.314 -    if (SDL_DBus_CallMethod(fcitx_client.servicename, fcitx_client.icname, FCITX_IC_DBUS_INTERFACE, "ProcessKeyEvent",
   7.315 -            DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INT32, &type, DBUS_TYPE_UINT32, &event_time, DBUS_TYPE_INVALID,
   7.316 -            DBUS_TYPE_INT32, &handled, DBUS_TYPE_INVALID)) {
   7.317 +    if (!fcitx_client.ic_path) {
   7.318 +        return SDL_FALSE;
   7.319 +    }
   7.320 +
   7.321 +    if (SDL_DBus_CallMethod(FCITX_DBUS_SERVICE, fcitx_client.ic_path, FCITX_IC_DBUS_INTERFACE, "ProcessKeyEvent",
   7.322 +            DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &state, DBUS_TYPE_BOOLEAN, &is_release, DBUS_TYPE_UINT32, &event_time, DBUS_TYPE_INVALID,
   7.323 +            DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID)) {
   7.324          if (handled) {
   7.325              SDL_Fcitx_UpdateTextRect(NULL);
   7.326              return SDL_TRUE;
   7.327 @@ -350,7 +399,7 @@
   7.328      x += cursor->x;
   7.329      y += cursor->y;
   7.330  
   7.331 -    SDL_DBus_CallVoidMethod(fcitx_client.servicename, fcitx_client.icname, FCITX_IC_DBUS_INTERFACE, "SetCursorRect",
   7.332 +    SDL_DBus_CallVoidMethod(FCITX_DBUS_SERVICE, fcitx_client.ic_path, FCITX_IC_DBUS_INTERFACE, "SetCursorRect",
   7.333          DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_INT32, &cursor->w, DBUS_TYPE_INT32, &cursor->h, DBUS_TYPE_INVALID);
   7.334  }
   7.335  
   7.336 @@ -368,6 +417,4 @@
   7.337      }
   7.338  }
   7.339  
   7.340 -#endif /* HAVE_FCITX_FRONTEND_H */
   7.341 -
   7.342  /* vi: set ts=4 sw=4 expandtab: */
     8.1 --- a/src/core/linux/SDL_ime.c	Fri May 08 21:50:23 2020 +0200
     8.2 +++ b/src/core/linux/SDL_ime.c	Mon May 11 14:31:04 2020 -0700
     8.3 @@ -43,7 +43,7 @@
     8.4  InitIME()
     8.5  {
     8.6      static SDL_bool inited = SDL_FALSE;
     8.7 -#ifdef HAVE_FCITX_FRONTEND_H
     8.8 +#ifdef HAVE_FCITX
     8.9      const char *im_module = SDL_getenv("SDL_IM_MODULE");
    8.10      const char *xmodifiers = SDL_getenv("XMODIFIERS");
    8.11  #endif
    8.12 @@ -54,7 +54,7 @@
    8.13      inited = SDL_TRUE;
    8.14  
    8.15      /* See if fcitx IME support is being requested */
    8.16 -#ifdef HAVE_FCITX_FRONTEND_H
    8.17 +#ifdef HAVE_FCITX
    8.18      if (!SDL_IME_Init_Real &&
    8.19          ((im_module && SDL_strcmp(im_module, "fcitx") == 0) ||
    8.20           (!im_module && xmodifiers && SDL_strstr(xmodifiers, "@im=fcitx") != NULL))) {
    8.21 @@ -66,7 +66,7 @@
    8.22          SDL_IME_UpdateTextRect_Real = SDL_Fcitx_UpdateTextRect;
    8.23          SDL_IME_PumpEvents_Real = SDL_Fcitx_PumpEvents;
    8.24      }
    8.25 -#endif /* HAVE_FCITX_FRONTEND_H */
    8.26 +#endif /* HAVE_FCITX */
    8.27  
    8.28      /* default to IBus */
    8.29  #ifdef HAVE_IBUS_IBUS_H
     9.1 --- a/src/video/x11/SDL_x11events.c	Fri May 08 21:50:23 2020 +0200
     9.2 +++ b/src/video/x11/SDL_x11events.c	Mon May 11 14:31:04 2020 -0700
     9.3 @@ -683,7 +683,7 @@
     9.4          /* But only if we're using one of the DBus IMEs, otherwise
     9.5             some XIM IMEs will generate duplicate events */
     9.6          if (orig_keycode) {
     9.7 -#if defined(HAVE_IBUS_IBUS_H) || defined(HAVE_FCITX_FRONTEND_H)
     9.8 +#if defined(HAVE_IBUS_IBUS_H) || defined(HAVE_FCITX)
     9.9              SDL_Scancode scancode = videodata->key_layout[orig_keycode];
    9.10              videodata->filter_code = orig_keycode;
    9.11              videodata->filter_time = xevent.xkey.time;