ibus preedit

This commit is contained in:
2026-05-28 17:28:51 +09:00
parent 7629ec5fe8
commit daadd320f3

78
ibus.c
View File

@@ -200,47 +200,54 @@ mget(u32int state)
return m; return m;
} }
static int static void
sendkey(u32int ks, u32int mod, char *out, int sz, int *eaten) sendkey(u32int ks, u32int mod, char *com, int csz, char *pre, int psz,
int *eaten)
{ {
Keyreq kr; Keyreq kr;
int p[2]; int p[2];
uchar hdr[2]; uchar hdr[2];
uchar pl;
int n; int n;
*eaten = 0; *eaten = 0;
out[0] = '\0'; com[0] = '\0';
pre[0] = '\0';
if(pipe(p) < 0) if(pipe(p) < 0)
return 0; return;
kr.fd = p[1]; kr.fd = p[1];
kr.ks = ks; kr.ks = ks;
kr.mod = mod; kr.mod = mod;
kr.want = 1;
chansend(keyc, &kr); chansend(keyc, &kr);
if(read(p[0], hdr, 2) != 2){ if(read(p[0], hdr, 2) != 2)
close(p[0]); goto out;
close(p[1]);
return 0;
}
*eaten = hdr[0]; *eaten = hdr[0];
n = hdr[1]; n = hdr[1];
if(n > 0 && n < sz){ if(n > 0 && n < csz){
if(read(p[0], out, n) != n) if(read(p[0], com, n) != n)
n = 0; goto out;
}else com[n] = '\0';
n = 0; }
out[n] = '\0'; if(read(p[0], &pl, 1) != 1)
goto out;
if(pl > 0 && pl < psz){
if(read(p[0], pre, pl) != pl)
goto out;
pre[pl] = '\0';
}
out:
close(p[0]); close(p[0]);
close(p[1]); close(p[1]);
return n;
} }
static void static void
sendreset(void) sendreset(void)
{ {
char buf[64]; char com[64], pre[256];
int eaten; int eaten;
sendkey(Kesc, 0, buf, sizeof(buf), &eaten); sendkey(Kesc, 0, com, sizeof(com), pre, sizeof(pre), &eaten);
} }
static void static void
@@ -284,6 +291,28 @@ emitcommit(DBusConnection *c, const char *path, const char *text)
dbus_message_unref(sig); dbus_message_unref(sig);
} }
static void
emitpreedit(DBusConnection *c, const char *path, const char *text)
{
DBusMessage *sig;
DBusMessageIter it;
dbus_uint32_t cursor;
dbus_bool_t visible;
sig = dbus_message_new_signal(path,
"org.freedesktop.IBus.InputContext", "UpdatePreeditText");
if(sig == nil)
return;
dbus_message_iter_init_append(sig, &it);
appendibustext(&it, text);
cursor = utflen(text);
visible = text[0] != '\0' ? TRUE : FALSE;
dbus_message_iter_append_basic(&it, DBUS_TYPE_UINT32, &cursor);
dbus_message_iter_append_basic(&it, DBUS_TYPE_BOOLEAN, &visible);
dbus_connection_send(c, sig, nil);
dbus_message_unref(sig);
}
static DBusHandlerResult static DBusHandlerResult
handlehello(DBusConnection *c, DBusMessage *m) handlehello(DBusConnection *c, DBusMessage *m)
{ {
@@ -324,8 +353,8 @@ handlekey(DBusConnection *c, DBusMessage *m)
DBusMessage *r; DBusMessage *r;
DBusError err; DBusError err;
dbus_uint32_t sym, code, state; dbus_uint32_t sym, code, state;
char commit[256]; char commit[256], preedit[256];
int eaten, n; int eaten;
dbus_bool_t b; dbus_bool_t b;
u32int ks, mod; u32int ks, mod;
@@ -349,9 +378,11 @@ handlekey(DBusConnection *c, DBusMessage *m)
} }
ks = kget(sym); ks = kget(sym);
mod = mget(state); mod = mget(state);
n = sendkey(ks, mod, commit, sizeof(commit), &eaten); sendkey(ks, mod, commit, sizeof(commit), preedit, sizeof(preedit),
if(n > 0) &eaten);
if(commit[0] != '\0')
emitcommit(c, dbus_message_get_path(m), commit); emitcommit(c, dbus_message_get_path(m), commit);
emitpreedit(c, dbus_message_get_path(m), preedit);
r = dbus_message_new_method_return(m); r = dbus_message_new_method_return(m);
b = eaten ? TRUE : FALSE; b = eaten ? TRUE : FALSE;
dbus_message_append_args(r, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID); dbus_message_append_args(r, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
@@ -375,6 +406,7 @@ static DBusHandlerResult
handlereset(DBusConnection *c, DBusMessage *m) handlereset(DBusConnection *c, DBusMessage *m)
{ {
sendreset(); sendreset();
emitpreedit(c, dbus_message_get_path(m), "");
return handlenoop(c, m); return handlenoop(c, m);
} }
@@ -405,6 +437,8 @@ static const char introspectxml[] =
"<arg direction=\"in\" type=\"i\"/><arg direction=\"in\" type=\"i\"/></method>\n" "<arg direction=\"in\" type=\"i\"/><arg direction=\"in\" type=\"i\"/></method>\n"
" <method name=\"SetEngine\"><arg direction=\"in\" type=\"s\"/></method>\n" " <method name=\"SetEngine\"><arg direction=\"in\" type=\"s\"/></method>\n"
" <signal name=\"CommitText\"><arg type=\"v\"/></signal>\n" " <signal name=\"CommitText\"><arg type=\"v\"/></signal>\n"
" <signal name=\"UpdatePreeditText\">"
"<arg type=\"v\"/><arg type=\"u\"/><arg type=\"b\"/></signal>\n"
" </interface>\n" " </interface>\n"
"</node>\n"; "</node>\n";