linux: Simplify D-Bus interface, remove lots of boilerplate.
diff --git a/src/core/linux/SDL_dbus.c b/src/core/linux/SDL_dbus.c
index e6676f7..c139412 100644
--- a/src/core/linux/SDL_dbus.c
+++ b/src/core/linux/SDL_dbus.c
@@ -56,7 +56,9 @@
     SDL_DBUS_SYM(message_is_signal);
     SDL_DBUS_SYM(message_new_method_call);
     SDL_DBUS_SYM(message_append_args);
+    SDL_DBUS_SYM(message_append_args_valist);
     SDL_DBUS_SYM(message_get_args);
+    SDL_DBUS_SYM(message_get_args_valist);
     SDL_DBUS_SYM(message_iter_init);
     SDL_DBUS_SYM(message_iter_next);
     SDL_DBUS_SYM(message_iter_get_basic);
@@ -157,91 +159,170 @@
     }
 }
 
-void
-SDL_DBus_ScreensaverTickle(void)
+static SDL_bool
+SDL_DBus_CallMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap)
 {
-    DBusConnection *conn = dbus.session_conn;
-    if (conn != NULL) {
-        DBusMessage *msg = dbus.message_new_method_call("org.gnome.ScreenSaver",
-                                                        "/org/gnome/ScreenSaver",
-                                                        "org.gnome.ScreenSaver",
-                                                        "SimulateUserActivity");
-        if (msg != NULL) {
-            if (dbus.connection_send(conn, msg, NULL)) {
-                dbus.connection_flush(conn);
+    SDL_bool retval = SDL_FALSE;
+
+    if (conn) {
+        DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method);
+        if (msg) {
+            int firstarg = va_arg(ap, int);
+            if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) {
+                DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
+                if (reply) {
+                    firstarg = va_arg(ap, int);
+                    if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_get_args_valist(reply, NULL, firstarg, ap)) {
+                        retval = SDL_TRUE;
+                    }
+                    dbus.message_unref(reply);
+                }
             }
             dbus.message_unref(msg);
         }
     }
+
+    return retval;
+}
+
+SDL_bool
+SDL_DBus_CallMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...)
+{
+    SDL_bool retval;
+    va_list ap;
+    va_start(ap, method);
+    retval = SDL_DBus_CallMethodInternal(conn, node, path, interface, method, ap);
+    va_end(ap);
+    return retval;
+}
+
+SDL_bool
+SDL_DBus_CallMethod(const char *node, const char *path, const char *interface, const char *method, ...)
+{
+    SDL_bool retval;
+    va_list ap;
+    va_start(ap, method);
+    retval = SDL_DBus_CallMethodInternal(dbus.session_conn, node, path, interface, method, ap);
+    va_end(ap);
+    return retval;
+}
+
+static SDL_bool
+SDL_DBus_CallVoidMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap)
+{
+    SDL_bool retval = SDL_FALSE;
+
+    if (conn) {
+        DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method);
+        if (msg) {
+            int firstarg = va_arg(ap, int);
+            if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) {
+                if (dbus.connection_send(conn, msg, NULL)) {
+                    dbus.connection_flush(conn);
+                    retval = SDL_TRUE;
+                }
+            }
+
+            dbus.message_unref(msg);
+        }
+    }
+
+    return retval;
+}
+
+SDL_bool
+SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...)
+{
+    SDL_bool retval;
+    va_list ap;
+    va_start(ap, method);
+    retval = SDL_DBus_CallVoidMethodInternal(conn, node, path, interface, method, ap);
+    va_end(ap);
+    return retval;
+}
+
+SDL_bool
+SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *interface, const char *method, ...)
+{
+    SDL_bool retval;
+    va_list ap;
+    va_start(ap, method);
+    retval = SDL_DBus_CallVoidMethodInternal(dbus.session_conn, node, path, interface, method, ap);
+    va_end(ap);
+    return retval;
+}
+
+SDL_bool
+SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result)
+{
+    SDL_bool retval = SDL_FALSE;
+
+    if (conn) {
+        DBusMessage *msg = dbus.message_new_method_call(node, path, "org.freedesktop.DBus.Properties", "Get");
+        if (msg) {
+            if (dbus.message_append_args(msg, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) {
+                DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
+                if (reply) {
+                    DBusMessageIter iter, sub;
+                    dbus.message_iter_init(reply, &iter);
+                    if (dbus.message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT) {
+                        dbus.message_iter_recurse(&iter, &sub);
+                        if (dbus.message_iter_get_arg_type(&sub) == expectedtype) {
+                            dbus.message_iter_get_basic(&sub, result);
+                            retval = SDL_TRUE;
+                        }
+                    }
+                    dbus.message_unref(reply);
+                }
+            }
+            dbus.message_unref(msg);
+        }
+    }
+
+    return retval;
+}
+
+SDL_bool
+SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result)
+{
+    return SDL_DBus_QueryPropertyOnConnection(dbus.session_conn, node, path, interface, property, expectedtype, result);
+}
+
+
+void
+SDL_DBus_ScreensaverTickle(void)
+{
+    SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
 }
 
 SDL_bool
 SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
 {
-    DBusConnection *conn = dbus.session_conn;
-
-    if (conn == NULL)
-        return SDL_FALSE;
-
-    if (inhibit &&
-        screensaver_cookie != 0)
-        return SDL_TRUE;
-    if (!inhibit &&
-        screensaver_cookie == 0)
-        return SDL_TRUE;
-
-    if (inhibit) {
-        const char *app = "My SDL application";
-        const char *reason = "Playing a game";
-
-        DBusMessage *msg = dbus.message_new_method_call("org.freedesktop.ScreenSaver",
-                                                         "/org/freedesktop/ScreenSaver",
-                                                         "org.freedesktop.ScreenSaver",
-                                                         "Inhibit");
-        if (msg != NULL) {
-            dbus.message_append_args (msg,
-                                      DBUS_TYPE_STRING, &app,
-                                      DBUS_TYPE_STRING, &reason,
-                                      DBUS_TYPE_INVALID);
-        }
-
-        if (msg != NULL) {
-            DBusMessage *reply;
-
-            reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
-            if (reply) {
-                if (!dbus.message_get_args(reply, NULL,
-                                           DBUS_TYPE_UINT32, &screensaver_cookie,
-                                           DBUS_TYPE_INVALID))
-                    screensaver_cookie = 0;
-                dbus.message_unref(reply);
-            }
-
-            dbus.message_unref(msg);
-        }
-
-        if (screensaver_cookie == 0) {
-            return SDL_FALSE;
-        }
+    if ( (inhibit && (screensaver_cookie != 0)) || (!inhibit && (screensaver_cookie == 0)) ) {
         return SDL_TRUE;
     } else {
-        DBusMessage *msg = dbus.message_new_method_call("org.freedesktop.ScreenSaver",
-                                                        "/org/freedesktop/ScreenSaver",
-                                                        "org.freedesktop.ScreenSaver",
-                                                        "UnInhibit");
-        dbus.message_append_args (msg,
-                                  DBUS_TYPE_UINT32, &screensaver_cookie,
-                                  DBUS_TYPE_INVALID);
-        if (msg != NULL) {
-            if (dbus.connection_send(conn, msg, NULL)) {
-                dbus.connection_flush(conn);
-            }
-            dbus.message_unref(msg);
-        }
+        const char *node = "org.freedesktop.ScreenSaver";
+        const char *path = "/org/freedesktop/ScreenSaver";
+        const char *interface = "org.freedesktop.ScreenSaver";
 
-        screensaver_cookie = 0;
-        return SDL_TRUE;
+        if (inhibit) {
+            const char *app = "My SDL application";
+            const char *reason = "Playing a game";
+            if (!SDL_DBus_CallMethod(node, path, interface, "Inhibit",
+                    DBUS_TYPE_STRING, &app, DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID,
+                    DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {
+                return SDL_FALSE;
+            }
+            return (screensaver_cookie != 0) ? SDL_TRUE : SDL_FALSE;
+        } else {
+            if (!SDL_DBus_CallVoidMethod(node, path, interface, "UnInhibit", DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {
+                return SDL_FALSE;
+            }
+            screensaver_cookie = 0;
+        }
     }
+
+    return SDL_TRUE;
 }
 #endif
 
diff --git a/src/core/linux/SDL_dbus.h b/src/core/linux/SDL_dbus.h
index ee568e8..b5fbaac 100644
--- a/src/core/linux/SDL_dbus.h
+++ b/src/core/linux/SDL_dbus.h
@@ -54,7 +54,9 @@
     dbus_bool_t (*message_is_signal)(DBusMessage *, const char *, const char *); 	
     DBusMessage *(*message_new_method_call)(const char *, const char *, const char *, const char *);
     dbus_bool_t (*message_append_args)(DBusMessage *, int, ...);
+    dbus_bool_t (*message_append_args_valist)(DBusMessage *, int, va_list);
     dbus_bool_t (*message_get_args)(DBusMessage *, DBusError *, int, ...);
+    dbus_bool_t (*message_get_args_valist)(DBusMessage *, DBusError *, int, va_list);
     dbus_bool_t (*message_iter_init)(DBusMessage *, DBusMessageIter *);
     dbus_bool_t (*message_iter_next)(DBusMessageIter *);
     void (*message_iter_get_basic)(DBusMessageIter *, void *);
@@ -73,6 +75,17 @@
 extern void SDL_DBus_Init(void);
 extern void SDL_DBus_Quit(void);
 extern SDL_DBusContext * SDL_DBus_GetContext(void);
+
+/* These use the built-in Session connection. */
+extern SDL_bool SDL_DBus_CallMethod(const char *node, const char *path, const char *interface, const char *method, ...);
+extern SDL_bool SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *interface, const char *method, ...);
+extern SDL_bool SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result);
+
+/* These use whatever connection you like. */
+extern SDL_bool SDL_DBus_CallMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...);
+extern SDL_bool SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...);
+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);
+
 extern void SDL_DBus_ScreensaverTickle(void);
 extern SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit);
 
