fix(xim): honor reset and X11 keyboard state
This commit is contained in:
@@ -614,46 +614,6 @@ waitcommit(Display *dpy, XIC ic, char *commit, size_t cap)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rawtakeover(void)
|
||||
{
|
||||
unsigned char req[Ipcreqsz];
|
||||
char commit[Ipcfieldmax+1], preedit[Ipcfieldmax+1];
|
||||
Ipcresp resp;
|
||||
struct timeval tv;
|
||||
int fd;
|
||||
|
||||
fd = ipcconnect();
|
||||
if(fd < 0)
|
||||
return fail("connect raw IPC owner: %s", strerror(errno));
|
||||
tv.tv_sec = Eventtimeout / 1000;
|
||||
tv.tv_usec = (Eventtimeout % 1000) * 1000;
|
||||
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv);
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv);
|
||||
ipcpackreq(req, 0, 0, 'z');
|
||||
if(ipcsend(fd, req, sizeof req) < 0 ||
|
||||
ipcreadresp(fd, 0, commit, sizeof commit,
|
||||
preedit, sizeof preedit, &resp) < 0){
|
||||
close(fd);
|
||||
return fail("raw IPC ownership transfer: %s", strerror(errno));
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int
|
||||
waitclear(Display *dpy, Prelog *p, int empty, int done)
|
||||
{
|
||||
int64_t deadline;
|
||||
|
||||
deadline = nowms() + Eventtimeout;
|
||||
while(leftms(deadline) > 0){
|
||||
pump(dpy, leftms(deadline));
|
||||
if(p->empty >= empty && p->done >= done)
|
||||
return 1;
|
||||
}
|
||||
return fail("timed out waiting for empty DRAW and DONE");
|
||||
}
|
||||
|
||||
static int
|
||||
waitpreedit(Display *dpy, Prelog *p)
|
||||
{
|
||||
@@ -692,7 +652,6 @@ testcallbacks(Display *dpy, XIM im, Window win)
|
||||
char commit[Ipcfieldmax+1], *reset;
|
||||
Prelog log;
|
||||
XIC ic;
|
||||
int fd, empty, done;
|
||||
|
||||
memset(&log, 0, sizeof log);
|
||||
ic = callbackic(im, win, &log);
|
||||
@@ -730,42 +689,33 @@ testcallbacks(Display *dpy, XIM im, Window win)
|
||||
return fail("bad initial callback sequence: start=%d draw=%d empty=%d done=%d ordered=%d bad=%d",
|
||||
start, draw, empty, done, ordered, bad);
|
||||
}
|
||||
empty = log.empty;
|
||||
done = log.done;
|
||||
fd = rawtakeover();
|
||||
if(fd < 0){
|
||||
XDestroyIC(ic);
|
||||
return 0;
|
||||
}
|
||||
if(!waitclear(dpy, &log, empty + 1, done + 1)){
|
||||
close(fd);
|
||||
XDestroyIC(ic);
|
||||
return 0;
|
||||
}
|
||||
/* Leave the live IC time to expose a delayed duplicate transfer clear. */
|
||||
pump(dpy, 100);
|
||||
if(log.empty != empty + 1 || log.done != done + 1 ||
|
||||
log.doneafterempty != 1 || log.badorder != 0){
|
||||
int gotempty, gotdone, ordered;
|
||||
|
||||
gotempty = log.empty - empty;
|
||||
gotdone = log.done - done;
|
||||
ordered = log.doneafterempty;
|
||||
close(fd);
|
||||
XDestroyIC(ic);
|
||||
return fail("owner loss callback counts: empty=%d done=%d ordered=%d",
|
||||
gotempty, gotdone, ordered);
|
||||
}
|
||||
reset = Xutf8ResetIC(ic);
|
||||
if(reset != NULL)
|
||||
XFree(reset);
|
||||
if(reset == NULL || strcmp(reset, "ㄱ") != 0){
|
||||
if(reset != NULL)
|
||||
XFree(reset);
|
||||
XDestroyIC(ic);
|
||||
return fail("ResetIC did not return pending preedit");
|
||||
}
|
||||
XFree(reset);
|
||||
if(!sendkey(dpy, ic, win, XK_r, 0, commit, sizeof commit) ||
|
||||
!sendkey(dpy, ic, win, XK_k, 0, commit, sizeof commit) ||
|
||||
!sendkey(dpy, ic, win, XK_Return, 0, commit, sizeof commit)){
|
||||
XDestroyIC(ic);
|
||||
return 0;
|
||||
}
|
||||
if(commit[0] == '\0' && !waitcommit(dpy, ic, commit, sizeof commit)){
|
||||
XDestroyIC(ic);
|
||||
return fail("input context did not compose after ResetIC");
|
||||
}
|
||||
if(strcmp(commit, "가") != 0){
|
||||
XDestroyIC(ic);
|
||||
return fail("post-reset composition did not contain 가");
|
||||
}
|
||||
XUnsetICFocus(ic);
|
||||
XDestroyIC(ic);
|
||||
pump(dpy, 100);
|
||||
close(fd);
|
||||
pump(dpy, 100);
|
||||
if(log.empty != empty + 1 || log.done != done + 1)
|
||||
return fail("late lifecycle produced duplicate clear callbacks");
|
||||
if(log.badorder != 0)
|
||||
return fail("bad callback order after ResetIC");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user