ibus: the InputContext interface as a table

onmsg matched the member name, then handleplain matched four of the
names again after checking their empty signature, and the handlers that
take arguments each re-checked theirs with a message of their own.  One
table of member, signature, and handler does the matching and the
checking once; the handlers read arguments a signature has already
vouched for.
This commit is contained in:
2026-08-17 10:55:09 +09:00
parent 82cb07eba2
commit 46bb8b1d46

76
ibus.c
View File

@@ -630,13 +630,9 @@ handlekey(DBusConnection *c, DBusMessage *m, Ictx *ctx)
char commit[Maxutf], preedit[Maxutf]; char commit[Maxutf], preedit[Maxutf];
int restart; int restart;
if(!dbus_message_get_args(m, nil, dbus_message_get_args(m, nil, DBUS_TYPE_UINT32, &sym,
DBUS_TYPE_UINT32, &sym, DBUS_TYPE_UINT32, &code, DBUS_TYPE_UINT32, &state,
DBUS_TYPE_UINT32, &code, DBUS_TYPE_INVALID);
DBUS_TYPE_UINT32, &state,
DBUS_TYPE_INVALID))
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
"ProcessKeyEvent expects three unsigned integers");
if(!processkey(ctx, sym, state, &res)) if(!processkey(ctx, sym, state, &res))
return replybool(c, m, 0); return replybool(c, m, 0);
stoutf(&res.commit, commit, sizeof commit); stoutf(&res.commit, commit, sizeof commit);
@@ -722,10 +718,7 @@ handlecap(DBusConnection *c, DBusMessage *m, Ictx *ctx)
char preedit[Maxutf]; char preedit[Maxutf];
u32int old; u32int old;
if(!dbus_message_get_args(m, nil, DBUS_TYPE_UINT32, &cap, dbus_message_get_args(m, nil, DBUS_TYPE_UINT32, &cap, DBUS_TYPE_INVALID);
DBUS_TYPE_INVALID))
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
"SetCapabilities expects one unsigned integer");
old = ctx->cap; old = ctx->cap;
ctx->cap = cap; ctx->cap = cap;
if(ctx->focused){ if(ctx->focused){
@@ -865,32 +858,35 @@ handlecursor(DBusConnection *c, DBusMessage *m, Ictx *ctx)
{ {
dbus_int32_t x, y, w, h; dbus_int32_t x, y, w, h;
if(!dbus_message_get_args(m, nil, dbus_message_get_args(m, nil, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y,
DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_INT32, &w, DBUS_TYPE_INT32, &h, DBUS_TYPE_INVALID);
DBUS_TYPE_INT32, &w, DBUS_TYPE_INT32, &h,
DBUS_TYPE_INVALID))
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
"SetCursorLocation expects four integers");
setcursor(ctx, x, y, h); setcursor(ctx, x, y, h);
return reply(c, m, DBUS_TYPE_INVALID, nil); return reply(c, m, DBUS_TYPE_INVALID, nil);
} }
/* Argument-free InputContext calls, checked for an empty signature. */ /* SetEngine: there is one engine, so any name is fine. */
static DBusHandlerResult static DBusHandlerResult
handleplain(DBusConnection *c, DBusMessage *m, Ictx *ctx, const char *member) handleok(DBusConnection *c, DBusMessage *m, Ictx*)
{ {
if(!dbus_message_has_signature(m, "")) return reply(c, m, DBUS_TYPE_INVALID, nil);
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
"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);
} }
/* The InputContext interface: member, argument signature, handler. */
static struct {
char *member;
char *sig;
DBusHandlerResult (*fn)(DBusConnection*, DBusMessage*, Ictx*);
} ictab[] = {
{"ProcessKeyEvent", "uuu", handlekey},
{"FocusIn", "", handlefocusin},
{"FocusOut", "", handlefocusout},
{"Reset", "", handlereset},
{"Destroy", "", handledestroy},
{"SetCursorLocation", "iiii", handlecursor},
{"SetCapabilities", "u", handlecap},
{"SetEngine", "s", handleok},
};
/* /*
* One handler for everything a client sends: the tiny slice of the bus * One handler for everything a client sends: the tiny slice of the bus
* that libibus needs, then the InputContext interface. Unhandled calls * that libibus needs, then the InputContext interface. Unhandled calls
@@ -901,6 +897,7 @@ onmsg(DBusConnection *c, DBusMessage *m, void*)
{ {
const char *iface, *member, *path; const char *iface, *member, *path;
Ictx *ctx; Ictx *ctx;
int i;
if(dbus_message_get_type(m) != DBUS_MESSAGE_TYPE_METHOD_CALL) if(dbus_message_get_type(m) != DBUS_MESSAGE_TYPE_METHOD_CALL)
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -953,22 +950,13 @@ onmsg(DBusConnection *c, DBusMessage *m, void*)
if(ctx == nil) if(ctx == nil)
return handleerror(c, m, DBUS_ERROR_UNKNOWN_OBJECT, return handleerror(c, m, DBUS_ERROR_UNKNOWN_OBJECT,
"unknown input context"); "unknown input context");
if(strcmp(member, "ProcessKeyEvent") == 0) for(i = 0; i < nelem(ictab); i++){
return handlekey(c, m, ctx); if(strcmp(member, ictab[i].member) != 0)
if(strcmp(member, "FocusIn") == 0 || continue;
strcmp(member, "FocusOut") == 0 || if(!dbus_message_has_signature(m, ictab[i].sig))
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)
return handlecap(c, m, ctx);
if(strcmp(member, "SetEngine") == 0){
if(!dbus_message_has_signature(m, "s"))
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
"SetEngine expects one engine name"); "bad arguments");
return reply(c, m, DBUS_TYPE_INVALID, nil); return ictab[i].fn(c, m, ctx);
} }
} }
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;