diff --git a/src/core/linux/SDL_fcitx.c b/src/core/linux/SDL_fcitx.c
index eaf95cd..7a04615 100644
--- a/src/core/linux/SDL_fcitx.c
+++ b/src/core/linux/SDL_fcitx.c
@@ -231,33 +231,10 @@
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
-static DBusMessage*
-FcitxClientICNewMethod(FcitxClient *client,
-        const char *method)
-{
-    SDL_DBusContext *dbus = client->dbus;
-    return dbus->message_new_method_call(
-            client->servicename,
-            client->icname,
-            FCITX_IC_DBUS_INTERFACE,
-            method);
-}
-
 static void
-FcitxClientICCallMethod(FcitxClient *client,
-        const char *method)
+FcitxClientICCallMethod(FcitxClient *client, const char *method)
 {
-    SDL_DBusContext *dbus = client->dbus;
-    DBusMessage *msg = FcitxClientICNewMethod(client, method);
-
-    if (msg == NULL)
-        return ;
-
-    if (dbus->connection_send(dbus->session_conn, msg, NULL)) {
-        dbus->connection_flush(dbus->session_conn);
-    }
-
-    dbus->message_unref(msg);
+    SDL_DBus_CallVoidMethod(client->servicename, client->icname, FCITX_IC_DBUS_INTERFACE, method, DBUS_TYPE_INVALID);
 }
 
 static void
