ipc: negotiate preedit capability and caret messages

This commit is contained in:
2026-08-14 18:53:14 +09:00
parent b536573622
commit 6a58b63223
7 changed files with 538 additions and 17 deletions

71
srv.c
View File

@@ -8,20 +8,46 @@ static char adir[256];
static Channel *clientc;
static int
srvreadkey(int fd, Keyreq *kr)
srvreadreq(int fd, Keyreq *kr, int *want)
{
uchar req[Ipcreqsz];
uchar req[Ipccaretsz];
int type, valid;
int32_t x, y, h;
u32int ks, mod;
int want;
if(ipcreadn(fd, req, sizeof req) < 0)
if(ipcreadn(fd, req, Ipcreqsz) < 0)
return -1;
ipcunpackreq(req, &want, &mod, &ks);
kr->op = ipcreqreset(req) ? Keyreset : Keypress;
kr->ks = ks;
kr->mod = mod;
memset(&kr->caret, 0, sizeof kr->caret);
return want;
type = ipcreqtype(req);
switch(type){
case Ipclegacy:
ipcunpackreq(req, want, &mod, &ks);
kr->op = ipcreqreset(req) ? Keyreset : Keypress;
kr->ks = ks;
kr->mod = mod;
break;
case Ipccap:
*want = (req[0] & Ipcreqwant) != 0;
kr->op = Keycap;
kr->ks = 0;
kr->mod = 0;
break;
case Ipccaret:
if(ipcreadn(fd, req + Ipcreqsz, Ipccaretsz - Ipcreqsz) < 0 ||
ipcunpackcaret(req, &valid, &x, &y, &h) < 0)
return -1;
*want = 0;
kr->op = Keycaret;
kr->ks = 0;
kr->mod = 0;
kr->caret.valid = valid;
kr->caret.x = x;
kr->caret.y = y;
kr->caret.h = h;
break;
default:
return -1;
}
return type;
}
static void
@@ -31,9 +57,10 @@ clientthread(void *arg)
int fd;
Keyreq kr;
Keyres res;
Caret caret;
uchar out[Ipcmaxresp];
char commit[Maxutf], preedit[Maxutf];
int n, ncommit, npreedit, want;
int cap, n, ncommit, npreedit, type, want;
uchar token;
fd = (int)(uintptr)arg;
@@ -41,18 +68,34 @@ clientthread(void *arg)
reply = chancreate(sizeof(Keyres), 0);
kr.reply = reply;
kr.owner = &fd;
kr.cap = Cclientpreedit;
while((want = srvreadkey(fd, &kr)) >= 0){
cap = Cclientpreedit;
memset(&caret, 0, sizeof caret);
kr.cap = cap;
kr.caret = caret;
while((type = srvreadreq(fd, &kr, &want)) >= 0){
if(type == Ipccap)
cap = want ? Cclientpreedit : 0;
else if(type == Ipccaret)
caret = kr.caret;
kr.cap = cap;
kr.caret = caret;
chansend(keyc, &kr);
chanrecv(reply, &res);
if(type == Ipccaret)
continue;
ncommit = stoutf(&res.commit, commit, sizeof commit);
npreedit = stoutf(&res.preedit, preedit, sizeof preedit);
n = ipcpackresp(out, sizeof out, res.eaten,
n = ipcpackresp(out, sizeof out,
type == Ipccap ? 1 : res.eaten,
commit, ncommit, preedit, npreedit, want);
if(n < 0 || ipcsend(fd, out, n) < 0)
break;
}
kr.op = Keyrelease;
kr.cap = cap;
kr.caret = caret;
kr.ks = 0;
kr.mod = 0;
chansend(keyc, &kr);
chanrecv(reply, &res);
chanfree(reply);