From eaf31da0d180d5c9f53a7c99c5fc19b4fd1678d8 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Sun, 16 Aug 2026 16:20:10 +0900 Subject: [PATCH] ibus: one reply path, no ceremony around calls that cannot fail Six handlers built method returns by hand and only two of them checked for a nil message; reply() builds them all and dies on OOM like the rest of the daemon. DBusError objects were initialised and freed but never read: libdbus accepts nil. Properties.Get always errored, so it is one line in onmsg; the introspection XML served nobody (libibus never asks) and had to be kept in sync by hand. Ibushinthidden was not an IBus hint, so that term of hidden() never fired. writeaddr uses the syscalls directly and the address file's dev/ino is the ownership proof; buildaddrpath makes the directory in place. An empty UpdatePreeditText goes out only to the context that shows a preedit. --- ibus.c | 489 +++++++++++++++++----------------------------- tests/ibus_test.c | 1 - 2 files changed, 174 insertions(+), 316 deletions(-) diff --git a/ibus.c b/ibus.c index e906480..5335759 100644 --- a/ibus.c +++ b/ibus.c @@ -22,7 +22,6 @@ enum Ibuscappreedit = 1<<0, Ibuspurposepassword = 8, Ibuspurposepin = 9, - Ibushinthidden = 1<<12, Ibusattrunderline = 1, Ibusunderlinesingle = 1, Ibuspreeditclear = 0, @@ -50,27 +49,24 @@ static Ictx contexts[Maxcontexts]; static char addrfile[512]; static dev_t addrdev; static ino_t addrino; -static int addrowned; static int icctr; static int busctr; static Channel *replyc; static const char ibusowner[] = ":1.0"; static Ictx *preowner; -static DBusHandlerResult onmsg(DBusConnection*, DBusMessage*, void*); -static DBusHandlerResult handleerror(DBusConnection*, DBusMessage*, - const char*, const char*); -static void checkpreowner(void); - +/* Removes the address file only while it is still the one we wrote. */ static void unlinkaddr(void) { struct stat st; - if(addrowned && lstat(addrfile, &st) == 0 && + if(addrfile[0] != '\0' && lstat(addrfile, &st) == 0 && st.st_dev == addrdev && st.st_ino == addrino) unlink(addrfile); - addrowned = 0; + addrfile[0] = '\0'; + addrdev = 0; + addrino = 0; } static void @@ -136,12 +132,12 @@ xdisplay(char *host, int hsz, char *num, int nsz) num[n] = '\0'; } +/* The IBus address file lives where libibus looks: config/ibus/bus/. */ static int buildaddrpath(char *buf, int sz) { - char mid[64], host[64], num[8], *cfg, *home, *explicit; - struct stat st; - char dir[512]; + char mid[64], host[64], num[8], dir[512]; + char *cfg, *home, *explicit, *p; int n; explicit = getenv("IBUS_ADDRESS_FILE"); @@ -164,69 +160,45 @@ buildaddrpath(char *buf, int sz) } if(n < 0 || n >= (int)sizeof dir) return -1; - if(stat(dir, &st) < 0){ - char tmp[512]; - char *p; - strncpy(tmp, dir, sizeof(tmp)); - tmp[sizeof(tmp)-1] = '\0'; - for(p = tmp+1; *p; p++) - if(*p == '/'){ - *p = '\0'; - mkdir(tmp, 0700); - *p = '/'; - } - mkdir(tmp, 0700); - } + for(p = dir+1; *p; p++) + if(*p == '/'){ + *p = '\0'; + mkdir(dir, 0700); + *p = '/'; + } + mkdir(dir, 0700); n = snprintf(buf, sz, "%s/%s-%s-%s", dir, mid, host, num); return n < 0 || n >= sz ? -1 : 0; } +/* Publishes the address atomically and remembers the file's identity. */ static int writeaddr(char *path, char *addr) { - char tmp[576]; - FILE *fp; + char tmp[576], text[256]; struct stat st; int fd, n, ok; n = snprintf(tmp, sizeof tmp, "%s.tmp.XXXXXX", path); if(n < 0 || n >= (int)sizeof tmp) return -1; + n = snprintf(text, sizeof text, "IBUS_ADDRESS=%s\nIBUS_DAEMON_PID=%d\n", + addr, (int)getpid()); + if(n < 0 || n >= (int)sizeof text) + return -1; fd = mkstemp(tmp); if(fd < 0) return -1; - ok = 0; - fp = nil; - if(fchmod(fd, 0600) < 0) - goto out; - fp = fdopen(fd, "w"); - if(fp == nil) - goto out; - fd = -1; - if(fprintf(fp, "IBUS_ADDRESS=%s\n", addr) < 0 || - fprintf(fp, "IBUS_DAEMON_PID=%d\n", (int)getpid()) < 0 || - fflush(fp) < 0 || fsync(fileno(fp)) < 0 || - fstat(fileno(fp), &st) < 0) - goto out; - if(fclose(fp) < 0){ - fp = nil; - goto out; + ok = write(fd, text, n) == n && fsync(fd) == 0 && + fstat(fd, &st) == 0; + close(fd); + if(!ok || rename(tmp, path) < 0){ + unlink(tmp); + return -1; } - fp = nil; - if(rename(tmp, path) < 0) - goto out; addrdev = st.st_dev; addrino = st.st_ino; - addrowned = 1; - ok = 1; -out: - if(fp != nil) - fclose(fp); - if(fd >= 0) - close(fd); - if(!ok) - unlink(tmp); - return ok ? 0 : -1; + return 0; } static dbus_bool_t @@ -350,20 +322,7 @@ static int hidden(Ictx *ctx) { return ctx->purpose == Ibuspurposepassword || - ctx->purpose == Ibuspurposepin || - (ctx->hints & Ibushinthidden) != 0; -} - -static int -processkey(Ictx *ctx, u32int sym, u32int state, Keyres *res) -{ - if(state & Relmask || !ctx->focused || hidden(ctx)) - return 0; - sendrequest(ctx, Keypress, ipckeysym(sym, xkb_keysym_to_utf32(sym)), - ipcmod(state), res); - if(preowner != nil && preowner != ctx) - checkpreowner(); - return 1; + ctx->purpose == Ibuspurposepin; } static void @@ -379,11 +338,21 @@ setcursor(Ictx *ctx, int x, int y, int h) sendrequest(ctx, Keycaret, 0, 0, &res); } +/* Every IBus serializable carries an (empty) attachment dictionary. */ +static void +emptydict(DBusMessageIter *it) +{ + DBusMessageIter d; + + dbus_message_iter_open_container(it, DBUS_TYPE_ARRAY, "{sv}", &d); + dbus_message_iter_close_container(it, &d); +} + +/* IBusText: (sa{sv}sv) holding an IBusAttrList of IBusAttributes. */ static void appendibustext(DBusMessageIter *it, const char *s, int underline) { - DBusMessageIter v, st, attach, alv, ali, attr, alist; - DBusMessageIter av, ai, aattach; + DBusMessageIter v, st, alv, ali, alist, av, ai; const char *name = "IBusText"; const char *aname = "IBusAttrList"; const char *iname = "IBusAttribute"; @@ -392,14 +361,12 @@ appendibustext(DBusMessageIter *it, const char *s, int underline) dbus_message_iter_open_container(it, DBUS_TYPE_VARIANT, "(sa{sv}sv)", &v); dbus_message_iter_open_container(&v, DBUS_TYPE_STRUCT, nil, &st); dbus_message_iter_append_basic(&st, DBUS_TYPE_STRING, &name); - dbus_message_iter_open_container(&st, DBUS_TYPE_ARRAY, "{sv}", &attach); - dbus_message_iter_close_container(&st, &attach); + emptydict(&st); dbus_message_iter_append_basic(&st, DBUS_TYPE_STRING, &s); dbus_message_iter_open_container(&st, DBUS_TYPE_VARIANT, "(sa{sv}av)", &alv); dbus_message_iter_open_container(&alv, DBUS_TYPE_STRUCT, nil, &ali); dbus_message_iter_append_basic(&ali, DBUS_TYPE_STRING, &aname); - dbus_message_iter_open_container(&ali, DBUS_TYPE_ARRAY, "{sv}", &attr); - dbus_message_iter_close_container(&ali, &attr); + emptydict(&ali); dbus_message_iter_open_container(&ali, DBUS_TYPE_ARRAY, "v", &alist); if(underline && s[0] != '\0'){ type = Ibusattrunderline; @@ -410,9 +377,7 @@ appendibustext(DBusMessageIter *it, const char *s, int underline) "(sa{sv}uuuu)", &av); dbus_message_iter_open_container(&av, DBUS_TYPE_STRUCT, nil, &ai); dbus_message_iter_append_basic(&ai, DBUS_TYPE_STRING, &iname); - dbus_message_iter_open_container(&ai, DBUS_TYPE_ARRAY, "{sv}", - &aattach); - dbus_message_iter_close_container(&ai, &aattach); + emptydict(&ai); dbus_message_iter_append_basic(&ai, DBUS_TYPE_UINT32, &type); dbus_message_iter_append_basic(&ai, DBUS_TYPE_UINT32, &value); dbus_message_iter_append_basic(&ai, DBUS_TYPE_UINT32, &start); @@ -427,22 +392,33 @@ appendibustext(DBusMessageIter *it, const char *s, int underline) dbus_message_iter_close_container(it, &v); } +static DBusMessage* +newsignal(const char *path, const char *name) +{ + DBusMessage *sig; + + sig = dbus_message_new_signal(path, "org.freedesktop.IBus.InputContext", + name); + if(sig == nil) + die("ibus: out of memory"); + dbus_message_set_sender(sig, ibusowner); + return sig; +} + static void emitcommit(DBusConnection *c, const char *path, const char *text) { DBusMessage *sig; DBusMessageIter it; - sig = dbus_message_new_signal(path, "org.freedesktop.IBus.InputContext", "CommitText"); - if(sig == nil) - return; + sig = newsignal(path, "CommitText"); dbus_message_iter_init_append(sig, &it); appendibustext(&it, text, 0); - dbus_message_set_sender(sig, ibusowner); dbus_connection_send(c, sig, nil); dbus_message_unref(sig); } +/* preowner is the one context showing a preedit; clearing anyone else's is moot. */ static void emitpreedit(Ictx *ctx, const char *text) { @@ -450,14 +426,11 @@ emitpreedit(Ictx *ctx, const char *text) DBusMessageIter it; dbus_uint32_t cursor, mode; dbus_bool_t visible; - const char *name; - name = ctx->clientcommitpreedit ? - "UpdatePreeditTextWithMode" : "UpdatePreeditText"; - sig = dbus_message_new_signal(ctx->path, - "org.freedesktop.IBus.InputContext", name); - if(sig == nil) + if(text[0] == '\0' && preowner != ctx) return; + sig = newsignal(ctx->path, ctx->clientcommitpreedit ? + "UpdatePreeditTextWithMode" : "UpdatePreeditText"); dbus_message_iter_init_append(sig, &it); appendibustext(&it, text, 1); cursor = utflen((char*)text); @@ -468,7 +441,6 @@ emitpreedit(Ictx *ctx, const char *text) mode = Ibuspreeditclear; dbus_message_iter_append_basic(&it, DBUS_TYPE_UINT32, &mode); } - dbus_message_set_sender(sig, ibusowner); if(dbus_connection_send(ctx->conn, sig, nil)){ if(text[0] != '\0') preowner = ctx; @@ -478,6 +450,7 @@ emitpreedit(Ictx *ctx, const char *text) dbus_message_unref(sig); } +/* Another frontend may have taken the engine; then our preedit is stale. */ static void checkpreowner(void) { @@ -492,10 +465,62 @@ checkpreowner(void) emitpreedit(ctx, ""); } +static int +processkey(Ictx *ctx, u32int sym, u32int state, Keyres *res) +{ + if(state & Relmask || !ctx->focused || hidden(ctx)) + return 0; + sendrequest(ctx, Keypress, ipckeysym(sym, xkb_keysym_to_utf32(sym)), + ipcmod(state), res); + if(preowner != nil && preowner != ctx) + checkpreowner(); + return 1; +} + + +static DBusHandlerResult +handleerror(DBusConnection *c, DBusMessage *m, const char *name, + const char *text) +{ + DBusMessage *r; + + r = dbus_message_new_error(m, name, text); + if(r == nil) + die("ibus: out of memory"); + dbus_connection_send(c, r, nil); + dbus_message_unref(r); + return DBUS_HANDLER_RESULT_HANDLED; +} + +/* Replies with one argument of the given D-Bus type, or none. */ +static DBusHandlerResult +reply(DBusConnection *c, DBusMessage *m, int type, void *v) +{ + DBusMessage *r; + + r = dbus_message_new_method_return(m); + if(r == nil) + die("ibus: out of memory"); + if(type != DBUS_TYPE_INVALID) + dbus_message_append_args(r, type, v, DBUS_TYPE_INVALID); + dbus_connection_send(c, r, nil); + dbus_message_unref(r); + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusHandlerResult +replybool(DBusConnection *c, DBusMessage *m, int value) +{ + dbus_bool_t b; + + b = value ? TRUE : FALSE; + return reply(c, m, DBUS_TYPE_BOOLEAN, &b); +} + +/* We are the bus as well as the engine: Hello names the caller. */ static DBusHandlerResult handlehello(DBusConnection *c, DBusMessage *m) { - DBusMessage *r; char name[32]; const char *np; @@ -505,122 +530,66 @@ handlehello(DBusConnection *c, DBusMessage *m) busctr++; snprintf(name, sizeof(name), ":1.%d", busctr); np = name; - r = dbus_message_new_method_return(m); - dbus_message_append_args(r, DBUS_TYPE_STRING, &np, DBUS_TYPE_INVALID); - dbus_connection_send(c, r, nil); - dbus_message_unref(r); - return DBUS_HANDLER_RESULT_HANDLED; + return reply(c, m, DBUS_TYPE_STRING, &np); } static DBusHandlerResult handlenameowner(DBusConnection *c, DBusMessage *m) { - DBusError err; - DBusMessage *r; const char *name, *owner; - dbus_error_init(&err); - if(!dbus_message_get_args(m, &err, DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)){ - dbus_error_free(&err); + if(!dbus_message_get_args(m, nil, DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID)) return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, "GetNameOwner expects one bus name"); - } if(strcmp(name, "org.freedesktop.IBus") != 0) return handleerror(c, m, DBUS_ERROR_NAME_HAS_NO_OWNER, "bus name has no owner"); owner = ibusowner; - r = dbus_message_new_method_return(m); - if(r == nil) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - dbus_message_append_args(r, DBUS_TYPE_STRING, &owner, DBUS_TYPE_INVALID); - dbus_connection_send(c, r, nil); - dbus_message_unref(r); - return DBUS_HANDLER_RESULT_HANDLED; -} - -static DBusHandlerResult -handleerror(DBusConnection *c, DBusMessage *m, const char *name, - const char *text) -{ - DBusMessage *r; - - r = dbus_message_new_error(m, name, text); - if(r != nil){ - dbus_connection_send(c, r, nil); - dbus_message_unref(r); - } - return DBUS_HANDLER_RESULT_HANDLED; -} - -static DBusHandlerResult -handlebool(DBusConnection *c, DBusMessage *m, int value) -{ - DBusMessage *r; - dbus_bool_t b; - - r = dbus_message_new_method_return(m); - b = value ? TRUE : FALSE; - dbus_message_append_args(r, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID); - dbus_connection_send(c, r, nil); - dbus_message_unref(r); - return DBUS_HANDLER_RESULT_HANDLED; + return reply(c, m, DBUS_TYPE_STRING, &owner); } static DBusHandlerResult handlecreate(DBusConnection *c, DBusMessage *m) { - DBusMessage *r; char path[64]; const char *pp; Ictx *ctx; - int n; if(!dbus_message_has_signature(m, "s")) return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, "CreateInputContext expects one client name"); icctr++; - n = snprintf(path, sizeof(path), + snprintf(path, sizeof(path), "/org/freedesktop/IBus/InputContext_%d", icctr); - if(n < 0 || n >= (int)sizeof path) - return handleerror(c, m, DBUS_ERROR_LIMITS_EXCEEDED, - "input context path exhausted"); ctx = newcontext(c, path); if(ctx == nil) return handleerror(c, m, DBUS_ERROR_LIMITS_EXCEEDED, "too many input contexts"); pp = path; - r = dbus_message_new_method_return(m); - dbus_message_append_args(r, DBUS_TYPE_OBJECT_PATH, &pp, DBUS_TYPE_INVALID); - dbus_connection_send(c, r, nil); - dbus_message_unref(r); - return DBUS_HANDLER_RESULT_HANDLED; + return reply(c, m, DBUS_TYPE_OBJECT_PATH, &pp); } static DBusHandlerResult handlekey(DBusConnection *c, DBusMessage *m, Ictx *ctx) { - DBusError err; dbus_uint32_t sym, code, state; Keyres res; char commit[Maxutf], preedit[Maxutf]; int restart; - dbus_error_init(&err); - if(!dbus_message_get_args(m, &err, + if(!dbus_message_get_args(m, nil, DBUS_TYPE_UINT32, &sym, DBUS_TYPE_UINT32, &code, DBUS_TYPE_UINT32, &state, - DBUS_TYPE_INVALID)){ - dbus_error_free(&err); + DBUS_TYPE_INVALID)) return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, "ProcessKeyEvent expects three unsigned integers"); - } - USED(code); if(!processkey(ctx, sym, state, &res)) - return handlebool(c, m, 0); + return replybool(c, m, 0); stoutf(&res.commit, commit, sizeof commit); stoutf(&res.preedit, preedit, sizeof preedit); + /* A commit ends the preedit around it, so clients place it right. */ restart = clientpreedit(ctx) && commit[0] != '\0' && preowner == ctx; if(restart) emitpreedit(ctx, ""); @@ -628,18 +597,7 @@ handlekey(DBusConnection *c, DBusMessage *m, Ictx *ctx) emitcommit(c, dbus_message_get_path(m), commit); if(clientpreedit(ctx) && (!restart || preedit[0] != '\0')) emitpreedit(ctx, preedit); - return handlebool(c, m, res.eaten); -} - -static DBusHandlerResult -handlenoop(DBusConnection *c, DBusMessage *m) -{ - DBusMessage *r; - - r = dbus_message_new_method_return(m); - dbus_connection_send(c, r, nil); - dbus_message_unref(r); - return DBUS_HANDLER_RESULT_HANDLED; + return replybool(c, m, res.eaten); } static DBusHandlerResult @@ -650,14 +608,14 @@ handlereset(DBusConnection *c, DBusMessage *m, Ictx *ctx) sendrequest(ctx, Keyreset, 0, 0, &res); if(clientpreedit(ctx)) emitpreedit(ctx, ""); - return handlenoop(c, m); + return reply(c, m, DBUS_TYPE_INVALID, nil); } static DBusHandlerResult handlefocusin(DBusConnection *c, DBusMessage *m, Ictx *ctx) { ctx->focused = 1; - return handlenoop(c, m); + return reply(c, m, DBUS_TYPE_INVALID, nil); } static DBusHandlerResult @@ -666,25 +624,21 @@ handlefocusout(DBusConnection *c, DBusMessage *m, Ictx *ctx) releasecontext(ctx); if(clientpreedit(ctx)) emitpreedit(ctx, ""); - return handlenoop(c, m); + return reply(c, m, DBUS_TYPE_INVALID, nil); } static DBusHandlerResult handlecap(DBusConnection *c, DBusMessage *m, Ictx *ctx) { - DBusError err; dbus_uint32_t cap; Keyres res; char preedit[Maxutf]; u32int old; - dbus_error_init(&err); - if(!dbus_message_get_args(m, &err, DBUS_TYPE_UINT32, &cap, - DBUS_TYPE_INVALID)){ - dbus_error_free(&err); + if(!dbus_message_get_args(m, nil, DBUS_TYPE_UINT32, &cap, + DBUS_TYPE_INVALID)) return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, "SetCapabilities expects one unsigned integer"); - } old = ctx->cap; ctx->cap = cap; if(ctx->focused){ @@ -697,7 +651,7 @@ handlecap(DBusConnection *c, DBusMessage *m, Ictx *ctx) emitpreedit(ctx, ""); } } - return handlenoop(c, m); + return reply(c, m, DBUS_TYPE_INVALID, nil); } static int @@ -740,6 +694,7 @@ getcontent(DBusMessageIter *value, u32int *purpose, u32int *hints) return 1; } +/* Only ContentType and ClientCommitPreedit are settable; none is readable. */ static DBusHandlerResult handlepropertyset(DBusConnection *c, DBusMessage *m, Ictx *ctx) { @@ -768,7 +723,7 @@ handlepropertyset(DBusConnection *c, DBusMessage *m, Ictx *ctx) if(clientpreedit(ctx)) emitpreedit(ctx, ""); } - return handlenoop(c, m); + return reply(c, m, DBUS_TYPE_INVALID, nil); } if(strcmp(name, "ClientCommitPreedit") == 0){ if(dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_STRUCT) @@ -783,60 +738,31 @@ handlepropertyset(DBusConnection *c, DBusMessage *m, Ictx *ctx) return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, "ClientCommitPreedit expects (b)"); ctx->clientcommitpreedit = b != FALSE; - return handlenoop(c, m); + return reply(c, m, DBUS_TYPE_INVALID, nil); } return handleerror(c, m, DBUS_ERROR_UNKNOWN_PROPERTY, "unknown input context property"); } static DBusHandlerResult -handlepropertyget(DBusConnection *c, DBusMessage *m, Ictx *ctx) -{ - DBusError err; - const char *iface, *name; - - USED(ctx); - dbus_error_init(&err); - if(!dbus_message_get_args(m, &err, - DBUS_TYPE_STRING, &iface, DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)){ - dbus_error_free(&err); - return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, - "Properties.Get expects interface and property names"); - } - if(strcmp(iface, "org.freedesktop.IBus.InputContext") != 0) - return handleerror(c, m, DBUS_ERROR_UNKNOWN_INTERFACE, - "unknown property interface"); - USED(name); - return handleerror(c, m, DBUS_ERROR_UNKNOWN_PROPERTY, - "input context properties are write-only"); -} - -static DBusHandlerResult -handlepropertygetall(DBusConnection *c, DBusMessage *m, Ictx *ctx) +handlepropertygetall(DBusConnection *c, DBusMessage *m) { DBusMessage *r; - DBusMessageIter it, a; - DBusError err; + DBusMessageIter it; const char *iface; - USED(ctx); - dbus_error_init(&err); - if(!dbus_message_get_args(m, &err, DBUS_TYPE_STRING, &iface, - DBUS_TYPE_INVALID)){ - dbus_error_free(&err); + if(!dbus_message_get_args(m, nil, DBUS_TYPE_STRING, &iface, + DBUS_TYPE_INVALID)) return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, "Properties.GetAll expects an interface name"); - } if(strcmp(iface, "org.freedesktop.IBus.InputContext") != 0) return handleerror(c, m, DBUS_ERROR_UNKNOWN_INTERFACE, "unknown property interface"); r = dbus_message_new_method_return(m); if(r == nil) - return DBUS_HANDLER_RESULT_NEED_MEMORY; + die("ibus: out of memory"); dbus_message_iter_init_append(r, &it); - dbus_message_iter_open_container(&it, DBUS_TYPE_ARRAY, "{sv}", &a); - dbus_message_iter_close_container(&it, &a); + emptydict(&it); dbus_connection_send(c, r, nil); dbus_message_unref(r); return DBUS_HANDLER_RESULT_HANDLED; @@ -846,99 +772,54 @@ static DBusHandlerResult handledestroy(DBusConnection *c, DBusMessage *m, Ictx *ctx) { dropcontext(ctx); - return handlenoop(c, m); + return reply(c, m, DBUS_TYPE_INVALID, nil); } static DBusHandlerResult handlecursor(DBusConnection *c, DBusMessage *m, Ictx *ctx) { - DBusError err; dbus_int32_t x, y, w, h; - dbus_error_init(&err); - if(!dbus_message_get_args(m, &err, + if(!dbus_message_get_args(m, nil, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_INT32, &w, DBUS_TYPE_INT32, &h, - DBUS_TYPE_INVALID)){ - dbus_error_free(&err); + DBUS_TYPE_INVALID)) return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, "SetCursorLocation expects four integers"); - } if(w < 0 || h < 0) return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, "cursor dimensions must not be negative"); setcursor(ctx, x, y, h); - return handlenoop(c, m); + return reply(c, m, DBUS_TYPE_INVALID, nil); } -static const char introspectxml[] = -"\n" -"\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" " -"" -"\n" -" \n" -" \n" -" \n" -" \n" -" " -"\n" -" " -"" -"\n" -" \n" -" \n" -" " -"\n" -" " -"\n" -" " -"\n" -" \n" -"\n"; - +/* Argument-free InputContext calls, checked for an empty signature. */ static DBusHandlerResult -handleintrospect(DBusConnection *c, DBusMessage *m) +handleplain(DBusConnection *c, DBusMessage *m, Ictx *ctx, const char *member) { - DBusMessage *r; - const char *xml = introspectxml; - if(!dbus_message_has_signature(m, "")) return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, - "Introspect expects no arguments"); - r = dbus_message_new_method_return(m); - dbus_message_append_args(r, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID); - dbus_connection_send(c, r, nil); - dbus_message_unref(r); - return DBUS_HANDLER_RESULT_HANDLED; + "this call takes no arguments"); + if(strcmp(member, "FocusIn") == 0) + return handlefocusin(c, m, ctx); + if(strcmp(member, "FocusOut") == 0) + return handlefocusout(c, m, ctx); + if(strcmp(member, "Reset") == 0) + return handlereset(c, m, ctx); + return handledestroy(c, m, ctx); } +/* + * One handler for everything a client sends: the tiny slice of the bus + * that libibus needs, then the InputContext interface. Unhandled calls + * get libdbus's UnknownMethod error. + */ static DBusHandlerResult -onmsg(DBusConnection *c, DBusMessage *m, void *_) +onmsg(DBusConnection *c, DBusMessage *m, void*) { const char *iface, *member, *path; Ictx *ctx; - USED(_); if(dbus_message_get_type(m) != DBUS_MESSAGE_TYPE_METHOD_CALL) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; iface = dbus_message_get_interface(m); @@ -946,9 +827,6 @@ onmsg(DBusConnection *c, DBusMessage *m, void *_) path = dbus_message_get_path(m); if(iface == nil || member == nil || path == nil) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - if(strcmp(iface, "org.freedesktop.DBus.Introspectable") == 0 - && strcmp(member, "Introspect") == 0) - return handleintrospect(c, m); if(strcmp(iface, "org.freedesktop.DBus") == 0){ if(strcmp(member, "Hello") == 0) return handlehello(c, m); @@ -959,7 +837,7 @@ onmsg(DBusConnection *c, DBusMessage *m, void *_) if(!dbus_message_has_signature(m, "s")) return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, "match rule must be one string"); - return handlenoop(c, m); + return reply(c, m, DBUS_TYPE_INVALID, nil); } } if(strcmp(iface, "org.freedesktop.IBus") == 0){ @@ -967,16 +845,16 @@ onmsg(DBusConnection *c, DBusMessage *m, void *_) return handlecreate(c, m); } if(strcmp(iface, "org.freedesktop.DBus.Properties") == 0){ - ctx = findcontext(c, path); - if(ctx == nil) + if(findcontext(c, path) == nil) return handleerror(c, m, DBUS_ERROR_UNKNOWN_OBJECT, "unknown input context"); if(strcmp(member, "Set") == 0) - return handlepropertyset(c, m, ctx); + return handlepropertyset(c, m, findcontext(c, path)); if(strcmp(member, "Get") == 0) - return handlepropertyget(c, m, ctx); + return handleerror(c, m, DBUS_ERROR_UNKNOWN_PROPERTY, + "input context properties are write-only"); if(strcmp(member, "GetAll") == 0) - return handlepropertygetall(c, m, ctx); + return handlepropertygetall(c, m); } if(strcmp(iface, "org.freedesktop.IBus.InputContext") == 0){ ctx = findcontext(c, path); @@ -985,30 +863,11 @@ onmsg(DBusConnection *c, DBusMessage *m, void *_) "unknown input context"); if(strcmp(member, "ProcessKeyEvent") == 0) return handlekey(c, m, ctx); - if(strcmp(member, "FocusIn") == 0){ - if(!dbus_message_has_signature(m, "")) - return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, - "FocusIn expects no arguments"); - return handlefocusin(c, m, ctx); - } - if(strcmp(member, "FocusOut") == 0){ - if(!dbus_message_has_signature(m, "")) - return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, - "FocusOut expects no arguments"); - return handlefocusout(c, m, ctx); - } - if(strcmp(member, "Reset") == 0){ - if(!dbus_message_has_signature(m, "")) - return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, - "Reset expects no arguments"); - return handlereset(c, m, ctx); - } - if(strcmp(member, "Destroy") == 0){ - if(!dbus_message_has_signature(m, "")) - return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, - "Destroy expects no arguments"); - return handledestroy(c, m, ctx); - } + if(strcmp(member, "FocusIn") == 0 || + strcmp(member, "FocusOut") == 0 || + strcmp(member, "Reset") == 0 || + strcmp(member, "Destroy") == 0) + return handleplain(c, m, ctx, member); if(strcmp(member, "SetCursorLocation") == 0) return handlecursor(c, m, ctx); if(strcmp(member, "SetCapabilities") == 0) @@ -1017,7 +876,7 @@ onmsg(DBusConnection *c, DBusMessage *m, void *_) if(!dbus_message_has_signature(m, "s")) return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, "SetEngine expects one engine name"); - return handlenoop(c, m); + return reply(c, m, DBUS_TYPE_INVALID, nil); } } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; diff --git a/tests/ibus_test.c b/tests/ibus_test.c index f7313d2..83814eb 100644 --- a/tests/ibus_test.c +++ b/tests/ibus_test.c @@ -358,7 +358,6 @@ ibus_private_input_policy(struct ct *t) { Ibuspurposepassword, 0, 1 }, { Ibuspurposepin, 0, 1 }, { 0, 1<<11, 0 }, - { 0, Ibushinthidden, 1 }, { 37, 1<<20, 0 }, }; Ibusfix f;