@@ -267,80 +244,35 @@
         const char *internal_editing)
 {
     FcitxClient *client = (FcitxClient *)data;
-    SDL_DBusContext *dbus = client->dbus;
     Uint32 caps = CAPACITY_NONE;
 
-    DBusMessage *msg = FcitxClientICNewMethod(client, "SetCapacity");
-    if (msg == NULL)
-        return ;
-
     if (!(internal_editing && *internal_editing == '1')) {
         caps |= CAPACITY_PREEDIT;
     }
 
-    dbus->message_append_args(msg,
-            DBUS_TYPE_UINT32, &caps,
-            DBUS_TYPE_INVALID);
-    if (dbus->connection_send(dbus->session_conn, msg, NULL)) {
-        dbus->connection_flush(dbus->session_conn);
-    }
-
-    dbus->message_unref(msg);
+    SDL_DBus_CallVoidMethod(client->servicename, client->icname, FCITX_IC_DBUS_INTERFACE, "SetCapacity", DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID);
 }
 
 static void
 FcitxClientCreateIC(FcitxClient *client)
 {
-    char *appname = NULL;
-    pid_t pid = 0;
-    int id = 0;
-    SDL_bool enable;
-    Uint32 arg1, arg2, arg3, arg4;
+    char *appname = GetAppName();
+    pid_t pid = getpid();
+    int id = -1;
+    Uint32 enable, arg1, arg2, arg3, arg4;
 
-    SDL_DBusContext *dbus = client->dbus;
-    DBusMessage *reply = NULL;
-    DBusMessage *msg = dbus->message_new_method_call(
-            client->servicename,
-            FCITX_IM_DBUS_PATH,
-            FCITX_IM_DBUS_INTERFACE,
-            "CreateICv3"
-            );
+    SDL_DBus_CallMethod(client->servicename, FCITX_IM_DBUS_PATH, FCITX_IM_DBUS_INTERFACE, "CreateICv3",
+        DBUS_TYPE_STRING, &appname, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID,
+        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);
 
-    if (msg == NULL)
-        return ;
+    SDL_free(appname);
 
-    appname = GetAppName();
-    pid = getpid();
-    dbus->message_append_args(msg,
-            DBUS_TYPE_STRING, &appname,
-            DBUS_TYPE_INT32, &pid,
-            DBUS_TYPE_INVALID);
+    if (id >= 0) {
+        SDL_DBusContext *dbus = client->dbus;
 
-    do {
-        reply = dbus->connection_send_with_reply_and_block(
-                dbus->session_conn,
-                msg,
-                DBUS_TIMEOUT,
-                NULL);
-
-        if (!reply)
-            break;
-        if (!dbus->message_get_args(reply, NULL,
-                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))
-            break;
-
-        if (id < 0)
-            break;
         client->id = id;
 
-        SDL_snprintf(client->icname, IC_NAME_MAX,
-                FCITX_IC_DBUS_PATH, client->id);
+        SDL_snprintf(client->icname, IC_NAME_MAX, FCITX_IC_DBUS_PATH, client->id);
 
         dbus->bus_add_match(dbus->session_conn,
                 "type='signal', interface='org.fcitx.Fcitx.InputContext'",
@@ -352,12 +284,6 @@
 
         SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, &Fcitx_SetCapabilities, client);
     }
-    while (0);
-
-    if (reply)
-        dbus->message_unref(reply);
-    dbus->message_unref(msg);
-    SDL_free(appname);
 }
 
 static Uint32
@@ -422,47 +348,21 @@
 SDL_bool
 SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
 {
-    DBusMessage *msg = NULL;
-    DBusMessage *reply = NULL;
-    SDL_DBusContext *dbus = fcitx_client.dbus;
-
-    Uint32 state = 0;
-    SDL_bool handled = SDL_FALSE;
+    Uint32 state = Fcitx_ModState();
+    Uint32 handled = SDL_FALSE;
     int type = FCITX_PRESS_KEY;
     Uint32 event_time = 0;
 
-    msg = FcitxClientICNewMethod(&fcitx_client, "ProcessKeyEvent");
-    if (msg == NULL)
-        return SDL_FALSE;
-
-    state = Fcitx_ModState();
-    dbus->message_append_args(msg,
-            DBUS_TYPE_UINT32, &keysym,
-            DBUS_TYPE_UINT32, &keycode,
-            DBUS_TYPE_UINT32, &state,
-            DBUS_TYPE_INT32, &type,
-            DBUS_TYPE_UINT32, &event_time,
-            DBUS_TYPE_INVALID);
-
-    reply = dbus->connection_send_with_reply_and_block(dbus->session_conn,
-            msg,
-            -1,
-            NULL);
-
-    if (reply) {
-        dbus->message_get_args(reply,
-                NULL,
-                DBUS_TYPE_INT32, &handled,
-                DBUS_TYPE_INVALID);
-
-        dbus->message_unref(reply);
+    if (SDL_DBus_CallMethod(fcitx_client.servicename, fcitx_client.icname, FCITX_IC_DBUS_INTERFACE, "ProcessKeyEvent",
+            DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INT32, &type, DBUS_TYPE_UINT32, &event_time, DBUS_TYPE_INVALID,
+            DBUS_TYPE_INT32, &handled, DBUS_TYPE_INVALID)) {
+        if (handled) {
+            SDL_Fcitx_UpdateTextRect(NULL);
+            return SDL_TRUE;
+        }
     }
 
-    if (handled) {
-        SDL_Fcitx_UpdateTextRect(NULL);
-    }
-
-    return handled;
+    return SDL_FALSE;
 }
 
 void
@@ -473,10 +373,6 @@
     int x = 0, y = 0;
     SDL_Rect *cursor = &fcitx_client.cursor_rect;
 
-    SDL_DBusContext *dbus = fcitx_client.dbus;
-    DBusMessage *msg = NULL;
-    DBusConnection *conn;
-
     if (rect) {
         SDL_memcpy(cursor, rect, sizeof(SDL_Rect));
     }
@@ -516,22 +412,8 @@
     x += cursor->x;
     y += cursor->y;
 
-    msg = FcitxClientICNewMethod(&fcitx_client, "SetCursorRect");
-    if (msg == NULL)
-        return ;
-
-    dbus->message_append_args(msg,
-            DBUS_TYPE_INT32, &x,
-            DBUS_TYPE_INT32, &y,
-            DBUS_TYPE_INT32, &cursor->w,
-            DBUS_TYPE_INT32, &cursor->h,
-            DBUS_TYPE_INVALID);
-
-    conn = dbus->session_conn;
-    if (dbus->connection_send(conn, msg, NULL))
-        dbus->connection_flush(conn);
-
-    dbus->message_unref(msg);
+    SDL_DBus_CallVoidMethod(fcitx_client.servicename, fcitx_client.icname, FCITX_IC_DBUS_INTERFACE, "SetCursorRect",
+        DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_INT32, &cursor->w, DBUS_TYPE_INT32, &cursor->h, DBUS_TYPE_INVALID);
 }
 
 void
diff --git a/src/core/linux/SDL_ibus.c b/src/core/linux/SDL_ibus.c
index 5def7e6..919c169 100644
--- a/src/core/linux/SDL_ibus.c
+++ b/src/core/linux/SDL_ibus.c
@@ -309,28 +309,13 @@
     SDL_DBusContext *dbus = SDL_DBus_GetContext();
     
     if (IBus_CheckConnection(dbus)) {
+        Uint32 caps = IBUS_CAP_FOCUS;
+        if (!(internal_editing && *internal_editing == '1')) {
+            caps |= IBUS_CAP_PREEDIT_TEXT;
+        }
 
-        DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
-                                                         input_ctx_path,
-                                                         IBUS_INPUT_INTERFACE,
-                                                         "SetCapabilities");
-        if (msg) {
-            Uint32 caps = IBUS_CAP_FOCUS;
-            if (!(internal_editing && *internal_editing == '1')) {
-                caps |= IBUS_CAP_PREEDIT_TEXT;
-            }
-            
-            dbus->message_append_args(msg,
-                                      DBUS_TYPE_UINT32, &caps,
-                                      DBUS_TYPE_INVALID);
-        }
-        
-        if (msg) {
-            if (dbus->connection_send(ibus_conn, msg, NULL)) {
-                dbus->connection_flush(ibus_conn);
-            }
-            dbus->message_unref(msg);
-        }
+        SDL_DBus_CallVoidMethod(IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "SetCapabilities",
+                                DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID);
     }
 }
 
