linux: Simplify D-Bus interface, remove lots of boilerplate.
authorRyan C. Gordon <icculus@icculus.org>
Sun, 28 May 2017 07:11:52 -0400
changeset 11042303c875e47f0
parent 11041 5aebcca5ff18
child 11043 5be3faa49e54
linux: Simplify D-Bus interface, remove lots of boilerplate.
src/core/linux/SDL_dbus.c
src/core/linux/SDL_dbus.h
src/core/linux/SDL_fcitx.c
src/core/linux/SDL_ibus.c
src/video/x11/SDL_x11video.c
     1.1 --- a/src/core/linux/SDL_dbus.c	Sun May 28 07:08:10 2017 -0400
     1.2 +++ b/src/core/linux/SDL_dbus.c	Sun May 28 07:11:52 2017 -0400
     1.3 @@ -56,7 +56,9 @@
     1.4      SDL_DBUS_SYM(message_is_signal);
     1.5      SDL_DBUS_SYM(message_new_method_call);
     1.6      SDL_DBUS_SYM(message_append_args);
     1.7 +    SDL_DBUS_SYM(message_append_args_valist);
     1.8      SDL_DBUS_SYM(message_get_args);
     1.9 +    SDL_DBUS_SYM(message_get_args_valist);
    1.10      SDL_DBUS_SYM(message_iter_init);
    1.11      SDL_DBUS_SYM(message_iter_next);
    1.12      SDL_DBUS_SYM(message_iter_get_basic);
    1.13 @@ -157,91 +159,170 @@
    1.14      }
    1.15  }
    1.16  
    1.17 -void
    1.18 -SDL_DBus_ScreensaverTickle(void)
    1.19 +static SDL_bool
    1.20 +SDL_DBus_CallMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap)
    1.21  {
    1.22 -    DBusConnection *conn = dbus.session_conn;
    1.23 -    if (conn != NULL) {
    1.24 -        DBusMessage *msg = dbus.message_new_method_call("org.gnome.ScreenSaver",
    1.25 -                                                        "/org/gnome/ScreenSaver",
    1.26 -                                                        "org.gnome.ScreenSaver",
    1.27 -                                                        "SimulateUserActivity");
    1.28 -        if (msg != NULL) {
    1.29 -            if (dbus.connection_send(conn, msg, NULL)) {
    1.30 -                dbus.connection_flush(conn);
    1.31 +    SDL_bool retval = SDL_FALSE;
    1.32 +
    1.33 +    if (conn) {
    1.34 +        DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method);
    1.35 +        if (msg) {
    1.36 +            int firstarg = va_arg(ap, int);
    1.37 +            if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) {
    1.38 +                DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
    1.39 +                if (reply) {
    1.40 +                    firstarg = va_arg(ap, int);
    1.41 +                    if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_get_args_valist(reply, NULL, firstarg, ap)) {
    1.42 +                        retval = SDL_TRUE;
    1.43 +                    }
    1.44 +                    dbus.message_unref(reply);
    1.45 +                }
    1.46              }
    1.47              dbus.message_unref(msg);
    1.48          }
    1.49      }
    1.50 +
    1.51 +    return retval;
    1.52 +}
    1.53 +
    1.54 +SDL_bool
    1.55 +SDL_DBus_CallMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...)
    1.56 +{
    1.57 +    SDL_bool retval;
    1.58 +    va_list ap;
    1.59 +    va_start(ap, method);
    1.60 +    retval = SDL_DBus_CallMethodInternal(conn, node, path, interface, method, ap);
    1.61 +    va_end(ap);
    1.62 +    return retval;
    1.63 +}
    1.64 +
    1.65 +SDL_bool
    1.66 +SDL_DBus_CallMethod(const char *node, const char *path, const char *interface, const char *method, ...)
    1.67 +{
    1.68 +    SDL_bool retval;
    1.69 +    va_list ap;
    1.70 +    va_start(ap, method);
    1.71 +    retval = SDL_DBus_CallMethodInternal(dbus.session_conn, node, path, interface, method, ap);
    1.72 +    va_end(ap);
    1.73 +    return retval;
    1.74 +}
    1.75 +
    1.76 +static SDL_bool
    1.77 +SDL_DBus_CallVoidMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap)
    1.78 +{
    1.79 +    SDL_bool retval = SDL_FALSE;
    1.80 +
    1.81 +    if (conn) {
    1.82 +        DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method);
    1.83 +        if (msg) {
    1.84 +            int firstarg = va_arg(ap, int);
    1.85 +            if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) {
    1.86 +                if (dbus.connection_send(conn, msg, NULL)) {
    1.87 +                    dbus.connection_flush(conn);
    1.88 +                    retval = SDL_TRUE;
    1.89 +                }
    1.90 +            }
    1.91 +
    1.92 +            dbus.message_unref(msg);
    1.93 +        }
    1.94 +    }
    1.95 +
    1.96 +    return retval;
    1.97 +}
    1.98 +
    1.99 +SDL_bool
   1.100 +SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...)
   1.101 +{
   1.102 +    SDL_bool retval;
   1.103 +    va_list ap;
   1.104 +    va_start(ap, method);
   1.105 +    retval = SDL_DBus_CallVoidMethodInternal(conn, node, path, interface, method, ap);
   1.106 +    va_end(ap);
   1.107 +    return retval;
   1.108 +}
   1.109 +
   1.110 +SDL_bool
   1.111 +SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *interface, const char *method, ...)
   1.112 +{
   1.113 +    SDL_bool retval;
   1.114 +    va_list ap;
   1.115 +    va_start(ap, method);
   1.116 +    retval = SDL_DBus_CallVoidMethodInternal(dbus.session_conn, node, path, interface, method, ap);
   1.117 +    va_end(ap);
   1.118 +    return retval;
   1.119 +}
   1.120 +
   1.121 +SDL_bool
   1.122 +SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result)
   1.123 +{
   1.124 +    SDL_bool retval = SDL_FALSE;
   1.125 +
   1.126 +    if (conn) {
   1.127 +        DBusMessage *msg = dbus.message_new_method_call(node, path, "org.freedesktop.DBus.Properties", "Get");
   1.128 +        if (msg) {
   1.129 +            if (dbus.message_append_args(msg, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) {
   1.130 +                DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
   1.131 +                if (reply) {
   1.132 +                    DBusMessageIter iter, sub;
   1.133 +                    dbus.message_iter_init(reply, &iter);
   1.134 +                    if (dbus.message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT) {
   1.135 +                        dbus.message_iter_recurse(&iter, &sub);
   1.136 +                        if (dbus.message_iter_get_arg_type(&sub) == expectedtype) {
   1.137 +                            dbus.message_iter_get_basic(&sub, result);
   1.138 +                            retval = SDL_TRUE;
   1.139 +                        }
   1.140 +                    }
   1.141 +                    dbus.message_unref(reply);
   1.142 +                }
   1.143 +            }
   1.144 +            dbus.message_unref(msg);
   1.145 +        }
   1.146 +    }
   1.147 +
   1.148 +    return retval;
   1.149 +}
   1.150 +
   1.151 +SDL_bool
   1.152 +SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result)
   1.153 +{
   1.154 +    return SDL_DBus_QueryPropertyOnConnection(dbus.session_conn, node, path, interface, property, expectedtype, result);
   1.155 +}
   1.156 +
   1.157 +
   1.158 +void
   1.159 +SDL_DBus_ScreensaverTickle(void)
   1.160 +{
   1.161 +    SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
   1.162  }
   1.163  
   1.164  SDL_bool
   1.165  SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
   1.166  {
   1.167 -    DBusConnection *conn = dbus.session_conn;
   1.168 -
   1.169 -    if (conn == NULL)
   1.170 -        return SDL_FALSE;
   1.171 -
   1.172 -    if (inhibit &&
   1.173 -        screensaver_cookie != 0)
   1.174 -        return SDL_TRUE;
   1.175 -    if (!inhibit &&
   1.176 -        screensaver_cookie == 0)
   1.177 -        return SDL_TRUE;
   1.178 -
   1.179 -    if (inhibit) {
   1.180 -        const char *app = "My SDL application";
   1.181 -        const char *reason = "Playing a game";
   1.182 -
   1.183 -        DBusMessage *msg = dbus.message_new_method_call("org.freedesktop.ScreenSaver",
   1.184 -                                                         "/org/freedesktop/ScreenSaver",
   1.185 -                                                         "org.freedesktop.ScreenSaver",
   1.186 -                                                         "Inhibit");
   1.187 -        if (msg != NULL) {
   1.188 -            dbus.message_append_args (msg,
   1.189 -                                      DBUS_TYPE_STRING, &app,
   1.190 -                                      DBUS_TYPE_STRING, &reason,
   1.191 -                                      DBUS_TYPE_INVALID);
   1.192 -        }
   1.193 -
   1.194 -        if (msg != NULL) {
   1.195 -            DBusMessage *reply;
   1.196 -
   1.197 -            reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
   1.198 -            if (reply) {
   1.199 -                if (!dbus.message_get_args(reply, NULL,
   1.200 -                                           DBUS_TYPE_UINT32, &screensaver_cookie,
   1.201 -                                           DBUS_TYPE_INVALID))
   1.202 -                    screensaver_cookie = 0;
   1.203 -                dbus.message_unref(reply);
   1.204 -            }
   1.205 -
   1.206 -            dbus.message_unref(msg);
   1.207 -        }
   1.208 -
   1.209 -        if (screensaver_cookie == 0) {
   1.210 -            return SDL_FALSE;
   1.211 -        }
   1.212 +    if ( (inhibit && (screensaver_cookie != 0)) || (!inhibit && (screensaver_cookie == 0)) ) {
   1.213          return SDL_TRUE;
   1.214      } else {
   1.215 -        DBusMessage *msg = dbus.message_new_method_call("org.freedesktop.ScreenSaver",
   1.216 -                                                        "/org/freedesktop/ScreenSaver",
   1.217 -                                                        "org.freedesktop.ScreenSaver",
   1.218 -                                                        "UnInhibit");
   1.219 -        dbus.message_append_args (msg,
   1.220 -                                  DBUS_TYPE_UINT32, &screensaver_cookie,
   1.221 -                                  DBUS_TYPE_INVALID);
   1.222 -        if (msg != NULL) {
   1.223 -            if (dbus.connection_send(conn, msg, NULL)) {
   1.224 -                dbus.connection_flush(conn);
   1.225 +        const char *node = "org.freedesktop.ScreenSaver";
   1.226 +        const char *path = "/org/freedesktop/ScreenSaver";
   1.227 +        const char *interface = "org.freedesktop.ScreenSaver";
   1.228 +
   1.229 +        if (inhibit) {
   1.230 +            const char *app = "My SDL application";
   1.231 +            const char *reason = "Playing a game";
   1.232 +            if (!SDL_DBus_CallMethod(node, path, interface, "Inhibit",
   1.233 +                    DBUS_TYPE_STRING, &app, DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID,
   1.234 +                    DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {
   1.235 +                return SDL_FALSE;
   1.236              }
   1.237 -            dbus.message_unref(msg);
   1.238 +            return (screensaver_cookie != 0) ? SDL_TRUE : SDL_FALSE;
   1.239 +        } else {
   1.240 +            if (!SDL_DBus_CallVoidMethod(node, path, interface, "UnInhibit", DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {
   1.241 +                return SDL_FALSE;
   1.242 +            }
   1.243 +            screensaver_cookie = 0;
   1.244          }
   1.245 +    }
   1.246  
   1.247 -        screensaver_cookie = 0;
   1.248 -        return SDL_TRUE;
   1.249 -    }
   1.250 +    return SDL_TRUE;
   1.251  }
   1.252  #endif
   1.253  
     2.1 --- a/src/core/linux/SDL_dbus.h	Sun May 28 07:08:10 2017 -0400
     2.2 +++ b/src/core/linux/SDL_dbus.h	Sun May 28 07:11:52 2017 -0400
     2.3 @@ -54,7 +54,9 @@
     2.4      dbus_bool_t (*message_is_signal)(DBusMessage *, const char *, const char *); 	
     2.5      DBusMessage *(*message_new_method_call)(const char *, const char *, const char *, const char *);
     2.6      dbus_bool_t (*message_append_args)(DBusMessage *, int, ...);
     2.7 +    dbus_bool_t (*message_append_args_valist)(DBusMessage *, int, va_list);
     2.8      dbus_bool_t (*message_get_args)(DBusMessage *, DBusError *, int, ...);
     2.9 +    dbus_bool_t (*message_get_args_valist)(DBusMessage *, DBusError *, int, va_list);
    2.10      dbus_bool_t (*message_iter_init)(DBusMessage *, DBusMessageIter *);
    2.11      dbus_bool_t (*message_iter_next)(DBusMessageIter *);
    2.12      void (*message_iter_get_basic)(DBusMessageIter *, void *);
    2.13 @@ -73,6 +75,17 @@
    2.14  extern void SDL_DBus_Init(void);
    2.15  extern void SDL_DBus_Quit(void);
    2.16  extern SDL_DBusContext * SDL_DBus_GetContext(void);
    2.17 +
    2.18 +/* These use the built-in Session connection. */
    2.19 +extern SDL_bool SDL_DBus_CallMethod(const char *node, const char *path, const char *interface, const char *method, ...);
    2.20 +extern SDL_bool SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *interface, const char *method, ...);
    2.21 +extern SDL_bool SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result);
    2.22 +
    2.23 +/* These use whatever connection you like. */
    2.24 +extern SDL_bool SDL_DBus_CallMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...);
    2.25 +extern SDL_bool SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...);
    2.26 +extern SDL_bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result);
    2.27 +
    2.28  extern void SDL_DBus_ScreensaverTickle(void);
    2.29  extern SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit);
    2.30  
     3.1 --- a/src/core/linux/SDL_fcitx.c	Sun May 28 07:08:10 2017 -0400
     3.2 +++ b/src/core/linux/SDL_fcitx.c	Sun May 28 07:11:52 2017 -0400
     3.3 @@ -231,33 +231,10 @@
     3.4      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
     3.5  }
     3.6  
     3.7 -static DBusMessage*
     3.8 -FcitxClientICNewMethod(FcitxClient *client,
     3.9 -        const char *method)
    3.10 +static void
    3.11 +FcitxClientICCallMethod(FcitxClient *client, const char *method)
    3.12  {
    3.13 -    SDL_DBusContext *dbus = client->dbus;
    3.14 -    return dbus->message_new_method_call(
    3.15 -            client->servicename,
    3.16 -            client->icname,
    3.17 -            FCITX_IC_DBUS_INTERFACE,
    3.18 -            method);
    3.19 -}
    3.20 -
    3.21 -static void
    3.22 -FcitxClientICCallMethod(FcitxClient *client,
    3.23 -        const char *method)
    3.24 -{
    3.25 -    SDL_DBusContext *dbus = client->dbus;
    3.26 -    DBusMessage *msg = FcitxClientICNewMethod(client, method);
    3.27 -
    3.28 -    if (msg == NULL)
    3.29 -        return ;
    3.30 -
    3.31 -    if (dbus->connection_send(dbus->session_conn, msg, NULL)) {
    3.32 -        dbus->connection_flush(dbus->session_conn);
    3.33 -    }
    3.34 -
    3.35 -    dbus->message_unref(msg);
    3.36 +    SDL_DBus_CallVoidMethod(client->servicename, client->icname, FCITX_IC_DBUS_INTERFACE, method, DBUS_TYPE_INVALID);
    3.37  }
    3.38  
    3.39  static void
    3.40 @@ -267,80 +244,35 @@
    3.41          const char *internal_editing)
    3.42  {
    3.43      FcitxClient *client = (FcitxClient *)data;
    3.44 -    SDL_DBusContext *dbus = client->dbus;
    3.45      Uint32 caps = CAPACITY_NONE;
    3.46  
    3.47 -    DBusMessage *msg = FcitxClientICNewMethod(client, "SetCapacity");
    3.48 -    if (msg == NULL)
    3.49 -        return ;
    3.50 -
    3.51      if (!(internal_editing && *internal_editing == '1')) {
    3.52          caps |= CAPACITY_PREEDIT;
    3.53      }
    3.54  
    3.55 -    dbus->message_append_args(msg,
    3.56 -            DBUS_TYPE_UINT32, &caps,
    3.57 -            DBUS_TYPE_INVALID);
    3.58 -    if (dbus->connection_send(dbus->session_conn, msg, NULL)) {
    3.59 -        dbus->connection_flush(dbus->session_conn);
    3.60 -    }
    3.61 -
    3.62 -    dbus->message_unref(msg);
    3.63 +    SDL_DBus_CallVoidMethod(client->servicename, client->icname, FCITX_IC_DBUS_INTERFACE, "SetCapacity", DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID);
    3.64  }
    3.65  
    3.66  static void
    3.67  FcitxClientCreateIC(FcitxClient *client)
    3.68  {
    3.69 -    char *appname = NULL;
    3.70 -    pid_t pid = 0;
    3.71 -    int id = 0;
    3.72 -    SDL_bool enable;
    3.73 -    Uint32 arg1, arg2, arg3, arg4;
    3.74 +    char *appname = GetAppName();
    3.75 +    pid_t pid = getpid();
    3.76 +    int id = -1;
    3.77 +    Uint32 enable, arg1, arg2, arg3, arg4;
    3.78  
    3.79 -    SDL_DBusContext *dbus = client->dbus;
    3.80 -    DBusMessage *reply = NULL;
    3.81 -    DBusMessage *msg = dbus->message_new_method_call(
    3.82 -            client->servicename,
    3.83 -            FCITX_IM_DBUS_PATH,
    3.84 -            FCITX_IM_DBUS_INTERFACE,
    3.85 -            "CreateICv3"
    3.86 -            );
    3.87 +    SDL_DBus_CallMethod(client->servicename, FCITX_IM_DBUS_PATH, FCITX_IM_DBUS_INTERFACE, "CreateICv3",
    3.88 +        DBUS_TYPE_STRING, &appname, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID,
    3.89 +        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);
    3.90  
    3.91 -    if (msg == NULL)
    3.92 -        return ;
    3.93 +    SDL_free(appname);
    3.94  
    3.95 -    appname = GetAppName();
    3.96 -    pid = getpid();
    3.97 -    dbus->message_append_args(msg,
    3.98 -            DBUS_TYPE_STRING, &appname,
    3.99 -            DBUS_TYPE_INT32, &pid,
   3.100 -            DBUS_TYPE_INVALID);
   3.101 +    if (id >= 0) {
   3.102 +        SDL_DBusContext *dbus = client->dbus;
   3.103  
   3.104 -    do {
   3.105 -        reply = dbus->connection_send_with_reply_and_block(
   3.106 -                dbus->session_conn,
   3.107 -                msg,
   3.108 -                DBUS_TIMEOUT,
   3.109 -                NULL);
   3.110 -
   3.111 -        if (!reply)
   3.112 -            break;
   3.113 -        if (!dbus->message_get_args(reply, NULL,
   3.114 -                DBUS_TYPE_INT32, &id,
   3.115 -                DBUS_TYPE_BOOLEAN, &enable,
   3.116 -                DBUS_TYPE_UINT32, &arg1,
   3.117 -                DBUS_TYPE_UINT32, &arg2,
   3.118 -                DBUS_TYPE_UINT32, &arg3,
   3.119 -                DBUS_TYPE_UINT32, &arg4,
   3.120 -                DBUS_TYPE_INVALID))
   3.121 -            break;
   3.122 -
   3.123 -        if (id < 0)
   3.124 -            break;
   3.125          client->id = id;
   3.126  
   3.127 -        SDL_snprintf(client->icname, IC_NAME_MAX,
   3.128 -                FCITX_IC_DBUS_PATH, client->id);
   3.129 +        SDL_snprintf(client->icname, IC_NAME_MAX, FCITX_IC_DBUS_PATH, client->id);
   3.130  
   3.131          dbus->bus_add_match(dbus->session_conn,
   3.132                  "type='signal', interface='org.fcitx.Fcitx.InputContext'",
   3.133 @@ -352,12 +284,6 @@
   3.134  
   3.135          SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, &Fcitx_SetCapabilities, client);
   3.136      }
   3.137 -    while (0);
   3.138 -
   3.139 -    if (reply)
   3.140 -        dbus->message_unref(reply);
   3.141 -    dbus->message_unref(msg);
   3.142 -    SDL_free(appname);
   3.143  }
   3.144  
   3.145  static Uint32
   3.146 @@ -422,47 +348,21 @@
   3.147  SDL_bool
   3.148  SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
   3.149  {
   3.150 -    DBusMessage *msg = NULL;
   3.151 -    DBusMessage *reply = NULL;
   3.152 -    SDL_DBusContext *dbus = fcitx_client.dbus;
   3.153 -
   3.154 -    Uint32 state = 0;
   3.155 -    SDL_bool handled = SDL_FALSE;
   3.156 +    Uint32 state = Fcitx_ModState();
   3.157 +    Uint32 handled = SDL_FALSE;
   3.158      int type = FCITX_PRESS_KEY;
   3.159      Uint32 event_time = 0;
   3.160  
   3.161 -    msg = FcitxClientICNewMethod(&fcitx_client, "ProcessKeyEvent");
   3.162 -    if (msg == NULL)
   3.163 -        return SDL_FALSE;
   3.164 -
   3.165 -    state = Fcitx_ModState();
   3.166 -    dbus->message_append_args(msg,
   3.167 -            DBUS_TYPE_UINT32, &keysym,
   3.168 -            DBUS_TYPE_UINT32, &keycode,
   3.169 -            DBUS_TYPE_UINT32, &state,
   3.170 -            DBUS_TYPE_INT32, &type,
   3.171 -            DBUS_TYPE_UINT32, &event_time,
   3.172 -            DBUS_TYPE_INVALID);
   3.173 -
   3.174 -    reply = dbus->connection_send_with_reply_and_block(dbus->session_conn,
   3.175 -            msg,
   3.176 -            -1,
   3.177 -            NULL);
   3.178 -
   3.179 -    if (reply) {
   3.180 -        dbus->message_get_args(reply,
   3.181 -                NULL,
   3.182 -                DBUS_TYPE_INT32, &handled,
   3.183 -                DBUS_TYPE_INVALID);
   3.184 -
   3.185 -        dbus->message_unref(reply);
   3.186 +    if (SDL_DBus_CallMethod(fcitx_client.servicename, fcitx_client.icname, FCITX_IC_DBUS_INTERFACE, "ProcessKeyEvent",
   3.187 +            DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INT32, &type, DBUS_TYPE_UINT32, &event_time, DBUS_TYPE_INVALID,
   3.188 +            DBUS_TYPE_INT32, &handled, DBUS_TYPE_INVALID)) {
   3.189 +        if (handled) {
   3.190 +            SDL_Fcitx_UpdateTextRect(NULL);
   3.191 +            return SDL_TRUE;
   3.192 +        }
   3.193      }
   3.194  
   3.195 -    if (handled) {
   3.196 -        SDL_Fcitx_UpdateTextRect(NULL);
   3.197 -    }
   3.198 -
   3.199 -    return handled;
   3.200 +    return SDL_FALSE;
   3.201  }
   3.202  
   3.203  void
   3.204 @@ -473,10 +373,6 @@
   3.205      int x = 0, y = 0;
   3.206      SDL_Rect *cursor = &fcitx_client.cursor_rect;
   3.207  
   3.208 -    SDL_DBusContext *dbus = fcitx_client.dbus;
   3.209 -    DBusMessage *msg = NULL;
   3.210 -    DBusConnection *conn;
   3.211 -
   3.212      if (rect) {
   3.213          SDL_memcpy(cursor, rect, sizeof(SDL_Rect));
   3.214      }
   3.215 @@ -516,22 +412,8 @@
   3.216      x += cursor->x;
   3.217      y += cursor->y;
   3.218  
   3.219 -    msg = FcitxClientICNewMethod(&fcitx_client, "SetCursorRect");
   3.220 -    if (msg == NULL)
   3.221 -        return ;
   3.222 -
   3.223 -    dbus->message_append_args(msg,
   3.224 -            DBUS_TYPE_INT32, &x,
   3.225 -            DBUS_TYPE_INT32, &y,
   3.226 -            DBUS_TYPE_INT32, &cursor->w,
   3.227 -            DBUS_TYPE_INT32, &cursor->h,
   3.228 -            DBUS_TYPE_INVALID);
   3.229 -
   3.230 -    conn = dbus->session_conn;
   3.231 -    if (dbus->connection_send(conn, msg, NULL))
   3.232 -        dbus->connection_flush(conn);
   3.233 -
   3.234 -    dbus->message_unref(msg);
   3.235 +    SDL_DBus_CallVoidMethod(fcitx_client.servicename, fcitx_client.icname, FCITX_IC_DBUS_INTERFACE, "SetCursorRect",
   3.236 +        DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_INT32, &cursor->w, DBUS_TYPE_INT32, &cursor->h, DBUS_TYPE_INVALID);
   3.237  }
   3.238  
   3.239  void
     4.1 --- a/src/core/linux/SDL_ibus.c	Sun May 28 07:08:10 2017 -0400
     4.2 +++ b/src/core/linux/SDL_ibus.c	Sun May 28 07:11:52 2017 -0400
     4.3 @@ -309,28 +309,13 @@
     4.4      SDL_DBusContext *dbus = SDL_DBus_GetContext();
     4.5      
     4.6      if (IBus_CheckConnection(dbus)) {
     4.7 +        Uint32 caps = IBUS_CAP_FOCUS;
     4.8 +        if (!(internal_editing && *internal_editing == '1')) {
     4.9 +            caps |= IBUS_CAP_PREEDIT_TEXT;
    4.10 +        }
    4.11  
    4.12 -        DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
    4.13 -                                                         input_ctx_path,
    4.14 -                                                         IBUS_INPUT_INTERFACE,
    4.15 -                                                         "SetCapabilities");
    4.16 -        if (msg) {
    4.17 -            Uint32 caps = IBUS_CAP_FOCUS;
    4.18 -            if (!(internal_editing && *internal_editing == '1')) {
    4.19 -                caps |= IBUS_CAP_PREEDIT_TEXT;
    4.20 -            }
    4.21 -            
    4.22 -            dbus->message_append_args(msg,
    4.23 -                                      DBUS_TYPE_UINT32, &caps,
    4.24 -                                      DBUS_TYPE_INVALID);
    4.25 -        }
    4.26 -        
    4.27 -        if (msg) {
    4.28 -            if (dbus->connection_send(ibus_conn, msg, NULL)) {
    4.29 -                dbus->connection_flush(ibus_conn);
    4.30 -            }
    4.31 -            dbus->message_unref(msg);
    4.32 -        }
    4.33 +        SDL_DBus_CallVoidMethod(IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "SetCapabilities",
    4.34 +                                DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID);
    4.35      }
    4.36  }
    4.37  
    4.38 @@ -338,9 +323,9 @@
    4.39  static SDL_bool
    4.40  IBus_SetupConnection(SDL_DBusContext *dbus, const char* addr)
    4.41  {
    4.42 +    const char *client_name = "SDL2_Application";
    4.43      const char *path = NULL;
    4.44      SDL_bool result = SDL_FALSE;
    4.45 -    DBusMessage *msg;
    4.46      DBusObjectPathVTable ibus_vtable;
    4.47  
    4.48      SDL_zero(ibus_vtable);
    4.49 @@ -361,34 +346,11 @@
    4.50      
    4.51      dbus->connection_flush(ibus_conn);
    4.52  
    4.53 -    msg = dbus->message_new_method_call(IBUS_SERVICE, IBUS_PATH, IBUS_INTERFACE, "CreateInputContext");
    4.54 -    if (msg) {
    4.55 -        const char *client_name = "SDL2_Application";
    4.56 -        dbus->message_append_args(msg,
    4.57 -                                  DBUS_TYPE_STRING, &client_name,
    4.58 -                                  DBUS_TYPE_INVALID);
    4.59 -    }
    4.60 -    
    4.61 -    if (msg) {
    4.62 -        DBusMessage *reply;
    4.63 -        
    4.64 -        reply = dbus->connection_send_with_reply_and_block(ibus_conn, msg, 1000, NULL);
    4.65 -        if (reply) {
    4.66 -            if (dbus->message_get_args(reply, NULL,
    4.67 -                                       DBUS_TYPE_OBJECT_PATH, &path,
    4.68 -                                       DBUS_TYPE_INVALID)) {
    4.69 -                if (input_ctx_path) {
    4.70 -                    SDL_free(input_ctx_path);
    4.71 -                }
    4.72 -                input_ctx_path = SDL_strdup(path);
    4.73 -                result = SDL_TRUE;                          
    4.74 -            }
    4.75 -            dbus->message_unref(reply);
    4.76 -        }
    4.77 -        dbus->message_unref(msg);
    4.78 -    }
    4.79 -
    4.80 -    if (result) {
    4.81 +    if (SDL_DBus_CallMethodOnConnection(ibus_conn, IBUS_SERVICE, IBUS_PATH, IBUS_INTERFACE, "CreateInputContext",
    4.82 +            DBUS_TYPE_STRING, &client_name, DBUS_TYPE_INVALID,
    4.83 +            DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) {
    4.84 +        SDL_free(input_ctx_path);
    4.85 +        input_ctx_path = SDL_strdup(path);
    4.86          SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, &IBus_SetCapabilities, NULL);
    4.87          
    4.88          dbus->bus_add_match(ibus_conn, "type='signal',interface='org.freedesktop.IBus.InputContext'", NULL);
    4.89 @@ -532,16 +494,7 @@
    4.90      SDL_DBusContext *dbus = SDL_DBus_GetContext();
    4.91      
    4.92      if (IBus_CheckConnection(dbus)) {
    4.93 -        DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
    4.94 -                                                         input_ctx_path,
    4.95 -                                                         IBUS_INPUT_INTERFACE,
    4.96 -                                                         method);
    4.97 -        if (msg) {
    4.98 -            if (dbus->connection_send(ibus_conn, msg, NULL)) {
    4.99 -                dbus->connection_flush(ibus_conn);
   4.100 -            }
   4.101 -            dbus->message_unref(msg);
   4.102 -        }
   4.103 +        SDL_DBus_CallVoidMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, method);
   4.104      }
   4.105  }
   4.106  
   4.107 @@ -561,43 +514,21 @@
   4.108  SDL_bool
   4.109  SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
   4.110  { 
   4.111 -    SDL_bool result = SDL_FALSE;   
   4.112 +    Uint32 result = 0;
   4.113      SDL_DBusContext *dbus = SDL_DBus_GetContext();
   4.114      
   4.115      if (IBus_CheckConnection(dbus)) {
   4.116 -        DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
   4.117 -                                                         input_ctx_path,
   4.118 -                                                         IBUS_INPUT_INTERFACE,
   4.119 -                                                         "ProcessKeyEvent");
   4.120 -        if (msg) {
   4.121 -            Uint32 mods = IBus_ModState();
   4.122 -            dbus->message_append_args(msg,
   4.123 -                                      DBUS_TYPE_UINT32, &keysym,
   4.124 -                                      DBUS_TYPE_UINT32, &keycode,
   4.125 -                                      DBUS_TYPE_UINT32, &mods,
   4.126 -                                      DBUS_TYPE_INVALID);
   4.127 +        Uint32 mods = IBus_ModState();
   4.128 +        if (!SDL_DBus_CallMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "ProcessKeyEvent",
   4.129 +                DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &mods, DBUS_TYPE_INVALID,
   4.130 +                DBUS_TYPE_BOOLEAN, &result, DBUS_TYPE_INVALID)) {
   4.131 +            result = 0;
   4.132          }
   4.133 -        
   4.134 -        if (msg) {
   4.135 -            DBusMessage *reply;
   4.136 -            
   4.137 -            reply = dbus->connection_send_with_reply_and_block(ibus_conn, msg, 300, NULL);
   4.138 -            if (reply) {
   4.139 -                if (!dbus->message_get_args(reply, NULL,
   4.140 -                                           DBUS_TYPE_BOOLEAN, &result,
   4.141 -                                           DBUS_TYPE_INVALID)) {
   4.142 -                    result = SDL_FALSE;                         
   4.143 -                }
   4.144 -                dbus->message_unref(reply);
   4.145 -            }
   4.146 -            dbus->message_unref(msg);
   4.147 -        }
   4.148 -        
   4.149      }
   4.150      
   4.151      SDL_IBus_UpdateTextRect(NULL);
   4.152  
   4.153 -    return result;
   4.154 +    return result ? SDL_TRUE : SDL_FALSE;
   4.155  }
   4.156  
   4.157  void
   4.158 @@ -643,25 +574,8 @@
   4.159      dbus = SDL_DBus_GetContext();
   4.160      
   4.161      if (IBus_CheckConnection(dbus)) {
   4.162 -        DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
   4.163 -                                                         input_ctx_path,
   4.164 -                                                         IBUS_INPUT_INTERFACE,
   4.165 -                                                         "SetCursorLocation");
   4.166 -        if (msg) {
   4.167 -            dbus->message_append_args(msg,
   4.168 -                                      DBUS_TYPE_INT32, &x,
   4.169 -                                      DBUS_TYPE_INT32, &y,
   4.170 -                                      DBUS_TYPE_INT32, &ibus_cursor_rect.w,
   4.171 -                                      DBUS_TYPE_INT32, &ibus_cursor_rect.h,
   4.172 -                                      DBUS_TYPE_INVALID);
   4.173 -        }
   4.174 -        
   4.175 -        if (msg) {
   4.176 -            if (dbus->connection_send(ibus_conn, msg, NULL)) {
   4.177 -                dbus->connection_flush(ibus_conn);
   4.178 -            }
   4.179 -            dbus->message_unref(msg);
   4.180 -        }
   4.181 +        SDL_DBus_CallVoidMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "SetCursorLocation",
   4.182 +                DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_INT32, &ibus_cursor_rect.w, DBUS_TYPE_INT32, &ibus_cursor_rect.h, DBUS_TYPE_INVALID);
   4.183      }
   4.184  }
   4.185  
     5.1 --- a/src/video/x11/SDL_x11video.c	Sun May 28 07:08:10 2017 -0400
     5.2 +++ b/src/video/x11/SDL_x11video.c	Sun May 28 07:11:52 2017 -0400
     5.3 @@ -461,6 +461,8 @@
     5.4      X11_QuitMouse(_this);
     5.5      X11_QuitTouch(_this);
     5.6  
     5.7 +/* !!! FIXME: other subsystems use D-Bus, so we shouldn't quit it here;
     5.8 +       have SDL.c do this at a higher level, or add refcounting. */
     5.9  #if SDL_USE_LIBDBUS
    5.10      SDL_DBus_Quit();
    5.11  #endif