compose: one Compose table for the XIM and IBus frontends
An IBus client throws away a dead key its engine did not take — the GTK module's own comment says so, and Qt does the same — so é and ü were lost in every IBus application, while XIM composed them with a table of its own. That table moves to compose.c, which both frontends now use; xim.c is the shorter for it. A finished sequence is text, not a key: the engine is asked to hand back what it had pending, and the composed text follows it, so the composed character can no longer land before the syllable typed before it.
This commit is contained in:
@@ -32,10 +32,11 @@ FAULT = daemon_collision_test daemon_failure_test daemon_restart_test
|
||||
LIVE = $(SMOKE) $(FAULT)
|
||||
TESTSRC = test_util.c str_test.c trie_test.c \
|
||||
ko_test.c vi_test.c engine_test.c dict_test.c ipc_test.c \
|
||||
popup_test.c font_test.c ibus_test.c server_test.c xim_adapter_test.c
|
||||
popup_test.c font_test.c ibus_test.c server_test.c compose_test.c \
|
||||
xim_adapter_test.c
|
||||
TESTOBJ = $(TESTSRC:.c=.o)
|
||||
PARENTSRC = str.c trie.c dict.c ko.c vi.c ipc.c popup_layout.c \
|
||||
font.c
|
||||
font.c compose.c
|
||||
PARENTOBJ = $(PARENTSRC:%.c=unit_%.o)
|
||||
COMMONOBJ = $(TESTOBJ) $(PARENTOBJ)
|
||||
OBJS = unit_test.o stress_test.o $(COMMONOBJ)
|
||||
@@ -125,6 +126,7 @@ xim_adapter_test.o: UNIT_CPPFLAGS += $(XIM_CFLAGS)
|
||||
xim_adapter_test.o: ../xim.c
|
||||
server_test.o: ../srv.c
|
||||
unit_font.o: UNIT_CPPFLAGS += $(TEXT_CFLAGS)
|
||||
unit_compose.o compose_test.o: UNIT_CPPFLAGS += $(IBUS_CFLAGS)
|
||||
|
||||
unit_%.o: ../%.c ../dat.h ../fn.h ../ipc.h
|
||||
$(CC) $(CPPFLAGS) $(UNIT_CPPFLAGS) $(UNIT_CFLAGS) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
37
tests/compose_test.c
Normal file
37
tests/compose_test.c
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "dat.h"
|
||||
#include "fn.h"
|
||||
#include "test.h"
|
||||
#include <xkbcommon/xkbcommon-keysyms.h>
|
||||
|
||||
/* A sequence swallows its keys and hands its text back at the end. */
|
||||
void
|
||||
compose_sequences(struct ct *t)
|
||||
{
|
||||
static const struct {
|
||||
u32int sym;
|
||||
int composing;
|
||||
char *text;
|
||||
} keys[] = {
|
||||
{ XKB_KEY_a, 0, "" },
|
||||
{ XKB_KEY_dead_acute, 1, "" },
|
||||
{ XKB_KEY_e, 0, "é" },
|
||||
{ XKB_KEY_Multi_key, 1, "" },
|
||||
{ XKB_KEY_o, 1, "" },
|
||||
{ XKB_KEY_c, 0, "©" },
|
||||
{ XKB_KEY_dead_acute, 1, "" },
|
||||
{ XKB_KEY_Escape, 1, "" },
|
||||
{ XKB_KEY_a, 0, "" },
|
||||
};
|
||||
char buf[Maxutf];
|
||||
int i;
|
||||
|
||||
if(!CT_CHECK(t, setenv("XCOMPOSEFILE", "data/compose", 1) == 0))
|
||||
return;
|
||||
composeinit();
|
||||
for(i = 0; i < nelem(keys); i++){
|
||||
CT_EQ_INT(t, keys[i].composing,
|
||||
composekey(keys[i].sym, buf, sizeof buf));
|
||||
CT_EQ_STR(t, keys[i].text, buf);
|
||||
}
|
||||
unsetenv("XCOMPOSEFILE");
|
||||
}
|
||||
2
tests/data/compose
Normal file
2
tests/data/compose
Normal file
@@ -0,0 +1,2 @@
|
||||
<dead_acute> <e> : "é"
|
||||
<Multi_key> <o> <c> : "©"
|
||||
@@ -153,9 +153,10 @@ static Keyres
|
||||
contextkey(struct ct *t, Ibusfix *f, Ictx *ctx, u32int sym, u32int state)
|
||||
{
|
||||
Keyres res;
|
||||
char text[Maxutf];
|
||||
|
||||
memset(&res, 0, sizeof res);
|
||||
CT_CHECK(t, processkey(ctx, sym, state, &res));
|
||||
CT_CHECK(t, processkey(ctx, sym, state, text, sizeof text, &res));
|
||||
nexttrace(t, f, Keypress, ctx);
|
||||
return res;
|
||||
}
|
||||
@@ -219,6 +220,7 @@ ibus_private_input_policy(struct ct *t)
|
||||
Ibusfix f;
|
||||
Ictx *ctx;
|
||||
Keyres res;
|
||||
char text[Maxutf];
|
||||
int i;
|
||||
|
||||
if(!ibusbegin(t, &f))
|
||||
@@ -239,7 +241,7 @@ ibus_private_input_policy(struct ct *t)
|
||||
checkstr(t, "preedit", "k", &res.preedit);
|
||||
ctx->purpose = Ibuspurposepassword;
|
||||
memset(&res, 0, sizeof res);
|
||||
CT_CHECK(t, !processkey(ctx, 'x', 0, &res));
|
||||
CT_CHECK(t, !processkey(ctx, 'x', 0, text, sizeof text, &res));
|
||||
CT_CHECK(t, !res.eaten);
|
||||
notrace(t, &f);
|
||||
checkenginepreedit(t, "k");
|
||||
@@ -270,6 +272,7 @@ ibus_context_lifecycle(struct ct *t)
|
||||
Keyreq req;
|
||||
Keyres res;
|
||||
Caret at;
|
||||
char text[Maxutf];
|
||||
|
||||
if(!ibusbegin(t, &f))
|
||||
goto cleanup;
|
||||
@@ -285,7 +288,7 @@ ibus_context_lifecycle(struct ct *t)
|
||||
notrace(t, &f);
|
||||
CT_CHECK(t, a->caret.valid);
|
||||
memset(&res, 0, sizeof res);
|
||||
CT_CHECK(t, !processkey(a, 'x', Relmask, &res));
|
||||
CT_CHECK(t, !processkey(a, 'x', Relmask, text, sizeof text, &res));
|
||||
CT_CHECK(t, !res.eaten);
|
||||
notrace(t, &f);
|
||||
CT_CHECK(t, !a->focused);
|
||||
@@ -293,7 +296,7 @@ ibus_context_lifecycle(struct ct *t)
|
||||
|
||||
/* A key stands for the FocusIn a client may never send. */
|
||||
memset(&res, 0, sizeof res);
|
||||
CT_CHECK(t, processkey(a, 'x', 0, &res));
|
||||
CT_CHECK(t, processkey(a, 'x', 0, text, sizeof text, &res));
|
||||
req = nexttrace(t, &f, Keypress, a);
|
||||
CT_CHECK(t, a->focused);
|
||||
CT_CHECK(t, !res.eaten);
|
||||
@@ -369,7 +372,7 @@ ibus_context_lifecycle(struct ct *t)
|
||||
notrace(t, &f);
|
||||
|
||||
memset(&res, 0, sizeof res);
|
||||
CT_CHECK(t, !processkey(b, 'x', Relmask, &res));
|
||||
CT_CHECK(t, !processkey(b, 'x', Relmask, text, sizeof text, &res));
|
||||
CT_CHECK(t, !res.eaten);
|
||||
notrace(t, &f);
|
||||
CT_EQ_PTR(t, b, testengineowner());
|
||||
|
||||
@@ -112,6 +112,7 @@ void ibus_capability_policy(struct ct*);
|
||||
void ibus_private_input_policy(struct ct*);
|
||||
void ibus_context_lifecycle(struct ct*);
|
||||
void ibus_active_release_lifecycle(struct ct*);
|
||||
void compose_sequences(struct ct*);
|
||||
void xim_keymap_lookup(struct ct*);
|
||||
void xim_compound_text(struct ct*);
|
||||
void xim_adapter_key_contract(struct ct*);
|
||||
|
||||
@@ -135,6 +135,7 @@ static const struct ct_test tests[] = {
|
||||
{ "ibus/private-input-policy", ibus_private_input_policy },
|
||||
{ "ibus/context-lifecycle", ibus_context_lifecycle },
|
||||
{ "ibus/active-release-lifecycle", ibus_active_release_lifecycle },
|
||||
{ "compose/sequences", compose_sequences },
|
||||
{ "xim/keymap-lookup", xim_keymap_lookup },
|
||||
{ "xim/compound-text", xim_compound_text },
|
||||
{ "xim/adapter-key-contract", xim_adapter_key_contract },
|
||||
|
||||
Reference in New Issue
Block a user