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.
This commit is contained in:
481
ibus.c
481
ibus.c
@@ -22,7 +22,6 @@ enum
|
|||||||
Ibuscappreedit = 1<<0,
|
Ibuscappreedit = 1<<0,
|
||||||
Ibuspurposepassword = 8,
|
Ibuspurposepassword = 8,
|
||||||
Ibuspurposepin = 9,
|
Ibuspurposepin = 9,
|
||||||
Ibushinthidden = 1<<12,
|
|
||||||
Ibusattrunderline = 1,
|
Ibusattrunderline = 1,
|
||||||
Ibusunderlinesingle = 1,
|
Ibusunderlinesingle = 1,
|
||||||
Ibuspreeditclear = 0,
|
Ibuspreeditclear = 0,
|
||||||
@@ -50,27 +49,24 @@ static Ictx contexts[Maxcontexts];
|
|||||||
static char addrfile[512];
|
static char addrfile[512];
|
||||||
static dev_t addrdev;
|
static dev_t addrdev;
|
||||||
static ino_t addrino;
|
static ino_t addrino;
|
||||||
static int addrowned;
|
|
||||||
static int icctr;
|
static int icctr;
|
||||||
static int busctr;
|
static int busctr;
|
||||||
static Channel *replyc;
|
static Channel *replyc;
|
||||||
static const char ibusowner[] = ":1.0";
|
static const char ibusowner[] = ":1.0";
|
||||||
static Ictx *preowner;
|
static Ictx *preowner;
|
||||||
|
|
||||||
static DBusHandlerResult onmsg(DBusConnection*, DBusMessage*, void*);
|
/* Removes the address file only while it is still the one we wrote. */
|
||||||
static DBusHandlerResult handleerror(DBusConnection*, DBusMessage*,
|
|
||||||
const char*, const char*);
|
|
||||||
static void checkpreowner(void);
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
unlinkaddr(void)
|
unlinkaddr(void)
|
||||||
{
|
{
|
||||||
struct stat st;
|
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)
|
st.st_dev == addrdev && st.st_ino == addrino)
|
||||||
unlink(addrfile);
|
unlink(addrfile);
|
||||||
addrowned = 0;
|
addrfile[0] = '\0';
|
||||||
|
addrdev = 0;
|
||||||
|
addrino = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -136,12 +132,12 @@ xdisplay(char *host, int hsz, char *num, int nsz)
|
|||||||
num[n] = '\0';
|
num[n] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The IBus address file lives where libibus looks: config/ibus/bus/. */
|
||||||
static int
|
static int
|
||||||
buildaddrpath(char *buf, int sz)
|
buildaddrpath(char *buf, int sz)
|
||||||
{
|
{
|
||||||
char mid[64], host[64], num[8], *cfg, *home, *explicit;
|
char mid[64], host[64], num[8], dir[512];
|
||||||
struct stat st;
|
char *cfg, *home, *explicit, *p;
|
||||||
char dir[512];
|
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
explicit = getenv("IBUS_ADDRESS_FILE");
|
explicit = getenv("IBUS_ADDRESS_FILE");
|
||||||
@@ -164,69 +160,45 @@ buildaddrpath(char *buf, int sz)
|
|||||||
}
|
}
|
||||||
if(n < 0 || n >= (int)sizeof dir)
|
if(n < 0 || n >= (int)sizeof dir)
|
||||||
return -1;
|
return -1;
|
||||||
if(stat(dir, &st) < 0){
|
for(p = dir+1; *p; p++)
|
||||||
char tmp[512];
|
|
||||||
char *p;
|
|
||||||
strncpy(tmp, dir, sizeof(tmp));
|
|
||||||
tmp[sizeof(tmp)-1] = '\0';
|
|
||||||
for(p = tmp+1; *p; p++)
|
|
||||||
if(*p == '/'){
|
if(*p == '/'){
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
mkdir(tmp, 0700);
|
mkdir(dir, 0700);
|
||||||
*p = '/';
|
*p = '/';
|
||||||
}
|
}
|
||||||
mkdir(tmp, 0700);
|
mkdir(dir, 0700);
|
||||||
}
|
|
||||||
n = snprintf(buf, sz, "%s/%s-%s-%s", dir, mid, host, num);
|
n = snprintf(buf, sz, "%s/%s-%s-%s", dir, mid, host, num);
|
||||||
return n < 0 || n >= sz ? -1 : 0;
|
return n < 0 || n >= sz ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Publishes the address atomically and remembers the file's identity. */
|
||||||
static int
|
static int
|
||||||
writeaddr(char *path, char *addr)
|
writeaddr(char *path, char *addr)
|
||||||
{
|
{
|
||||||
char tmp[576];
|
char tmp[576], text[256];
|
||||||
FILE *fp;
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int fd, n, ok;
|
int fd, n, ok;
|
||||||
|
|
||||||
n = snprintf(tmp, sizeof tmp, "%s.tmp.XXXXXX", path);
|
n = snprintf(tmp, sizeof tmp, "%s.tmp.XXXXXX", path);
|
||||||
if(n < 0 || n >= (int)sizeof tmp)
|
if(n < 0 || n >= (int)sizeof tmp)
|
||||||
return -1;
|
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);
|
fd = mkstemp(tmp);
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
ok = 0;
|
ok = write(fd, text, n) == n && fsync(fd) == 0 &&
|
||||||
fp = nil;
|
fstat(fd, &st) == 0;
|
||||||
if(fchmod(fd, 0600) < 0)
|
close(fd);
|
||||||
goto out;
|
if(!ok || rename(tmp, path) < 0){
|
||||||
fp = fdopen(fd, "w");
|
unlink(tmp);
|
||||||
if(fp == nil)
|
return -1;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
fp = nil;
|
|
||||||
if(rename(tmp, path) < 0)
|
|
||||||
goto out;
|
|
||||||
addrdev = st.st_dev;
|
addrdev = st.st_dev;
|
||||||
addrino = st.st_ino;
|
addrino = st.st_ino;
|
||||||
addrowned = 1;
|
return 0;
|
||||||
ok = 1;
|
|
||||||
out:
|
|
||||||
if(fp != nil)
|
|
||||||
fclose(fp);
|
|
||||||
if(fd >= 0)
|
|
||||||
close(fd);
|
|
||||||
if(!ok)
|
|
||||||
unlink(tmp);
|
|
||||||
return ok ? 0 : -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static dbus_bool_t
|
static dbus_bool_t
|
||||||
@@ -350,20 +322,7 @@ static int
|
|||||||
hidden(Ictx *ctx)
|
hidden(Ictx *ctx)
|
||||||
{
|
{
|
||||||
return ctx->purpose == Ibuspurposepassword ||
|
return ctx->purpose == Ibuspurposepassword ||
|
||||||
ctx->purpose == Ibuspurposepin ||
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -379,11 +338,21 @@ setcursor(Ictx *ctx, int x, int y, int h)
|
|||||||
sendrequest(ctx, Keycaret, 0, 0, &res);
|
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
|
static void
|
||||||
appendibustext(DBusMessageIter *it, const char *s, int underline)
|
appendibustext(DBusMessageIter *it, const char *s, int underline)
|
||||||
{
|
{
|
||||||
DBusMessageIter v, st, attach, alv, ali, attr, alist;
|
DBusMessageIter v, st, alv, ali, alist, av, ai;
|
||||||
DBusMessageIter av, ai, aattach;
|
|
||||||
const char *name = "IBusText";
|
const char *name = "IBusText";
|
||||||
const char *aname = "IBusAttrList";
|
const char *aname = "IBusAttrList";
|
||||||
const char *iname = "IBusAttribute";
|
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(it, DBUS_TYPE_VARIANT, "(sa{sv}sv)", &v);
|
||||||
dbus_message_iter_open_container(&v, DBUS_TYPE_STRUCT, nil, &st);
|
dbus_message_iter_open_container(&v, DBUS_TYPE_STRUCT, nil, &st);
|
||||||
dbus_message_iter_append_basic(&st, DBUS_TYPE_STRING, &name);
|
dbus_message_iter_append_basic(&st, DBUS_TYPE_STRING, &name);
|
||||||
dbus_message_iter_open_container(&st, DBUS_TYPE_ARRAY, "{sv}", &attach);
|
emptydict(&st);
|
||||||
dbus_message_iter_close_container(&st, &attach);
|
|
||||||
dbus_message_iter_append_basic(&st, DBUS_TYPE_STRING, &s);
|
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(&st, DBUS_TYPE_VARIANT, "(sa{sv}av)", &alv);
|
||||||
dbus_message_iter_open_container(&alv, DBUS_TYPE_STRUCT, nil, &ali);
|
dbus_message_iter_open_container(&alv, DBUS_TYPE_STRUCT, nil, &ali);
|
||||||
dbus_message_iter_append_basic(&ali, DBUS_TYPE_STRING, &aname);
|
dbus_message_iter_append_basic(&ali, DBUS_TYPE_STRING, &aname);
|
||||||
dbus_message_iter_open_container(&ali, DBUS_TYPE_ARRAY, "{sv}", &attr);
|
emptydict(&ali);
|
||||||
dbus_message_iter_close_container(&ali, &attr);
|
|
||||||
dbus_message_iter_open_container(&ali, DBUS_TYPE_ARRAY, "v", &alist);
|
dbus_message_iter_open_container(&ali, DBUS_TYPE_ARRAY, "v", &alist);
|
||||||
if(underline && s[0] != '\0'){
|
if(underline && s[0] != '\0'){
|
||||||
type = Ibusattrunderline;
|
type = Ibusattrunderline;
|
||||||
@@ -410,9 +377,7 @@ appendibustext(DBusMessageIter *it, const char *s, int underline)
|
|||||||
"(sa{sv}uuuu)", &av);
|
"(sa{sv}uuuu)", &av);
|
||||||
dbus_message_iter_open_container(&av, DBUS_TYPE_STRUCT, nil, &ai);
|
dbus_message_iter_open_container(&av, DBUS_TYPE_STRUCT, nil, &ai);
|
||||||
dbus_message_iter_append_basic(&ai, DBUS_TYPE_STRING, &iname);
|
dbus_message_iter_append_basic(&ai, DBUS_TYPE_STRING, &iname);
|
||||||
dbus_message_iter_open_container(&ai, DBUS_TYPE_ARRAY, "{sv}",
|
emptydict(&ai);
|
||||||
&aattach);
|
|
||||||
dbus_message_iter_close_container(&ai, &aattach);
|
|
||||||
dbus_message_iter_append_basic(&ai, DBUS_TYPE_UINT32, &type);
|
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, &value);
|
||||||
dbus_message_iter_append_basic(&ai, DBUS_TYPE_UINT32, &start);
|
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);
|
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
|
static void
|
||||||
emitcommit(DBusConnection *c, const char *path, const char *text)
|
emitcommit(DBusConnection *c, const char *path, const char *text)
|
||||||
{
|
{
|
||||||
DBusMessage *sig;
|
DBusMessage *sig;
|
||||||
DBusMessageIter it;
|
DBusMessageIter it;
|
||||||
|
|
||||||
sig = dbus_message_new_signal(path, "org.freedesktop.IBus.InputContext", "CommitText");
|
sig = newsignal(path, "CommitText");
|
||||||
if(sig == nil)
|
|
||||||
return;
|
|
||||||
dbus_message_iter_init_append(sig, &it);
|
dbus_message_iter_init_append(sig, &it);
|
||||||
appendibustext(&it, text, 0);
|
appendibustext(&it, text, 0);
|
||||||
dbus_message_set_sender(sig, ibusowner);
|
|
||||||
dbus_connection_send(c, sig, nil);
|
dbus_connection_send(c, sig, nil);
|
||||||
dbus_message_unref(sig);
|
dbus_message_unref(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* preowner is the one context showing a preedit; clearing anyone else's is moot. */
|
||||||
static void
|
static void
|
||||||
emitpreedit(Ictx *ctx, const char *text)
|
emitpreedit(Ictx *ctx, const char *text)
|
||||||
{
|
{
|
||||||
@@ -450,14 +426,11 @@ emitpreedit(Ictx *ctx, const char *text)
|
|||||||
DBusMessageIter it;
|
DBusMessageIter it;
|
||||||
dbus_uint32_t cursor, mode;
|
dbus_uint32_t cursor, mode;
|
||||||
dbus_bool_t visible;
|
dbus_bool_t visible;
|
||||||
const char *name;
|
|
||||||
|
|
||||||
name = ctx->clientcommitpreedit ?
|
if(text[0] == '\0' && preowner != ctx)
|
||||||
"UpdatePreeditTextWithMode" : "UpdatePreeditText";
|
|
||||||
sig = dbus_message_new_signal(ctx->path,
|
|
||||||
"org.freedesktop.IBus.InputContext", name);
|
|
||||||
if(sig == nil)
|
|
||||||
return;
|
return;
|
||||||
|
sig = newsignal(ctx->path, ctx->clientcommitpreedit ?
|
||||||
|
"UpdatePreeditTextWithMode" : "UpdatePreeditText");
|
||||||
dbus_message_iter_init_append(sig, &it);
|
dbus_message_iter_init_append(sig, &it);
|
||||||
appendibustext(&it, text, 1);
|
appendibustext(&it, text, 1);
|
||||||
cursor = utflen((char*)text);
|
cursor = utflen((char*)text);
|
||||||
@@ -468,7 +441,6 @@ emitpreedit(Ictx *ctx, const char *text)
|
|||||||
mode = Ibuspreeditclear;
|
mode = Ibuspreeditclear;
|
||||||
dbus_message_iter_append_basic(&it, DBUS_TYPE_UINT32, &mode);
|
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(dbus_connection_send(ctx->conn, sig, nil)){
|
||||||
if(text[0] != '\0')
|
if(text[0] != '\0')
|
||||||
preowner = ctx;
|
preowner = ctx;
|
||||||
@@ -478,6 +450,7 @@ emitpreedit(Ictx *ctx, const char *text)
|
|||||||
dbus_message_unref(sig);
|
dbus_message_unref(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Another frontend may have taken the engine; then our preedit is stale. */
|
||||||
static void
|
static void
|
||||||
checkpreowner(void)
|
checkpreowner(void)
|
||||||
{
|
{
|
||||||
@@ -492,10 +465,62 @@ checkpreowner(void)
|
|||||||
emitpreedit(ctx, "");
|
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
|
static DBusHandlerResult
|
||||||
handlehello(DBusConnection *c, DBusMessage *m)
|
handlehello(DBusConnection *c, DBusMessage *m)
|
||||||
{
|
{
|
||||||
DBusMessage *r;
|
|
||||||
char name[32];
|
char name[32];
|
||||||
const char *np;
|
const char *np;
|
||||||
|
|
||||||
@@ -505,122 +530,66 @@ handlehello(DBusConnection *c, DBusMessage *m)
|
|||||||
busctr++;
|
busctr++;
|
||||||
snprintf(name, sizeof(name), ":1.%d", busctr);
|
snprintf(name, sizeof(name), ":1.%d", busctr);
|
||||||
np = name;
|
np = name;
|
||||||
r = dbus_message_new_method_return(m);
|
return reply(c, m, DBUS_TYPE_STRING, &np);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static DBusHandlerResult
|
static DBusHandlerResult
|
||||||
handlenameowner(DBusConnection *c, DBusMessage *m)
|
handlenameowner(DBusConnection *c, DBusMessage *m)
|
||||||
{
|
{
|
||||||
DBusError err;
|
|
||||||
DBusMessage *r;
|
|
||||||
const char *name, *owner;
|
const char *name, *owner;
|
||||||
|
|
||||||
dbus_error_init(&err);
|
if(!dbus_message_get_args(m, nil, DBUS_TYPE_STRING, &name,
|
||||||
if(!dbus_message_get_args(m, &err, DBUS_TYPE_STRING, &name,
|
DBUS_TYPE_INVALID))
|
||||||
DBUS_TYPE_INVALID)){
|
|
||||||
dbus_error_free(&err);
|
|
||||||
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
||||||
"GetNameOwner expects one bus name");
|
"GetNameOwner expects one bus name");
|
||||||
}
|
|
||||||
if(strcmp(name, "org.freedesktop.IBus") != 0)
|
if(strcmp(name, "org.freedesktop.IBus") != 0)
|
||||||
return handleerror(c, m, DBUS_ERROR_NAME_HAS_NO_OWNER,
|
return handleerror(c, m, DBUS_ERROR_NAME_HAS_NO_OWNER,
|
||||||
"bus name has no owner");
|
"bus name has no owner");
|
||||||
owner = ibusowner;
|
owner = ibusowner;
|
||||||
r = dbus_message_new_method_return(m);
|
return reply(c, m, DBUS_TYPE_STRING, &owner);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static DBusHandlerResult
|
static DBusHandlerResult
|
||||||
handlecreate(DBusConnection *c, DBusMessage *m)
|
handlecreate(DBusConnection *c, DBusMessage *m)
|
||||||
{
|
{
|
||||||
DBusMessage *r;
|
|
||||||
char path[64];
|
char path[64];
|
||||||
const char *pp;
|
const char *pp;
|
||||||
Ictx *ctx;
|
Ictx *ctx;
|
||||||
int n;
|
|
||||||
|
|
||||||
if(!dbus_message_has_signature(m, "s"))
|
if(!dbus_message_has_signature(m, "s"))
|
||||||
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
||||||
"CreateInputContext expects one client name");
|
"CreateInputContext expects one client name");
|
||||||
icctr++;
|
icctr++;
|
||||||
n = snprintf(path, sizeof(path),
|
snprintf(path, sizeof(path),
|
||||||
"/org/freedesktop/IBus/InputContext_%d", icctr);
|
"/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);
|
ctx = newcontext(c, path);
|
||||||
if(ctx == nil)
|
if(ctx == nil)
|
||||||
return handleerror(c, m, DBUS_ERROR_LIMITS_EXCEEDED,
|
return handleerror(c, m, DBUS_ERROR_LIMITS_EXCEEDED,
|
||||||
"too many input contexts");
|
"too many input contexts");
|
||||||
pp = path;
|
pp = path;
|
||||||
r = dbus_message_new_method_return(m);
|
return reply(c, m, DBUS_TYPE_OBJECT_PATH, &pp);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static DBusHandlerResult
|
static DBusHandlerResult
|
||||||
handlekey(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
handlekey(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
||||||
{
|
{
|
||||||
DBusError err;
|
|
||||||
dbus_uint32_t sym, code, state;
|
dbus_uint32_t sym, code, state;
|
||||||
Keyres res;
|
Keyres res;
|
||||||
char commit[Maxutf], preedit[Maxutf];
|
char commit[Maxutf], preedit[Maxutf];
|
||||||
int restart;
|
int restart;
|
||||||
|
|
||||||
dbus_error_init(&err);
|
if(!dbus_message_get_args(m, nil,
|
||||||
if(!dbus_message_get_args(m, &err,
|
|
||||||
DBUS_TYPE_UINT32, &sym,
|
DBUS_TYPE_UINT32, &sym,
|
||||||
DBUS_TYPE_UINT32, &code,
|
DBUS_TYPE_UINT32, &code,
|
||||||
DBUS_TYPE_UINT32, &state,
|
DBUS_TYPE_UINT32, &state,
|
||||||
DBUS_TYPE_INVALID)){
|
DBUS_TYPE_INVALID))
|
||||||
dbus_error_free(&err);
|
|
||||||
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
||||||
"ProcessKeyEvent expects three unsigned integers");
|
"ProcessKeyEvent expects three unsigned integers");
|
||||||
}
|
|
||||||
USED(code);
|
|
||||||
if(!processkey(ctx, sym, state, &res))
|
if(!processkey(ctx, sym, state, &res))
|
||||||
return handlebool(c, m, 0);
|
return replybool(c, m, 0);
|
||||||
stoutf(&res.commit, commit, sizeof commit);
|
stoutf(&res.commit, commit, sizeof commit);
|
||||||
stoutf(&res.preedit, preedit, sizeof preedit);
|
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;
|
restart = clientpreedit(ctx) && commit[0] != '\0' && preowner == ctx;
|
||||||
if(restart)
|
if(restart)
|
||||||
emitpreedit(ctx, "");
|
emitpreedit(ctx, "");
|
||||||
@@ -628,18 +597,7 @@ handlekey(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
|||||||
emitcommit(c, dbus_message_get_path(m), commit);
|
emitcommit(c, dbus_message_get_path(m), commit);
|
||||||
if(clientpreedit(ctx) && (!restart || preedit[0] != '\0'))
|
if(clientpreedit(ctx) && (!restart || preedit[0] != '\0'))
|
||||||
emitpreedit(ctx, preedit);
|
emitpreedit(ctx, preedit);
|
||||||
return handlebool(c, m, res.eaten);
|
return replybool(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static DBusHandlerResult
|
static DBusHandlerResult
|
||||||
@@ -650,14 +608,14 @@ handlereset(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
|||||||
sendrequest(ctx, Keyreset, 0, 0, &res);
|
sendrequest(ctx, Keyreset, 0, 0, &res);
|
||||||
if(clientpreedit(ctx))
|
if(clientpreedit(ctx))
|
||||||
emitpreedit(ctx, "");
|
emitpreedit(ctx, "");
|
||||||
return handlenoop(c, m);
|
return reply(c, m, DBUS_TYPE_INVALID, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DBusHandlerResult
|
static DBusHandlerResult
|
||||||
handlefocusin(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
handlefocusin(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
||||||
{
|
{
|
||||||
ctx->focused = 1;
|
ctx->focused = 1;
|
||||||
return handlenoop(c, m);
|
return reply(c, m, DBUS_TYPE_INVALID, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DBusHandlerResult
|
static DBusHandlerResult
|
||||||
@@ -666,25 +624,21 @@ handlefocusout(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
|||||||
releasecontext(ctx);
|
releasecontext(ctx);
|
||||||
if(clientpreedit(ctx))
|
if(clientpreedit(ctx))
|
||||||
emitpreedit(ctx, "");
|
emitpreedit(ctx, "");
|
||||||
return handlenoop(c, m);
|
return reply(c, m, DBUS_TYPE_INVALID, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DBusHandlerResult
|
static DBusHandlerResult
|
||||||
handlecap(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
handlecap(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
||||||
{
|
{
|
||||||
DBusError err;
|
|
||||||
dbus_uint32_t cap;
|
dbus_uint32_t cap;
|
||||||
Keyres res;
|
Keyres res;
|
||||||
char preedit[Maxutf];
|
char preedit[Maxutf];
|
||||||
u32int old;
|
u32int old;
|
||||||
|
|
||||||
dbus_error_init(&err);
|
if(!dbus_message_get_args(m, nil, DBUS_TYPE_UINT32, &cap,
|
||||||
if(!dbus_message_get_args(m, &err, DBUS_TYPE_UINT32, &cap,
|
DBUS_TYPE_INVALID))
|
||||||
DBUS_TYPE_INVALID)){
|
|
||||||
dbus_error_free(&err);
|
|
||||||
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
||||||
"SetCapabilities expects one unsigned integer");
|
"SetCapabilities expects one unsigned integer");
|
||||||
}
|
|
||||||
old = ctx->cap;
|
old = ctx->cap;
|
||||||
ctx->cap = cap;
|
ctx->cap = cap;
|
||||||
if(ctx->focused){
|
if(ctx->focused){
|
||||||
@@ -697,7 +651,7 @@ handlecap(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
|||||||
emitpreedit(ctx, "");
|
emitpreedit(ctx, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return handlenoop(c, m);
|
return reply(c, m, DBUS_TYPE_INVALID, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -740,6 +694,7 @@ getcontent(DBusMessageIter *value, u32int *purpose, u32int *hints)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Only ContentType and ClientCommitPreedit are settable; none is readable. */
|
||||||
static DBusHandlerResult
|
static DBusHandlerResult
|
||||||
handlepropertyset(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
handlepropertyset(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
||||||
{
|
{
|
||||||
@@ -768,7 +723,7 @@ handlepropertyset(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
|||||||
if(clientpreedit(ctx))
|
if(clientpreedit(ctx))
|
||||||
emitpreedit(ctx, "");
|
emitpreedit(ctx, "");
|
||||||
}
|
}
|
||||||
return handlenoop(c, m);
|
return reply(c, m, DBUS_TYPE_INVALID, nil);
|
||||||
}
|
}
|
||||||
if(strcmp(name, "ClientCommitPreedit") == 0){
|
if(strcmp(name, "ClientCommitPreedit") == 0){
|
||||||
if(dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_STRUCT)
|
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,
|
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
||||||
"ClientCommitPreedit expects (b)");
|
"ClientCommitPreedit expects (b)");
|
||||||
ctx->clientcommitpreedit = b != FALSE;
|
ctx->clientcommitpreedit = b != FALSE;
|
||||||
return handlenoop(c, m);
|
return reply(c, m, DBUS_TYPE_INVALID, nil);
|
||||||
}
|
}
|
||||||
return handleerror(c, m, DBUS_ERROR_UNKNOWN_PROPERTY,
|
return handleerror(c, m, DBUS_ERROR_UNKNOWN_PROPERTY,
|
||||||
"unknown input context property");
|
"unknown input context property");
|
||||||
}
|
}
|
||||||
|
|
||||||
static DBusHandlerResult
|
static DBusHandlerResult
|
||||||
handlepropertyget(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
handlepropertygetall(DBusConnection *c, DBusMessage *m)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
DBusMessage *r;
|
DBusMessage *r;
|
||||||
DBusMessageIter it, a;
|
DBusMessageIter it;
|
||||||
DBusError err;
|
|
||||||
const char *iface;
|
const char *iface;
|
||||||
|
|
||||||
USED(ctx);
|
if(!dbus_message_get_args(m, nil, DBUS_TYPE_STRING, &iface,
|
||||||
dbus_error_init(&err);
|
DBUS_TYPE_INVALID))
|
||||||
if(!dbus_message_get_args(m, &err, DBUS_TYPE_STRING, &iface,
|
|
||||||
DBUS_TYPE_INVALID)){
|
|
||||||
dbus_error_free(&err);
|
|
||||||
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
||||||
"Properties.GetAll expects an interface name");
|
"Properties.GetAll expects an interface name");
|
||||||
}
|
|
||||||
if(strcmp(iface, "org.freedesktop.IBus.InputContext") != 0)
|
if(strcmp(iface, "org.freedesktop.IBus.InputContext") != 0)
|
||||||
return handleerror(c, m, DBUS_ERROR_UNKNOWN_INTERFACE,
|
return handleerror(c, m, DBUS_ERROR_UNKNOWN_INTERFACE,
|
||||||
"unknown property interface");
|
"unknown property interface");
|
||||||
r = dbus_message_new_method_return(m);
|
r = dbus_message_new_method_return(m);
|
||||||
if(r == nil)
|
if(r == nil)
|
||||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
die("ibus: out of memory");
|
||||||
dbus_message_iter_init_append(r, &it);
|
dbus_message_iter_init_append(r, &it);
|
||||||
dbus_message_iter_open_container(&it, DBUS_TYPE_ARRAY, "{sv}", &a);
|
emptydict(&it);
|
||||||
dbus_message_iter_close_container(&it, &a);
|
|
||||||
dbus_connection_send(c, r, nil);
|
dbus_connection_send(c, r, nil);
|
||||||
dbus_message_unref(r);
|
dbus_message_unref(r);
|
||||||
return DBUS_HANDLER_RESULT_HANDLED;
|
return DBUS_HANDLER_RESULT_HANDLED;
|
||||||
@@ -846,99 +772,54 @@ static DBusHandlerResult
|
|||||||
handledestroy(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
handledestroy(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
||||||
{
|
{
|
||||||
dropcontext(ctx);
|
dropcontext(ctx);
|
||||||
return handlenoop(c, m);
|
return reply(c, m, DBUS_TYPE_INVALID, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DBusHandlerResult
|
static DBusHandlerResult
|
||||||
handlecursor(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
handlecursor(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
||||||
{
|
{
|
||||||
DBusError err;
|
|
||||||
dbus_int32_t x, y, w, h;
|
dbus_int32_t x, y, w, h;
|
||||||
|
|
||||||
dbus_error_init(&err);
|
if(!dbus_message_get_args(m, nil,
|
||||||
if(!dbus_message_get_args(m, &err,
|
|
||||||
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_INT32, &w, DBUS_TYPE_INT32, &h,
|
||||||
DBUS_TYPE_INVALID)){
|
DBUS_TYPE_INVALID))
|
||||||
dbus_error_free(&err);
|
|
||||||
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
||||||
"SetCursorLocation expects four integers");
|
"SetCursorLocation expects four integers");
|
||||||
}
|
|
||||||
if(w < 0 || h < 0)
|
if(w < 0 || h < 0)
|
||||||
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
||||||
"cursor dimensions must not be negative");
|
"cursor dimensions must not be negative");
|
||||||
setcursor(ctx, x, y, h);
|
setcursor(ctx, x, y, h);
|
||||||
return handlenoop(c, m);
|
return reply(c, m, DBUS_TYPE_INVALID, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char introspectxml[] =
|
/* Argument-free InputContext calls, checked for an empty signature. */
|
||||||
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
|
|
||||||
" \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
|
|
||||||
"<node>\n"
|
|
||||||
" <interface name=\"org.freedesktop.IBus\">\n"
|
|
||||||
" <method name=\"CreateInputContext\">\n"
|
|
||||||
" <arg direction=\"in\" type=\"s\"/>\n"
|
|
||||||
" <arg direction=\"out\" type=\"o\"/>\n"
|
|
||||||
" </method>\n"
|
|
||||||
" </interface>\n"
|
|
||||||
" <interface name=\"org.freedesktop.IBus.InputContext\">\n"
|
|
||||||
" <method name=\"ProcessKeyEvent\">\n"
|
|
||||||
" <arg direction=\"in\" type=\"u\"/>\n"
|
|
||||||
" <arg direction=\"in\" type=\"u\"/>\n"
|
|
||||||
" <arg direction=\"in\" type=\"u\"/>\n"
|
|
||||||
" <arg direction=\"out\" type=\"b\"/>\n"
|
|
||||||
" </method>\n"
|
|
||||||
" <method name=\"FocusIn\"/>\n"
|
|
||||||
" <method name=\"FocusOut\"/>\n"
|
|
||||||
" <method name=\"Reset\"/>\n"
|
|
||||||
" <method name=\"Destroy\"/>\n"
|
|
||||||
" <method name=\"SetCapabilities\"><arg direction=\"in\" type=\"u\"/></method>\n"
|
|
||||||
" <method name=\"SetCursorLocation\">"
|
|
||||||
"<arg direction=\"in\" type=\"i\"/><arg direction=\"in\" type=\"i\"/>"
|
|
||||||
"<arg direction=\"in\" type=\"i\"/><arg direction=\"in\" type=\"i\"/></method>\n"
|
|
||||||
" <method name=\"SetEngine\"><arg direction=\"in\" type=\"s\"/></method>\n"
|
|
||||||
" <property name=\"ContentType\" type=\"(uu)\" access=\"write\"/>\n"
|
|
||||||
" <property name=\"ClientCommitPreedit\" type=\"(b)\" access=\"write\"/>\n"
|
|
||||||
" <signal name=\"CommitText\"><arg type=\"v\"/></signal>\n"
|
|
||||||
" <signal name=\"UpdatePreeditText\">"
|
|
||||||
"<arg type=\"v\"/><arg type=\"u\"/><arg type=\"b\"/></signal>\n"
|
|
||||||
" <signal name=\"UpdatePreeditTextWithMode\">"
|
|
||||||
"<arg type=\"v\"/><arg type=\"u\"/><arg type=\"b\"/>"
|
|
||||||
"<arg type=\"u\"/></signal>\n"
|
|
||||||
" </interface>\n"
|
|
||||||
" <interface name=\"org.freedesktop.DBus.Properties\">\n"
|
|
||||||
" <method name=\"Get\"><arg direction=\"in\" type=\"s\"/>"
|
|
||||||
"<arg direction=\"in\" type=\"s\"/><arg direction=\"out\" type=\"v\"/></method>\n"
|
|
||||||
" <method name=\"Set\"><arg direction=\"in\" type=\"s\"/>"
|
|
||||||
"<arg direction=\"in\" type=\"s\"/><arg direction=\"in\" type=\"v\"/></method>\n"
|
|
||||||
" <method name=\"GetAll\"><arg direction=\"in\" type=\"s\"/>"
|
|
||||||
"<arg direction=\"out\" type=\"a{sv}\"/></method>\n"
|
|
||||||
" </interface>\n"
|
|
||||||
"</node>\n";
|
|
||||||
|
|
||||||
static DBusHandlerResult
|
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, ""))
|
if(!dbus_message_has_signature(m, ""))
|
||||||
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
||||||
"Introspect expects no arguments");
|
"this call takes no arguments");
|
||||||
r = dbus_message_new_method_return(m);
|
if(strcmp(member, "FocusIn") == 0)
|
||||||
dbus_message_append_args(r, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID);
|
return handlefocusin(c, m, ctx);
|
||||||
dbus_connection_send(c, r, nil);
|
if(strcmp(member, "FocusOut") == 0)
|
||||||
dbus_message_unref(r);
|
return handlefocusout(c, m, ctx);
|
||||||
return DBUS_HANDLER_RESULT_HANDLED;
|
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
|
static DBusHandlerResult
|
||||||
onmsg(DBusConnection *c, DBusMessage *m, void *_)
|
onmsg(DBusConnection *c, DBusMessage *m, void*)
|
||||||
{
|
{
|
||||||
const char *iface, *member, *path;
|
const char *iface, *member, *path;
|
||||||
Ictx *ctx;
|
Ictx *ctx;
|
||||||
|
|
||||||
USED(_);
|
|
||||||
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;
|
||||||
iface = dbus_message_get_interface(m);
|
iface = dbus_message_get_interface(m);
|
||||||
@@ -946,9 +827,6 @@ onmsg(DBusConnection *c, DBusMessage *m, void *_)
|
|||||||
path = dbus_message_get_path(m);
|
path = dbus_message_get_path(m);
|
||||||
if(iface == nil || member == nil || path == nil)
|
if(iface == nil || member == nil || path == nil)
|
||||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
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(iface, "org.freedesktop.DBus") == 0){
|
||||||
if(strcmp(member, "Hello") == 0)
|
if(strcmp(member, "Hello") == 0)
|
||||||
return handlehello(c, m);
|
return handlehello(c, m);
|
||||||
@@ -959,7 +837,7 @@ onmsg(DBusConnection *c, DBusMessage *m, void *_)
|
|||||||
if(!dbus_message_has_signature(m, "s"))
|
if(!dbus_message_has_signature(m, "s"))
|
||||||
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
||||||
"match rule must be one string");
|
"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){
|
if(strcmp(iface, "org.freedesktop.IBus") == 0){
|
||||||
@@ -967,16 +845,16 @@ onmsg(DBusConnection *c, DBusMessage *m, void *_)
|
|||||||
return handlecreate(c, m);
|
return handlecreate(c, m);
|
||||||
}
|
}
|
||||||
if(strcmp(iface, "org.freedesktop.DBus.Properties") == 0){
|
if(strcmp(iface, "org.freedesktop.DBus.Properties") == 0){
|
||||||
ctx = findcontext(c, path);
|
if(findcontext(c, path) == 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, "Set") == 0)
|
if(strcmp(member, "Set") == 0)
|
||||||
return handlepropertyset(c, m, ctx);
|
return handlepropertyset(c, m, findcontext(c, path));
|
||||||
if(strcmp(member, "Get") == 0)
|
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)
|
if(strcmp(member, "GetAll") == 0)
|
||||||
return handlepropertygetall(c, m, ctx);
|
return handlepropertygetall(c, m);
|
||||||
}
|
}
|
||||||
if(strcmp(iface, "org.freedesktop.IBus.InputContext") == 0){
|
if(strcmp(iface, "org.freedesktop.IBus.InputContext") == 0){
|
||||||
ctx = findcontext(c, path);
|
ctx = findcontext(c, path);
|
||||||
@@ -985,30 +863,11 @@ onmsg(DBusConnection *c, DBusMessage *m, void *_)
|
|||||||
"unknown input context");
|
"unknown input context");
|
||||||
if(strcmp(member, "ProcessKeyEvent") == 0)
|
if(strcmp(member, "ProcessKeyEvent") == 0)
|
||||||
return handlekey(c, m, ctx);
|
return handlekey(c, m, ctx);
|
||||||
if(strcmp(member, "FocusIn") == 0){
|
if(strcmp(member, "FocusIn") == 0 ||
|
||||||
if(!dbus_message_has_signature(m, ""))
|
strcmp(member, "FocusOut") == 0 ||
|
||||||
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
|
strcmp(member, "Reset") == 0 ||
|
||||||
"FocusIn expects no arguments");
|
strcmp(member, "Destroy") == 0)
|
||||||
return handlefocusin(c, m, ctx);
|
return handleplain(c, m, ctx, member);
|
||||||
}
|
|
||||||
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, "SetCursorLocation") == 0)
|
if(strcmp(member, "SetCursorLocation") == 0)
|
||||||
return handlecursor(c, m, ctx);
|
return handlecursor(c, m, ctx);
|
||||||
if(strcmp(member, "SetCapabilities") == 0)
|
if(strcmp(member, "SetCapabilities") == 0)
|
||||||
@@ -1017,7 +876,7 @@ onmsg(DBusConnection *c, DBusMessage *m, void *_)
|
|||||||
if(!dbus_message_has_signature(m, "s"))
|
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");
|
"SetEngine expects one engine name");
|
||||||
return handlenoop(c, m);
|
return reply(c, m, DBUS_TYPE_INVALID, nil);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||||
|
|||||||
@@ -358,7 +358,6 @@ ibus_private_input_policy(struct ct *t)
|
|||||||
{ Ibuspurposepassword, 0, 1 },
|
{ Ibuspurposepassword, 0, 1 },
|
||||||
{ Ibuspurposepin, 0, 1 },
|
{ Ibuspurposepin, 0, 1 },
|
||||||
{ 0, 1<<11, 0 },
|
{ 0, 1<<11, 0 },
|
||||||
{ 0, Ibushinthidden, 1 },
|
|
||||||
{ 37, 1<<20, 0 },
|
{ 37, 1<<20, 0 },
|
||||||
};
|
};
|
||||||
Ibusfix f;
|
Ibusfix f;
|
||||||
|
|||||||
Reference in New Issue
Block a user