@@ -338,9 +323,9 @@
 static SDL_bool
 IBus_SetupConnection(SDL_DBusContext *dbus, const char* addr)
 {
+    const char *client_name = "SDL2_Application";
     const char *path = NULL;
     SDL_bool result = SDL_FALSE;
-    DBusMessage *msg;
     DBusObjectPathVTable ibus_vtable;
 
     SDL_zero(ibus_vtable);
@@ -361,34 +346,11 @@
     
     dbus->connection_flush(ibus_conn);
 
-    msg = dbus->message_new_method_call(IBUS_SERVICE, IBUS_PATH, IBUS_INTERFACE, "CreateInputContext");
-    if (msg) {
-        const char *client_name = "SDL2_Application";
-        dbus->message_append_args(msg,
-                                  DBUS_TYPE_STRING, &client_name,
-                                  DBUS_TYPE_INVALID);
-    }
-    
-    if (msg) {
-        DBusMessage *reply;
-        
-        reply = dbus->connection_send_with_reply_and_block(ibus_conn, msg, 1000, NULL);
-        if (reply) {
-            if (dbus->message_get_args(reply, NULL,
-                                       DBUS_TYPE_OBJECT_PATH, &path,
-                                       DBUS_TYPE_INVALID)) {
-                if (input_ctx_path) {
-                    SDL_free(input_ctx_path);
-                }
-                input_ctx_path = SDL_strdup(path);
-                result = SDL_TRUE;                          
-            }
-            dbus->message_unref(reply);
-        }
-        dbus->message_unref(msg);
-    }
-
-    if (result) {
+    if (SDL_DBus_CallMethodOnConnection(ibus_conn, IBUS_SERVICE, IBUS_PATH, IBUS_INTERFACE, "CreateInputContext",
+            DBUS_TYPE_STRING, &client_name, DBUS_TYPE_INVALID,
+            DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) {
+        SDL_free(input_ctx_path);
+        input_ctx_path = SDL_strdup(path);
         SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, &IBus_SetCapabilities, NULL);
         
         dbus->bus_add_match(ibus_conn, "type='signal',interface='org.freedesktop.IBus.InputContext'", NULL);
@@ -532,16 +494,7 @@
     SDL_DBusContext *dbus = SDL_DBus_GetContext();
     
     if (IBus_CheckConnection(dbus)) {
-        DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
-                                                         input_ctx_path,
-                                                         IBUS_INPUT_INTERFACE,
-                                                         method);
-        if (msg) {
-            if (dbus->connection_send(ibus_conn, msg, NULL)) {
-                dbus->connection_flush(ibus_conn);
-            }
-            dbus->message_unref(msg);
-        }
+        SDL_DBus_CallVoidMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, method);
     }
 }
 
