xim: clear callback preedit on owner loss
This commit is contained in:
@@ -659,7 +659,7 @@ xim_adapter_placement(struct ct *t)
|
||||
{XCB_IM_PreeditPosition | XCB_IM_StatusNothing,
|
||||
XCB_XIM_XNSpotLocation_MASK, 1, 1, 1, 1, 1, 103, 204},
|
||||
{XCB_IM_PreeditPosition | XCB_IM_StatusNothing,
|
||||
XCB_XIM_XNSpotLocation_MASK, 1, 0, 1, 1, 1, 303, 404},
|
||||
XCB_XIM_XNSpotLocation_MASK, 1, 0, 1, 1, 1, 300, 440},
|
||||
{XCB_IM_PreeditPosition | XCB_IM_StatusNothing,
|
||||
0, 1, 1, 1, 1, 1, 100, 230},
|
||||
{XCB_IM_PreeditNothing | XCB_IM_StatusNothing,
|
||||
@@ -1022,6 +1022,110 @@ cleanup:
|
||||
ximend(&f);
|
||||
}
|
||||
|
||||
void
|
||||
xim_adapter_callback_owner_loss(struct ct *t)
|
||||
{
|
||||
Ximfix f;
|
||||
Ic state;
|
||||
xcb_im_input_context_t *ic;
|
||||
xcb_im_packet_header_fr_t hdr;
|
||||
Keyreq req;
|
||||
Keyreq trace;
|
||||
Keyres res;
|
||||
uchar token;
|
||||
int foreign, i, n;
|
||||
|
||||
ic = (xcb_im_input_context_t*)(uintptr)51;
|
||||
memset(&state, 0, sizeof state);
|
||||
foreign = 0;
|
||||
if(!ximbegin(t, &f, LangJP))
|
||||
goto cleanup;
|
||||
if(!CT_CHECK(t, wakeinit() == 0))
|
||||
goto cleanup;
|
||||
wakedrain();
|
||||
wireclear();
|
||||
wirebind(0, ic, &state);
|
||||
state.xic = ic;
|
||||
state.style = XCB_IM_PreeditCallbacks | XCB_IM_StatusNothing;
|
||||
state.cap = Cclientpreedit;
|
||||
state.encoding = Eutf8;
|
||||
keypress(&state, 'k', 0, &res);
|
||||
nexttrace(t, &f, Keypress, &state);
|
||||
updatepreedit(&state, &res.preedit);
|
||||
CT_EQ_INT(t, Wstart, wirecalls[0].op);
|
||||
CT_EQ_INT(t, Wdraw, wirecalls[1].op);
|
||||
CT_EQ_PTR(t, &state, preowner);
|
||||
checkownerwake();
|
||||
nexttrace(t, &f, Keycap, &state);
|
||||
CT_EQ_PTR(t, &state, preowner);
|
||||
|
||||
memset(&req, 0, sizeof req);
|
||||
req.owner = &foreign;
|
||||
req.op = Keypress;
|
||||
req.ks = 'n';
|
||||
req.reply = replyc;
|
||||
chansend(keyc, &req);
|
||||
chanrecv(replyc, &res);
|
||||
memset(&trace, 0, sizeof trace);
|
||||
CT_CHECK(t, channbrecv(f.trace, &trace) > 0);
|
||||
CT_EQ_INT(t, Keypress, trace.op);
|
||||
CT_EQ_PTR(t, &foreign, trace.owner);
|
||||
CT_EQ_PTR(t, &foreign, testengineowner());
|
||||
/* A full pipe cannot block imthread; all bytes coalesce into one probe. */
|
||||
token = 0;
|
||||
for(i = 0; i < 1<<20; i++){
|
||||
n = write(wakefd[1], &token, 1);
|
||||
if(n < 0 && errno == EINTR){
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
if(n < 0)
|
||||
break;
|
||||
}
|
||||
CT_CHECK(t, i < 1<<20);
|
||||
CT_CHECK(t, errno == EAGAIN || errno == EWOULDBLOCK);
|
||||
ximownernotify();
|
||||
CT_CHECK(t, wakedrain() > 0);
|
||||
checkpreowner();
|
||||
nexttrace(t, &f, Keycap, &state);
|
||||
CT_EQ_PTR(t, &foreign, testengineowner());
|
||||
CT_EQ_INT(t, 4, nwirecalls);
|
||||
CT_EQ_INT(t, Wdraw, wirecalls[2].op);
|
||||
CT_EQ_UINT(t, 1, wirecalls[2].changed);
|
||||
CT_EQ_INT(t, Wdone, wirecalls[3].op);
|
||||
CT_CHECK(t, !state.prestarted);
|
||||
CT_EQ_PTR(t, nil, preowner);
|
||||
|
||||
/* Late XIM lifecycle messages remain idempotent after owner cleanup. */
|
||||
release(&state);
|
||||
nexttrace(t, &f, Keyrelease, &state);
|
||||
release(&state);
|
||||
notrace(t, &f);
|
||||
memset(&hdr, 0, sizeof hdr);
|
||||
hdr.major_opcode = XCB_XIM_RESET_IC;
|
||||
callback(nil, nil, ic, &hdr, nil, nil, nil);
|
||||
notrace(t, &f);
|
||||
hdr.major_opcode = XCB_XIM_DESTROY_IC;
|
||||
callback(nil, nil, ic, &hdr, nil, nil, nil);
|
||||
notrace(t, &f);
|
||||
CT_EQ_INT(t, 4, nwirecalls);
|
||||
|
||||
memset(&req, 0, sizeof req);
|
||||
req.owner = &foreign;
|
||||
req.op = Keyrelease;
|
||||
req.reply = replyc;
|
||||
chansend(keyc, &req);
|
||||
chanrecv(replyc, &res);
|
||||
memset(&trace, 0, sizeof trace);
|
||||
CT_CHECK(t, channbrecv(f.trace, &trace) > 0);
|
||||
CT_EQ_INT(t, Keyrelease, trace.op);
|
||||
CT_EQ_PTR(t, &foreign, trace.owner);
|
||||
wakedrain();
|
||||
cleanup:
|
||||
preowner = nil;
|
||||
ximend(&f);
|
||||
}
|
||||
|
||||
void
|
||||
xim_adapter_commit_encoding(struct ct *t)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user