fix(frontends): preserve preedit lifecycle

This commit is contained in:
2026-08-15 15:05:49 +09:00
parent aeb6010f3c
commit d29d43f443
6 changed files with 164 additions and 46 deletions

View File

@@ -50,7 +50,7 @@ setpreedit(Im *im, const char *s, int n)
if(n < 0 || n > Ipcfieldmax)
n = 0;
if(n == im->prelen && memcmp(im->pre, s, n) == 0)
if(n == 0 && im->prelen == 0)
return;
was = im->prelen;
if(n > 0)
@@ -94,12 +94,10 @@ validtext(const char *s, size_t n)
}
static int
readresp(Im *im, int want, int update, char *commit, int ncommit,
readresp(Im *im, int want, char *commit, int ncommit, char *pre, int npre,
Ipcresp *resp)
{
char pre[Ipcfieldmax+1];
if(ipcreadresp(im->fd, want, commit, ncommit, pre, sizeof pre,
if(ipcreadresp(im->fd, want, commit, ncommit, pre, npre,
resp) < 0)
return -1;
if(!validtext(commit, resp->commitlen) ||
@@ -107,8 +105,6 @@ readresp(Im *im, int want, int update, char *commit, int ncommit,
errno = EPROTO;
return -1;
}
if(update)
setpreedit(im, pre, resp->preeditlen);
return 0;
}
@@ -199,6 +195,7 @@ srvconnect(Im *im)
{
unsigned char buf[Ipcreqsz];
char commit[Ipcfieldmax+1];
char pre[Ipcfieldmax+1];
Ipcresp resp;
if(im->fd >= 0)
@@ -209,11 +206,13 @@ srvconnect(Im *im)
/* Marker zero is an old daemon's harmless key-zero response. */
ipcpackcap(buf, im->usepreedit);
if(ipcsend(im->fd, buf, sizeof buf) < 0 ||
readresp(im, im->usepreedit, im->usepreedit, commit,
sizeof commit, &resp) < 0){
readresp(im, im->usepreedit, commit, sizeof commit,
pre, sizeof pre, &resp) < 0){
srvclose(im);
return -1;
}
if(im->usepreedit)
setpreedit(im, pre, resp.preeditlen);
im->ext = resp.eaten != 0;
if(!im->usepreedit)
setpreedit(im, "", 0);
@@ -293,6 +292,7 @@ sendreset(Im *im)
{
unsigned char buf[Ipcreqsz];
char commit[Ipcfieldmax+1];
char pre[Ipcfieldmax+1];
Ipcresp resp;
if(im->fd < 0){
@@ -301,8 +301,8 @@ sendreset(Im *im)
}
ipcpackreset(buf, im->usepreedit);
if(ipcsend(im->fd, buf, sizeof buf) < 0 ||
readresp(im, im->usepreedit, 0, commit,
sizeof commit, &resp) < 0){
readresp(im, im->usepreedit, commit, sizeof commit,
pre, sizeof pre, &resp) < 0){
srvclose(im);
return;
}
@@ -315,6 +315,7 @@ kpress(GtkIMContext *ctx, GdkEventKey *ev)
Im *im;
unsigned char buf[Ipcreqsz];
char commit[Ipcfieldmax+1];
char pre[Ipcfieldmax+1];
uint32_t key, mod;
Ipcresp resp;
@@ -339,13 +340,15 @@ kpress(GtkIMContext *ctx, GdkEventKey *ev)
}
ipcpackreq(buf, im->usepreedit, mod, key);
if(ipcsend(im->fd, buf, sizeof buf) < 0 ||
readresp(im, im->usepreedit, im->usepreedit, commit,
sizeof commit, &resp) < 0){
readresp(im, im->usepreedit, commit, sizeof commit,
pre, sizeof pre, &resp) < 0){
srvclose(im);
return simplefilter(ctx, ev, 0);
}
if(commit[0] != '\0')
g_signal_emit_by_name(ctx, "commit", commit);
if(im->usepreedit)
setpreedit(im, pre, resp.preeditlen);
if(resp.eaten)
return TRUE;
return simplefilter(ctx, ev, 0);
@@ -407,6 +410,7 @@ setusepreedit(GtkIMContext *ctx, gboolean use)
Im *im;
unsigned char buf[Ipcreqsz];
char commit[Ipcfieldmax+1];
char pre[Ipcfieldmax+1];
Ipcresp resp;
im = (Im*)ctx;
@@ -422,11 +426,14 @@ setusepreedit(GtkIMContext *ctx, gboolean use)
return;
ipcpackcap(buf, use);
if(ipcsend(im->fd, buf, sizeof buf) < 0 ||
readresp(im, use, use, commit, sizeof commit, &resp) < 0 ||
readresp(im, use, commit, sizeof commit,
pre, sizeof pre, &resp) < 0 ||
!resp.eaten){
srvclose(im);
return;
}
if(use)
setpreedit(im, pre, resp.preeditlen);
}
static void