xim: drop what no client uses; poll for owner loss like IBus
XIM text always went out through imdkit's COMPOUND_TEXT converter, which already wraps every UTF-8 string in ESC%G; the UTF8_STRING negotiation, the per-client encoding list, ximtext.c's fallback and its wrapper never changed a byte on the wire. The spot location is honoured for every style now (GTK's XIM module sends it with PreeditCallbacks) and an unset focus window means the client window, as the spec says, so those clients get the popup at the caret. readattrs/place kept four transient fields to pass values between them; ximclose tore down state right before die(); the OOM passthrough context was a third policy for one small calloc where emalloc dies like everything else. Both frontends now poll for engine-owner loss only while a preedit shows instead of XIM waking on a pipe the engine had to know about; ibus stops waking five times a second when idle. keymeaningful() is the engine's own predicate. The standalone xim_test moved into the unit suite, so xim/Makefile is gone.
This commit is contained in:
@@ -6,6 +6,7 @@ struct Icbinding
|
||||
{
|
||||
xcb_im_input_context_t *ic;
|
||||
void *data;
|
||||
uint32_t style;
|
||||
xcb_window_t clientwin;
|
||||
xcb_window_t focuswin;
|
||||
uint32_t preattrmask;
|
||||
@@ -51,6 +52,8 @@ static int wireflush(xcb_connection_t*);
|
||||
#define xcb_im_input_context_set_data wiresetdata
|
||||
#define xcb_im_input_context_get_data(ic) \
|
||||
(wirebinding(ic) == nil ? nil : wirebinding(ic)->data)
|
||||
#define xcb_im_input_context_get_input_style(ic) \
|
||||
(wirebinding(ic) == nil ? 0 : wirebinding(ic)->style)
|
||||
#define xcb_im_input_context_get_client_window(ic) \
|
||||
(wirebinding(ic) == nil ? XCB_NONE : wirebinding(ic)->clientwin)
|
||||
#define xcb_im_input_context_get_focus_window(ic) \
|
||||
@@ -72,6 +75,7 @@ static int wireflush(xcb_connection_t*);
|
||||
#undef xcb_im_forward_event
|
||||
#undef xcb_im_input_context_set_data
|
||||
#undef xcb_im_input_context_get_data
|
||||
#undef xcb_im_input_context_get_input_style
|
||||
#undef xcb_im_input_context_get_client_window
|
||||
#undef xcb_im_input_context_get_focus_window
|
||||
#undef xcb_im_input_context_get_preedit_attr_mask
|
||||
@@ -314,6 +318,26 @@ wireclear(void)
|
||||
preowner = nil;
|
||||
}
|
||||
|
||||
/* Wire text is the COMPOUND_TEXT of what the engine produced. */
|
||||
static int
|
||||
checkct(struct ct *t, char *where, uchar *got, size_t ngot, char *utf8)
|
||||
{
|
||||
char *want;
|
||||
size_t nwant;
|
||||
int ok;
|
||||
|
||||
xcb_compound_text_init();
|
||||
want = xcb_utf8_to_compound_text(utf8, strlen(utf8), &nwant);
|
||||
if(!CT_CHECK(t, want != nil))
|
||||
return 0;
|
||||
ok = ngot == nwant && memcmp(got, want, nwant) == 0;
|
||||
if(!ok)
|
||||
CT_ERRORF(t, "%s: wire text differs from COMPOUND_TEXT of %s",
|
||||
where, utf8);
|
||||
free(want);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static void
|
||||
wirebind(int n, xcb_im_input_context_t *ic, Ic *state)
|
||||
{
|
||||
@@ -681,35 +705,39 @@ xim_adapter_styles(struct ct *t)
|
||||
XCB_IM_PreeditCallbacks | XCB_IM_StatusNothing,
|
||||
XCB_IM_PreeditNothing | XCB_IM_StatusNothing,
|
||||
};
|
||||
Ic state;
|
||||
int cap, i;
|
||||
xcb_im_input_context_t *ic;
|
||||
Ic *state;
|
||||
int i;
|
||||
|
||||
CT_EQ_SIZE(t, 1, nelem(encs));
|
||||
CT_EQ_STR(t, "COMPOUND_TEXT", encs[0]);
|
||||
CT_EQ_SIZE(t, nelem(want), nelem(styles));
|
||||
/* Only PreeditCallbacks clients draw the preedit themselves. */
|
||||
for(i = 0; i < nelem(want); i++){
|
||||
CT_EQ_UINT(t, want[i], styles[i]);
|
||||
CT_CHECK(t, stylecap(want[i], &cap));
|
||||
CT_EQ_INT(t, i == 1 ? Cclientpreedit : 0, cap);
|
||||
wireclear();
|
||||
ic = (xcb_im_input_context_t*)(uintptr)(80+i);
|
||||
wirebind(0, ic, nil);
|
||||
icbindings[0].style = want[i];
|
||||
iccreate(nil, ic);
|
||||
state = icbindings[0].data;
|
||||
if(!CT_CHECK(t, state != nil && state == ics))
|
||||
continue;
|
||||
CT_EQ_INT(t, i == 1 ? Cclientpreedit : 0, state->cap);
|
||||
CT_EQ_PTR(t, ic, state->xic);
|
||||
icunlink(state);
|
||||
free(state);
|
||||
}
|
||||
CT_CHECK(t, !stylecap(XCB_IM_PreeditNone | XCB_IM_StatusNothing,
|
||||
&cap));
|
||||
CT_CHECK(t, !stylecap(XCB_IM_PreeditCallbacks | XCB_IM_StatusCallbacks,
|
||||
&cap));
|
||||
CT_EQ_INT(t, 0, cap);
|
||||
memset(&state, 0, sizeof state);
|
||||
setstyle(&state, XCB_IM_PreeditNone | XCB_IM_StatusNothing);
|
||||
CT_EQ_UINT(t, XCB_IM_PreeditNothing | XCB_IM_StatusNothing,
|
||||
state.style);
|
||||
CT_EQ_INT(t, 0, state.cap);
|
||||
setstyle(&state, XCB_IM_PreeditCallbacks | XCB_IM_StatusNothing);
|
||||
CT_EQ_INT(t, Cclientpreedit, state.cap);
|
||||
}
|
||||
|
||||
void
|
||||
xim_adapter_placement(struct ct *t)
|
||||
{
|
||||
/* Spot location first, then the bottom of the focus window, then of
|
||||
* the client window; an unset focus window is the client window. */
|
||||
static const struct {
|
||||
u32int style;
|
||||
u32int mask;
|
||||
int focuswin;
|
||||
int fgeo;
|
||||
int ftrans;
|
||||
int cgeo;
|
||||
@@ -718,18 +746,13 @@ xim_adapter_placement(struct ct *t)
|
||||
int x;
|
||||
int y;
|
||||
} cases[] = {
|
||||
{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, 300, 440},
|
||||
{XCB_IM_PreeditPosition | XCB_IM_StatusNothing,
|
||||
0, 1, 1, 1, 1, 1, 100, 230},
|
||||
{XCB_IM_PreeditNothing | XCB_IM_StatusNothing,
|
||||
XCB_XIM_XNSpotLocation_MASK, 1, 1, 1, 1, 1, 100, 230},
|
||||
{XCB_IM_PreeditPosition | XCB_IM_StatusNothing,
|
||||
0, 0, 1, 1, 1, 1, 300, 440},
|
||||
{XCB_IM_PreeditPosition | XCB_IM_StatusNothing,
|
||||
0, 0, 1, 0, 1, 0, 0, 0},
|
||||
{XCB_XIM_XNSpotLocation_MASK, 10, 1, 1, 1, 1, 1, 103, 204},
|
||||
{XCB_XIM_XNSpotLocation_MASK, 10, 1, 0, 1, 1, 1, 300, 440},
|
||||
{XCB_XIM_XNSpotLocation_MASK, 0, 1, 1, 1, 1, 1, 303, 404},
|
||||
{0, 10, 1, 1, 1, 1, 1, 100, 230},
|
||||
{0, 0, 1, 1, 1, 1, 1, 300, 440},
|
||||
{0, 10, 0, 1, 1, 1, 1, 300, 440},
|
||||
{0, 10, 0, 1, 0, 1, 0, 0, 0},
|
||||
};
|
||||
xcb_im_input_context_t *ic;
|
||||
Icbinding *b;
|
||||
@@ -742,12 +765,11 @@ xim_adapter_placement(struct ct *t)
|
||||
wireclear();
|
||||
memset(&state, 0, sizeof state);
|
||||
state.xic = ic;
|
||||
state.style = cases[i].style;
|
||||
state.caret.valid = 1;
|
||||
state.caret.x = state.caret.y = 9;
|
||||
wirebind(0, ic, &state);
|
||||
b = &icbindings[0];
|
||||
b->focuswin = 10;
|
||||
b->focuswin = cases[i].focuswin;
|
||||
b->clientwin = 20;
|
||||
b->preattrmask = cases[i].mask;
|
||||
b->preattr.spot_location.x = 3;
|
||||
@@ -758,12 +780,7 @@ xim_adapter_placement(struct ct *t)
|
||||
focus->translateok = cases[i].ftrans;
|
||||
client->geometryok = cases[i].cgeo;
|
||||
client->translateok = cases[i].ctrans;
|
||||
refreshplace(&state);
|
||||
CT_EQ_UINT(t, 10, state.focuswin);
|
||||
CT_EQ_UINT(t, 20, state.clientwin);
|
||||
CT_EQ_INT(t, cases[i].style ==
|
||||
(XCB_IM_PreeditPosition | XCB_IM_StatusNothing) &&
|
||||
cases[i].mask != 0, state.hasspot);
|
||||
place(&state);
|
||||
CT_EQ_INT(t, cases[i].valid, state.caret.valid);
|
||||
CT_EQ_INT(t, cases[i].x, state.caret.x);
|
||||
CT_EQ_INT(t, cases[i].y, state.caret.y);
|
||||
@@ -793,7 +810,6 @@ xim_adapter_placement_updates(struct ct *t)
|
||||
goto cleanup;
|
||||
wireclear();
|
||||
state.xic = ic;
|
||||
state.style = XCB_IM_PreeditPosition | XCB_IM_StatusNothing;
|
||||
wirebind(0, ic, &state);
|
||||
b = &icbindings[0];
|
||||
b->focuswin = 11;
|
||||
@@ -825,8 +841,6 @@ xim_adapter_placement_updates(struct ct *t)
|
||||
CT_CHECK(t, req.caret.valid);
|
||||
CT_EQ_INT(t, 165, req.caret.x);
|
||||
CT_EQ_INT(t, 266, req.caret.y);
|
||||
CT_EQ_INT(t, 15, state.spot.x);
|
||||
CT_EQ_INT(t, 16, state.spot.y);
|
||||
b->preattrmask = 0;
|
||||
wirewins[0].geometryok = 0;
|
||||
hdr.major_opcode = XCB_XIM_SET_IC_FOCUS;
|
||||
@@ -841,33 +855,6 @@ cleanup:
|
||||
ximend(&f);
|
||||
}
|
||||
|
||||
void
|
||||
xim_adapter_encoding_negotiation(struct ct *t)
|
||||
{
|
||||
xcb_im_packet_header_fr_t hdr;
|
||||
xcb_im_client_t *clients[Maxclients+1];
|
||||
u16int selected;
|
||||
int i;
|
||||
|
||||
clearencodings();
|
||||
CT_EQ_SIZE(t, 2, nelem(encs));
|
||||
CT_EQ_STR(t, "COMPOUND_TEXT", encs[0]);
|
||||
CT_EQ_STR(t, "UTF8_STRING", encs[1]);
|
||||
memset(&hdr, 0, sizeof hdr);
|
||||
hdr.major_opcode = XCB_XIM_ENCODING_NEGOTIATION;
|
||||
for(i = 0; i < nelem(clients); i++){
|
||||
clients[i] = (xcb_im_client_t*)(uintptr)(i+1);
|
||||
selected = i == 0 ? 0 : 1;
|
||||
callback(nil, clients[i], nil, &hdr, nil, &selected, nil);
|
||||
}
|
||||
CT_EQ_INT(t, Ecompound, getencoding(clients[0]));
|
||||
CT_EQ_INT(t, Eutf8, getencoding(clients[Maxclients]));
|
||||
hdr.major_opcode = XCB_XIM_DISCONNECT;
|
||||
for(i = 0; i < nelem(clients); i++)
|
||||
callback(nil, clients[i], nil, &hdr, nil, nil, nil);
|
||||
CT_EQ_PTR(t, nil, clientenc);
|
||||
}
|
||||
|
||||
void
|
||||
xim_adapter_callback_replacement(struct ct *t)
|
||||
{
|
||||
@@ -879,8 +866,7 @@ xim_adapter_callback_replacement(struct ct *t)
|
||||
ic = (xcb_im_input_context_t*)(uintptr)3;
|
||||
memset(&state, 0, sizeof state);
|
||||
state.xic = ic;
|
||||
state.style = XCB_IM_PreeditCallbacks | XCB_IM_StatusNothing;
|
||||
state.encoding = Eutf8;
|
||||
state.cap = Cclientpreedit;
|
||||
wireclear();
|
||||
sinit(&pre, "k", strlen("k"));
|
||||
updatepreedit(&state, &pre);
|
||||
@@ -899,8 +885,7 @@ xim_adapter_callback_replacement(struct ct *t)
|
||||
CT_EQ_UINT(t, 0, wirecalls[2].first);
|
||||
CT_EQ_UINT(t, 1, wirecalls[2].changed);
|
||||
CT_EQ_UINT(t, 2, wirecalls[2].caret);
|
||||
CT_EQ_INT(t, strlen("한😀"), wirecalls[2].nbyte);
|
||||
CT_EQ_MEM(t, "한😀", wirecalls[2].text, wirecalls[2].nbyte);
|
||||
checkct(t, "replacement", wirecalls[2].text, wirecalls[2].nbyte, "한😀");
|
||||
CT_EQ_INT(t, 2, wirecalls[2].nfeedback);
|
||||
for(i = 0; i < wirecalls[2].nfeedback; i++)
|
||||
CT_EQ_UINT(t, XCB_XIM_UNDERLINE, wirecalls[2].feedback[i]);
|
||||
@@ -925,16 +910,12 @@ xim_adapter_callback_unicode(struct ct *t)
|
||||
Ic state;
|
||||
Str pre;
|
||||
Wirecall *call;
|
||||
char *want;
|
||||
size_t nwant;
|
||||
int i;
|
||||
|
||||
xcb_compound_text_init();
|
||||
for(i = 0; i < nelem(text); i++){
|
||||
memset(&state, 0, sizeof state);
|
||||
state.xic = (xcb_im_input_context_t*)(uintptr)(10+i);
|
||||
state.style = XCB_IM_PreeditCallbacks | XCB_IM_StatusNothing;
|
||||
state.encoding = Eutf8;
|
||||
state.cap = Cclientpreedit;
|
||||
sinit(&pre, text[i], strlen(text[i]));
|
||||
wireclear();
|
||||
updatepreedit(&state, &pre);
|
||||
@@ -943,24 +924,7 @@ xim_adapter_callback_unicode(struct ct *t)
|
||||
CT_EQ_INT(t, Wdraw, call->op);
|
||||
CT_EQ_UINT(t, pre.n, call->caret);
|
||||
CT_EQ_INT(t, pre.n, call->nfeedback);
|
||||
CT_EQ_INT(t, strlen(text[i]), call->nbyte);
|
||||
CT_EQ_MEM(t, text[i], call->text, call->nbyte);
|
||||
|
||||
memset(&state, 0, sizeof state);
|
||||
state.xic = (xcb_im_input_context_t*)(uintptr)(20+i);
|
||||
state.style = XCB_IM_PreeditCallbacks | XCB_IM_StatusNothing;
|
||||
state.encoding = Ecompound;
|
||||
wireclear();
|
||||
updatepreedit(&state, &pre);
|
||||
want = ximcompound(text[i], strlen(text[i]), &nwant);
|
||||
if(!CT_CHECK(t, want != nil))
|
||||
continue;
|
||||
call = &wirecalls[1];
|
||||
CT_EQ_SIZE(t, nwant, call->nbyte);
|
||||
CT_EQ_MEM(t, want, call->text, nwant);
|
||||
CT_EQ_UINT(t, pre.n, call->caret);
|
||||
CT_EQ_INT(t, pre.n, call->nfeedback);
|
||||
free(want);
|
||||
checkct(t, text[i], call->text, call->nbyte, text[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -971,8 +935,7 @@ startstate(Ic *state, xcb_im_input_context_t *ic)
|
||||
|
||||
memset(state, 0, sizeof *state);
|
||||
state->xic = ic;
|
||||
state->style = XCB_IM_PreeditCallbacks | XCB_IM_StatusNothing;
|
||||
state->encoding = Eutf8;
|
||||
state->cap = Cclientpreedit;
|
||||
sinit(&pre, "あ", strlen("あ"));
|
||||
updatepreedit(state, &pre);
|
||||
}
|
||||
@@ -986,7 +949,6 @@ xim_adapter_callback_cleanup(struct ct *t)
|
||||
};
|
||||
xcb_im_packet_header_fr_t hdr;
|
||||
xcb_im_reset_ic_reply_fr_t reply;
|
||||
xcb_key_press_event_t ev;
|
||||
xcb_im_client_t *client;
|
||||
xcb_im_input_context_t *ic;
|
||||
Ximfix f;
|
||||
@@ -1001,9 +963,7 @@ xim_adapter_callback_cleanup(struct ct *t)
|
||||
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);
|
||||
keypress(&state, 'a', 0, &res);
|
||||
@@ -1016,9 +976,8 @@ xim_adapter_callback_cleanup(struct ct *t)
|
||||
nexttrace(t, &f, Keycap, &state);
|
||||
nexttrace(t, &f, Keyreset, &state);
|
||||
notrace(t, &f);
|
||||
CT_EQ_INT(t, strlen("か"), reply.byte_length_of_committed_string);
|
||||
CT_EQ_MEM(t, "か", reply.committed_string,
|
||||
reply.byte_length_of_committed_string);
|
||||
checkct(t, "reset reply", reply.committed_string,
|
||||
reply.byte_length_of_committed_string, "か");
|
||||
free(reply.committed_string);
|
||||
CT_CHECK(t, state.engaged);
|
||||
CT_EQ_PTR(t, &state, testengineowner());
|
||||
@@ -1075,23 +1034,6 @@ xim_adapter_callback_cleanup(struct ct *t)
|
||||
CT_EQ_INT(t, Wdone, wirecalls[3].op);
|
||||
CT_EQ_PTR(t, nil, preowner);
|
||||
|
||||
ic = (xcb_im_input_context_t*)(uintptr)42;
|
||||
wireclear();
|
||||
wirebind(0, ic, nil);
|
||||
icinstall(nil, ic, nil);
|
||||
CT_EQ_PTR(t, &passthrough, icbindings[0].data);
|
||||
memset(&ev, 0, sizeof ev);
|
||||
ev.response_type = XCB_KEY_PRESS;
|
||||
ev.detail = 38;
|
||||
hdr.major_opcode = XCB_XIM_FORWARD_EVENT;
|
||||
callback(nil, nil, ic, &hdr, nil, &ev, nil);
|
||||
CT_EQ_INT(t, 1, nwirecalls);
|
||||
CT_EQ_INT(t, Wforward, wirecalls[0].op);
|
||||
CT_EQ_UINT(t, ev.detail, wirecalls[0].keysym);
|
||||
ev.response_type = XCB_KEY_RELEASE;
|
||||
callback(nil, nil, ic, &hdr, nil, &ev, nil);
|
||||
CT_EQ_INT(t, 2, nwirecalls);
|
||||
CT_EQ_INT(t, Wforward, wirecalls[1].op);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1110,8 +1052,7 @@ xim_adapter_callback_transfer(struct ct *t)
|
||||
goto cleanup;
|
||||
wireclear();
|
||||
a.xic = aic;
|
||||
a.style = XCB_IM_PreeditCallbacks | XCB_IM_StatusNothing;
|
||||
a.encoding = Eutf8;
|
||||
a.cap = Cclientpreedit;
|
||||
sinit(&pre, "あ", strlen("あ"));
|
||||
updatepreedit(&a, &pre);
|
||||
keypress(&b, 'x', 0, &res);
|
||||
@@ -1138,33 +1079,30 @@ xim_adapter_callback_owner_loss(struct ct *t)
|
||||
Keyreq req;
|
||||
Keyreq trace;
|
||||
Keyres res;
|
||||
uchar token;
|
||||
int foreign, i, n;
|
||||
int foreign;
|
||||
|
||||
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();
|
||||
/* While we still own the engine, the periodic check changes nothing. */
|
||||
checkpreowner();
|
||||
nexttrace(t, &f, Keycap, &state);
|
||||
CT_EQ_PTR(t, &state, preowner);
|
||||
CT_EQ_INT(t, 2, nwirecalls);
|
||||
|
||||
/* Another frontend takes the engine; the next check clears our preedit. */
|
||||
memset(&req, 0, sizeof req);
|
||||
req.owner = &foreign;
|
||||
req.op = Keypress;
|
||||
@@ -1177,21 +1115,6 @@ xim_adapter_callback_owner_loss(struct ct *t)
|
||||
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());
|
||||
@@ -1201,6 +1124,8 @@ xim_adapter_callback_owner_loss(struct ct *t)
|
||||
CT_EQ_INT(t, Wdone, wirecalls[3].op);
|
||||
CT_CHECK(t, !state.prestarted);
|
||||
CT_EQ_PTR(t, nil, preowner);
|
||||
checkpreowner();
|
||||
notrace(t, &f);
|
||||
|
||||
/* Late XIM lifecycle messages remain idempotent after owner cleanup. */
|
||||
release(&state);
|
||||
@@ -1226,7 +1151,6 @@ xim_adapter_callback_owner_loss(struct ct *t)
|
||||
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);
|
||||
@@ -1238,32 +1162,18 @@ xim_adapter_commit_encoding(struct ct *t)
|
||||
static char text[] = "한𠀋❤️👩💻";
|
||||
Ic state;
|
||||
xcb_im_input_context_t *ic;
|
||||
char *want;
|
||||
size_t nwant;
|
||||
|
||||
ic = (xcb_im_input_context_t*)(uintptr)60;
|
||||
memset(&state, 0, sizeof state);
|
||||
state.xic = ic;
|
||||
state.encoding = Eutf8;
|
||||
wireclear();
|
||||
commit(&state, text, strlen(text));
|
||||
CT_EQ_INT(t, 1, nwirecalls);
|
||||
CT_EQ_INT(t, Wcommit, wirecalls[0].op);
|
||||
CT_EQ_UINT(t, XCB_XIM_LOOKUP_CHARS, wirecalls[0].flag);
|
||||
CT_EQ_UINT(t, 0, wirecalls[0].keysym);
|
||||
CT_EQ_INT(t, strlen(text), wirecalls[0].nbyte);
|
||||
CT_EQ_MEM(t, text, wirecalls[0].text, wirecalls[0].nbyte);
|
||||
|
||||
xcb_compound_text_init();
|
||||
state.encoding = Ecompound;
|
||||
checkct(t, "commit", wirecalls[0].text, wirecalls[0].nbyte, text);
|
||||
wireclear();
|
||||
commit(&state, text, strlen(text));
|
||||
want = ximcompound(text, strlen(text), &nwant);
|
||||
if(!CT_CHECK(t, want != nil))
|
||||
return;
|
||||
CT_EQ_INT(t, 1, nwirecalls);
|
||||
CT_EQ_INT(t, Wcommit, wirecalls[0].op);
|
||||
CT_EQ_SIZE(t, nwant, wirecalls[0].nbyte);
|
||||
CT_EQ_MEM(t, want, wirecalls[0].text, nwant);
|
||||
free(want);
|
||||
commit(&state, text, 0);
|
||||
CT_EQ_INT(t, 0, nwirecalls);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user