@@ -561,43 +514,21 @@
 SDL_bool
 SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
 { 
-    SDL_bool result = SDL_FALSE;   
+    Uint32 result = 0;
     SDL_DBusContext *dbus = SDL_DBus_GetContext();
     
     if (IBus_CheckConnection(dbus)) {
-        DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
-                                                         input_ctx_path,
-                                                         IBUS_INPUT_INTERFACE,
-                                                         "ProcessKeyEvent");
-        if (msg) {
-            Uint32 mods = IBus_ModState();
-            dbus->message_append_args(msg,
-                                      DBUS_TYPE_UINT32, &keysym,
-                                      DBUS_TYPE_UINT32, &keycode,
-                                      DBUS_TYPE_UINT32, &mods,
-                                      DBUS_TYPE_INVALID);
+        Uint32 mods = IBus_ModState();
+        if (!SDL_DBus_CallMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "ProcessKeyEvent",
+                DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &mods, DBUS_TYPE_INVALID,
+                DBUS_TYPE_BOOLEAN, &result, DBUS_TYPE_INVALID)) {
+            result = 0;
         }
-        
-        if (msg) {
-            DBusMessage *reply;
-            
-            reply = dbus->connection_send_with_reply_and_block(ibus_conn, msg, 300, NULL);
-            if (reply) {
-                if (!dbus->message_get_args(reply, NULL,
-                                           DBUS_TYPE_BOOLEAN, &result,
-                                           DBUS_TYPE_INVALID)) {
-                    result = SDL_FALSE;                         
-                }
-                dbus->message_unref(reply);
-            }
-            dbus->message_unref(msg);
-        }
-        
     }
     
     SDL_IBus_UpdateTextRect(NULL);
 
