xim: Compose results of any length, StatusNone styles; ibus: no cursor size check

A Compose sequence whose result is more than one character has no
keysym, so xkb_compose_state_get_one_sym gave nothing and the result was
lost; the UTF-8 the compose state holds is committed instead.  Clients
that ask for a StatusNone style — fcitx5 offers them — failed to create
an input context; the three preedit styles come in both status flavours
now.  IBus SetCursorLocation returned an error for a negative width or
height that nothing reads and no client ever waits for.
This commit is contained in:
2026-08-17 01:49:06 +09:00
parent 0cb395579f
commit 7c9e736996
4 changed files with 13 additions and 8 deletions

View File

@@ -59,6 +59,8 @@ query; the Hanja dictionary lists one modern Hangul syllable at a time.
| XIM PreeditPosition | strans popup | strans popup | | XIM PreeditPosition | strans popup | strans popup |
| XIM PreeditNothing | strans popup | strans popup | | XIM PreeditNothing | strans popup | strans popup |
Each XIM style is offered with StatusNothing and with StatusNone.
XIM text travels as `COMPOUND_TEXT`, which carries any UTF-8. A client that XIM text travels as `COMPOUND_TEXT`, which carries any UTF-8. A client that
sends `XNSpotLocation` gets the popup at that spot whatever its preedit sends `XNSpotLocation` gets the popup at that spot whatever its preedit
style; otherwise the popup sits under the focus window, or under the client style; otherwise the popup sits under the focus window, or under the client

3
ibus.c
View File

@@ -786,9 +786,6 @@ handlecursor(DBusConnection *c, DBusMessage *m, Ictx *ctx)
DBUS_TYPE_INVALID)) DBUS_TYPE_INVALID))
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS, return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
"SetCursorLocation expects four integers"); "SetCursorLocation expects four integers");
if(w < 0 || h < 0)
return handleerror(c, m, DBUS_ERROR_INVALID_ARGS,
"cursor dimensions must not be negative");
setcursor(ctx, x, y, h); setcursor(ctx, x, y, h);
return reply(c, m, DBUS_TYPE_INVALID, nil); return reply(c, m, DBUS_TYPE_INVALID, nil);
} }

View File

@@ -632,6 +632,9 @@ xim_adapter_styles(struct ct *t)
XCB_IM_PreeditPosition | XCB_IM_StatusNothing, XCB_IM_PreeditPosition | XCB_IM_StatusNothing,
XCB_IM_PreeditCallbacks | XCB_IM_StatusNothing, XCB_IM_PreeditCallbacks | XCB_IM_StatusNothing,
XCB_IM_PreeditNothing | XCB_IM_StatusNothing, XCB_IM_PreeditNothing | XCB_IM_StatusNothing,
XCB_IM_PreeditPosition | XCB_IM_StatusNone,
XCB_IM_PreeditCallbacks | XCB_IM_StatusNone,
XCB_IM_PreeditNothing | XCB_IM_StatusNone,
}; };
xcb_im_input_context_t *ic; xcb_im_input_context_t *ic;
Ic *state; Ic *state;
@@ -651,7 +654,8 @@ xim_adapter_styles(struct ct *t)
state = icbindings[0].data; state = icbindings[0].data;
if(!CT_CHECK(t, state != nil && state == ics)) if(!CT_CHECK(t, state != nil && state == ics))
continue; continue;
CT_EQ_INT(t, i == 1 ? Cclientpreedit : 0, state->cap); CT_EQ_INT(t, want[i] & XCB_IM_PreeditCallbacks ? Cclientpreedit : 0,
state->cap);
CT_EQ_PTR(t, ic, state->xic); CT_EQ_PTR(t, ic, state->xic);
icunlink(state); icunlink(state);
free(state); free(state);

10
xim.c
View File

@@ -46,6 +46,9 @@ static u32int styles[] = {
XCB_IM_PreeditPosition | XCB_IM_StatusNothing, XCB_IM_PreeditPosition | XCB_IM_StatusNothing,
XCB_IM_PreeditCallbacks | XCB_IM_StatusNothing, XCB_IM_PreeditCallbacks | XCB_IM_StatusNothing,
XCB_IM_PreeditNothing | XCB_IM_StatusNothing, XCB_IM_PreeditNothing | XCB_IM_StatusNothing,
XCB_IM_PreeditPosition | XCB_IM_StatusNone,
XCB_IM_PreeditCallbacks | XCB_IM_StatusNone,
XCB_IM_PreeditNothing | XCB_IM_StatusNone,
}; };
static void static void
@@ -434,8 +437,8 @@ kpress(Ic *state, xcb_key_press_event_t *ev)
; ;
else if(composed){ else if(composed){
/* The event holds the last key of the sequence, not its result. */ /* The event holds the last key of the sequence, not its result. */
n = xkb_keysym_to_utf8(sym, buf, sizeof buf); n = xkb_compose_state_get_utf8(compose, buf, sizeof buf);
commit(state, buf, max(n - 1, 0)); commit(state, buf, min(n, (int)sizeof buf - 1));
}else }else
xcb_im_forward_event(xim, state->xic, ev); xcb_im_forward_event(xim, state->xic, ev);
xcb_flush(conn); xcb_flush(conn);
@@ -473,8 +476,7 @@ iccreate(xcb_im_client_t *client, xcb_im_input_context_t *ic)
state = emalloc(sizeof(Ic)); state = emalloc(sizeof(Ic));
state->xic = ic; state->xic = ic;
state->client = client; state->client = client;
if(xcb_im_input_context_get_input_style(ic) == if(xcb_im_input_context_get_input_style(ic) & XCB_IM_PreeditCallbacks)
(XCB_IM_PreeditCallbacks | XCB_IM_StatusNothing))
state->cap = Cclientpreedit; state->cap = Cclientpreedit;
state->next = ics; state->next = ics;
ics = state; ics = state;