Commit Graph

51 Commits

Author SHA1 Message Date
ef7fb627c6 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.
2026-08-17 12:16:07 +09:00
cd637be4ca ibus: die where startup fails; print the Plan 9 way; drop what said nothing
ibusinit unwound its server and un-registered its atexit handler on a
failure whose only sequel was ibusthread dying anyway; now each failure
dies with its own message, and the test that existed to walk that
unwind goes with it.  Also gone: an empty watch-toggle callback where
libdbus takes nil, Maxconns as a second name for Maxclients, fprintf
and strerror where the rest of the daemon says fprint and %r, USED()
where a parameter can simply be unnamed, a second findcontext() for the
Properties branch, and emitcommit() taking a connection and path apart
from the context that has both.  Ownerpoll lives once, in dat.h.
2026-08-17 01:34:06 +09:00
5faefd9a87 dict: lookups take a trie; a prefix search is its own function; no self-key rule
dictlookup took a Lang for two reasons that were not its business: to
know whether to walk below the key (the emoji dictionary) and to drop a
candidate equal to the key except there.  No dictionary lists its key
among its candidates — the rule was left from a first version that put
the reading first itself — so it goes, and the walk is dictprefix(),
called by the emoji search alone.
2026-08-17 01:31:51 +09:00
795f11be22 test: one engine pump and one preedit check for the white-box suites
server_test, ibus_test and xim_adapter_test each ran their own copy of
the same alt loop that stands in for imthread, and two of them had
private checkstr/checkenginepreedit variants. test_util.c now provides
Pump (trace, optional hold on a chosen op, stop) in its own proc so a
test may block in socket I/O while the engine runs, and test.h declares
the engine hooks once; every .c includes dat.h and fn.h itself as the
rest of the tree does. server_test's three copies of fixture setup and
teardown became serverbegin/serverend.
2026-08-16 16:30:32 +09:00
826da31486 test: drive Korean and Vietnamese through the engine's own transstr
ko_test and vi_test replayed keys with private copies of transstr's
loop, and test_util reimplemented the shown preedit; the engine exports
impre(Im*, Str*) and transstr() instead, so a change to composition
rules is one edit.
2026-08-16 16:25:40 +09:00
a70cfc42e3 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.
2026-08-16 16:16:31 +09:00
abaea77248 engine: look dictionaries up synchronously
The dictionary thread ran in imthread's own proc, so a lookup could
only start once the engine blocked, and it was a trie probe anyway; the
emoji and Hanja searches already called dictlookup directly. The
request/result channels, sequence numbers, staleness checks and the
second draw per Japanese key are gone; dictqjp fills the candidates
in place. Emit.dict and Lang.dictq only ever triggered lookups for
Vietnamese, which has no dictionary. dictlookup(Lang*, key, out, max)
returns the count. The Hanja lookup no longer pre-checks for a single
syllable; a reading either has an entry or it does not.
2026-08-16 16:02:09 +09:00
ebcec3af6b fix(engine): send clients the composed Telex text, not the keys
For Vietnamese the preedit is the map key ('as', 'oong'); only the popup
and the commit path looked it up. Clients with inline preedit therefore
showed 'as' while Enter committed 'á'. impre() now maps once for every
reader, and snapshot() no longer maps a second time.
2026-08-16 15:57:55 +09:00
c7718ece52 data: one trie for maps and dictionaries, one loader
The hash map served a single exact-match lookup that the trie already
answers, at the price of a second container, a second file loader with
its own drift, and a Str-to-UTF-8 conversion on every chain probe. The
files are small (kanji.dict is 7.5k lines), so the trie holds both.
trieopen validates keys and each space-separated value word against Str
and reports path:line; trielookup takes the Str every caller holds and
treats a nil trie as an unloaded map; trienew/trieput exist for tests.
The overflow guards on growth, Trie.root (always 0) and the per-language
init loop written twice are gone.
2026-08-16 15:56:32 +09:00
e4fc327ffd popup: show the candidate page 2026-08-14 20:06:53 +09:00
a841894015 ibus: honor preedit and private-input policy 2026-08-14 19:41:07 +09:00
4cac6f1a15 engine: use stable candidate pages 2026-08-14 19:27:22 +09:00
2e6d7d8e48 xim: clear callback preedit on owner loss 2026-08-14 19:17:37 +09:00
6a58b63223 ipc: negotiate preedit capability and caret messages 2026-08-14 18:53:14 +09:00
9a3a92170e engine: reject stale dictionary results 2026-08-14 18:43:12 +09:00
e6bf32b0f6 xim: place popup from input context 2026-08-14 17:35:33 +09:00
2b4c509d0d xim: add callback preedit and UTF-8 negotiation 2026-08-14 17:20:38 +09:00
2376035524 engine: route popup preedit by client capability 2026-08-14 17:02:46 +09:00
4eba8c2904 tests: cover in-process XIM lifecycle 2026-08-14 16:17:27 +09:00
f5dc552c08 build: use configured include paths 2026-08-14 16:17:07 +09:00
f395f29918 ibus: complete setup before publication 2026-08-14 02:48:49 +09:00
6c0a533c4e ibus: fall back from unreadable machine id 2026-08-14 02:10:16 +09:00
9f4f9ceb14 ibus: cover context ownership through the engine 2026-08-13 23:21:12 +09:00
bb2a970db1 tests: cover ownership across ipc connections 2026-08-13 23:07:25 +09:00
367cbb6cc3 ibus: make context release explicit 2026-08-13 22:03:27 +09:00
b6a9ccd9d9 cleanup: simplify frontend request ownership 2026-08-13 21:57:32 +09:00
e01a991de4 remove: drop Wayland frontend 2026-08-13 21:25:12 +09:00
f46d51b539 renderer: use direct FreeType with explicit font files 2026-08-13 20:40:38 +09:00
125e9349c0 fix: pass empty search backspace through 2026-08-12 21:35:33 +09:00
136695a900 hanja: separate temporary search mode 2026-08-12 21:23:10 +09:00
0216cc3c8a hanja: add one-shot Korean search 2026-08-12 19:19:26 +09:00
0d06ba43cd refactor: remove conditional compilation layers 2026-08-12 17:27:42 +09:00
5927f6a5e1 fix: forward input at the composition limit 2026-08-12 16:21:33 +09:00
c7d4f16d3e test: stress engine transitions 2026-08-12 16:16:25 +09:00
a03efcf6bf test: cover IPC response framing 2026-08-12 16:11:22 +09:00
432df3730c fix: harden the per-user IPC endpoint 2026-08-12 16:08:23 +09:00
4120f90736 fix: make popup rendering deterministic 2026-08-12 15:59:52 +09:00
9c43bcb75c fix: repair Wayland key lifecycle 2026-08-12 15:58:24 +09:00
103f2ec448 fix: harden small core containers 2026-08-12 15:54:16 +09:00
bc5712b6ac fix: retain the active owner's caret 2026-08-12 15:44:04 +09:00
5ba5cf209c fix: assign one active engine owner 2026-08-12 15:41:46 +09:00
9c244d1dd1 fix: retain the newest dictionary request 2026-08-12 15:37:50 +09:00
fabce14933 fix: tighten emoji lookup contracts 2026-08-12 15:36:37 +09:00
d0def814ef refactor: remove empty language maps 2026-08-12 15:35:02 +09:00
f0ba7fc5f6 fix: normalize Korean shifted input 2026-08-12 15:32:28 +09:00
6dfbc08704 fix: correct Katakana composition 2026-08-12 15:29:35 +09:00
ec7e6eb992 fix: preserve complete Japanese readings 2026-08-12 15:28:16 +09:00
2ae87a3926 emoji: repair one-shot candidate selection 2026-08-12 02:08:01 +09:00
0fff17c8b8 emoji: add one-shot candidate search 2026-08-11 22:24:59 +09:00
82276bf37f strengthen core unit tests
Add table-driven dictionary miss and language-switch state coverage, regress stale candidates after backspace, and clear them before dictionary refresh. Keep IPC and runtime-created file checks outside the unit runner.
2026-08-11 21:12:23 +09:00