-    return result;
+    return result ? SDL_TRUE : SDL_FALSE;
 }
 
 void
@@ -643,25 +574,8 @@
     dbus = SDL_DBus_GetContext();
     
     if (IBus_CheckConnection(dbus)) {
-        DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
-                                                         input_ctx_path,
-                                                         IBUS_INPUT_INTERFACE,
-                                                         "SetCursorLocation");
-        if (msg) {
-            dbus->message_append_args(msg,
-                                      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);
-        }
-        
-        if (msg) {
-            if (dbus->connection_send(ibus_conn, msg, NULL)) {
-                dbus->connection_flush(ibus_conn);
-            }
-            dbus->message_unref(msg);
-        }
+        SDL_DBus_CallVoidMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "SetCursorLocation",
+                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);
     }
 }
 
diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c
index 7ced9aa..d45e907 100644
--- a/src/video/x11/SDL_x11video.c
+++ b/src/video/x11/SDL_x11video.c
@@ -461,6 +461,8 @@
     X11_QuitMouse(_this);
     X11_QuitTouch(_this);
 
+/* !!! FIXME: other subsystems use D-Bus, so we shouldn't quit it here;
+       have SDL.c do this at a higher level, or add refcounting. */
 #if SDL_USE_LIBDBUS
     SDL_DBus_Quit();
 #endif