From b6a9ccd9d9f8cf540d2196ae19ec0d21ec54bca5 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Thu, 13 Aug 2026 21:57:32 +0900 Subject: [PATCH] cleanup: simplify frontend request ownership --- dat.h | 3 +- fn.h | 2 - ibus.c | 5 +-- ipc.h | 4 +- srv.c | 14 +++---- strans.c | 27 +++---------- tests/engine_test.c | 96 +++++++++++++++++++++++++++------------------ tests/test.h | 1 + tests/unit_test.c | 1 + 9 files changed, 74 insertions(+), 79 deletions(-) diff --git a/dat.h b/dat.h index 32b2bcc..dd87fa9 100644 --- a/dat.h +++ b/dat.h @@ -154,12 +154,11 @@ struct Keyres struct Keyreq { - uvlong owner; + void *owner; /* stable until the context's release is acknowledged */ int op; u32int ks; u32int mod; Caret caret; - int want; /* nonzero: include preedit in reply */ Channel *reply; }; diff --git a/fn.h b/fn.h index dad3db9..52a23a2 100644 --- a/fn.h +++ b/fn.h @@ -36,8 +36,6 @@ Emit transko(Im*, Rune); Emit transvi(Im*, Rune); void backko(Im*); void backvi(Im*); -void dictsend(Im*, Str*); -uvlong ownernew(void); void srvthread(void*); void ibusthread(void*); diff --git a/ibus.c b/ibus.c index 63d4353..88631d6 100644 --- a/ibus.c +++ b/ibus.c @@ -30,7 +30,6 @@ struct Ictx { DBusConnection *conn; char path[64]; - uvlong owner; int focused; Caret caret; }; @@ -282,7 +281,6 @@ newcontext(DBusConnection *conn, const char *path) if(contexts[i].conn == nil){ memset(&contexts[i], 0, sizeof contexts[i]); contexts[i].conn = conn; - contexts[i].owner = ownernew(); strncpy(contexts[i].path, path, sizeof contexts[i].path); contexts[i].path[sizeof contexts[i].path-1] = '\0'; return &contexts[i]; @@ -296,12 +294,11 @@ sendrequest(Ictx *ctx, int op, u32int ks, u32int mod, Keyres *res) Keyreq kr; memset(&kr, 0, sizeof kr); - kr.owner = ctx->owner; + kr.owner = ctx; kr.op = op; kr.ks = ks; kr.mod = mod; kr.caret = ctx->caret; - kr.want = op == Keypress; kr.reply = replyc; chansend(keyc, &kr); chanrecv(replyc, res); diff --git a/ipc.h b/ipc.h index b517e94..2fcc82c 100644 --- a/ipc.h +++ b/ipc.h @@ -4,8 +4,8 @@ /* * Request: [flags, modifiers, key byte 0, ..., key byte 3]. * Flags request preedit and distinguish lifecycle reset from physical Escape. - * The server assigns the connection's owner generation; it is not sent on - * the wire. + * The server identifies the connection as the engine owner; that identity is + * not sent on the wire. * Only Mmask modifier bits are retained. * Response: [eaten, commit-length-low, commit-length-high, commit...], * followed, when requested, by diff --git a/srv.c b/srv.c index eabb785..acb4255 100644 --- a/srv.c +++ b/srv.c @@ -11,7 +11,6 @@ typedef struct Client Client; struct Client { int fd; - uvlong owner; }; static int @@ -27,9 +26,8 @@ srvreadkey(int fd, Keyreq *kr) kr->op = ipcreqreset(req) ? Keyreset : Keypress; kr->ks = ks; kr->mod = mod; - kr->want = want; memset(&kr->caret, 0, sizeof kr->caret); - return 0; + return want; } static void @@ -42,7 +40,7 @@ clientthread(void *arg) Keyres res; uchar out[Ipcmaxresp]; char commit[Maxutf], preedit[Maxutf]; - int n, ncommit, npreedit; + int n, ncommit, npreedit, want; uchar token; client = arg; @@ -50,19 +48,18 @@ clientthread(void *arg) threadsetname("client %d", fd); reply = chancreate(sizeof(Keyres), 0); kr.reply = reply; - kr.owner = client->owner; - while(srvreadkey(fd, &kr) == 0){ + kr.owner = client; + while((want = srvreadkey(fd, &kr)) >= 0){ chansend(keyc, &kr); chanrecv(reply, &res); ncommit = stoutf(&res.commit, commit, sizeof commit); npreedit = stoutf(&res.preedit, preedit, sizeof preedit); n = ipcpackresp(out, sizeof out, res.eaten, - commit, ncommit, preedit, npreedit, kr.want); + commit, ncommit, preedit, npreedit, want); if(n < 0 || ipcsend(fd, out, n) < 0) break; } kr.op = Keyrelease; - kr.want = 0; chansend(keyc, &kr); chanrecv(reply, &res); chanfree(reply); @@ -110,7 +107,6 @@ srvthread(void*) } client = emalloc(sizeof *client); client->fd = fd; - client->owner = ownernew(); if(proccreate(clientthread, client, 8192) < 0){ chanrecv(clientc, &token); close(fd); diff --git a/strans.c b/strans.c index 12c854a..d1c8b98 100644 --- a/strans.c +++ b/strans.c @@ -4,9 +4,7 @@ static Im im; static int popup = 0; static int visible = 0; -static Lock ownerlock; -static uvlong ownerctr; -static uvlong activeowner; +static void *activeowner; static Caret caret; static void dictqmap(Im*); static void dictqjp(Im*); @@ -22,19 +20,6 @@ struct Search }; static Search search; -uvlong -ownernew(void) -{ - uvlong n; - - lock(&ownerlock); - n = ++ownerctr; - if(n == 0) - n = ++ownerctr; - unlock(&ownerlock); - return n; -} - Lang langs[] = { {LangEN, nil, nil, nil, nil, nil, nil, nil}, {LangJP, "hira", "kanji", transmap, backjp, dictqjp, nil, nil}, @@ -155,7 +140,7 @@ reset(void) show(); } -void +static void dictsend(Im *im, Str *key) { Dictreq old, req; @@ -792,7 +777,7 @@ init(void) im.l = getlang(LangEN); memset(&search, 0, sizeof search); memset(&caret, 0, sizeof caret); - activeowner = 0; + activeowner = nil; visible = 0; } @@ -814,7 +799,7 @@ imhandlekey(Keyreq *kr) case Keyrelease: if(kr->owner == activeowner){ reset(); - activeowner = 0; + activeowner = nil; } break; case Keyreset: @@ -827,7 +812,7 @@ imhandlekey(Keyreq *kr) show(); } break; - default: + case Keypress: res.eaten = 0; if(meaningful(kr)){ if(kr->owner != activeowner){ @@ -840,7 +825,7 @@ imhandlekey(Keyreq *kr) } break; } - if(kr->want && kr->owner == activeowner){ + if(kr->owner == activeowner){ if(search.lang) res.preedit = search.text; else diff --git a/tests/engine_test.c b/tests/engine_test.c index ab0ec64..508071a 100644 --- a/tests/engine_test.c +++ b/tests/engine_test.c @@ -161,7 +161,7 @@ engine_dictionary_queue_latest_wins(struct ct *t) } static Keyres -ownerrequestat(uvlong owner, int op, Rune key, u32int mod, Caret *caret) +ownerrequestat(void *owner, int op, Rune key, u32int mod, Caret *caret) { Channel *reply; Keyreq req; @@ -175,7 +175,6 @@ ownerrequestat(uvlong owner, int op, Rune key, u32int mod, Caret *caret) req.mod = mod; if(caret != nil) req.caret = *caret; - req.want = 1; req.reply = reply; imhandlekey(&req); chanrecv(reply, &res); @@ -184,7 +183,7 @@ ownerrequestat(uvlong owner, int op, Rune key, u32int mod, Caret *caret) } static Keyres -ownerrequest(uvlong owner, int op, Rune key, u32int mod) +ownerrequest(void *owner, int op, Rune key, u32int mod) { return ownerrequestat(owner, op, key, mod, nil); } @@ -194,57 +193,75 @@ engine_active_owner_lifecycle(struct ct *t) { Keyres res; Str shown; - uvlong a, b, c; + char a, b, c; - a = ownernew(); - b = ownernew(); - c = ownernew(); - CT_CHECK(t, a != 0 && b != 0 && c != 0); - CT_CHECK(t, a != b && b != c && a != c); init(); im.l = getlang(LangJP); - res = ownerrequest(a, Keypress, 'k', 0); + res = ownerrequest(&a, Keypress, 'k', 0); CT_CHECK(t, res.eaten); - res = ownerrequest(a, Keypress, 'a', 0); + res = ownerrequest(&a, Keypress, 'a', 0); checkstr(t, "first owner preedit", "か", &res.preedit); - CT_EQ_UINT(t, a, activeowner); + CT_EQ_PTR(t, &a, activeowner); - res = ownerrequest(b, Keypress, 'n', 0); + res = ownerrequest(&b, Keypress, 'n', 0); checkstr(t, "takeover resets old preedit", "ん", &res.preedit); - CT_EQ_UINT(t, b, activeowner); - res = ownerrequest(a, Keyreset, 0, 0); + CT_EQ_PTR(t, &b, activeowner); + res = ownerrequest(&a, Keyreset, 0, 0); CT_EQ_INT(t, 0, res.preedit.n); shown = shownpre(&im); checkstr(t, "stale reset preserves owner", "ん", &shown); - CT_EQ_UINT(t, b, activeowner); + CT_EQ_PTR(t, &b, activeowner); - res = ownerrequest(b, Keypress, 'y', 0); - res = ownerrequest(b, Keypress, 'a', 0); + res = ownerrequest(&b, Keypress, 'y', 0); + res = ownerrequest(&b, Keypress, 'a', 0); checkstr(t, "current owner continues", "にゃ", &res.preedit); - ownerrequest(a, Keyrelease, 0, 0); + ownerrequest(&a, Keyrelease, 0, 0); shown = shownpre(&im); checkstr(t, "stale release preserves owner", "にゃ", &shown); - CT_EQ_UINT(t, b, activeowner); + CT_EQ_PTR(t, &b, activeowner); - ownerrequest(b, Keyrelease, 0, 0); - CT_EQ_UINT(t, 0, activeowner); + ownerrequest(&b, Keyrelease, 0, 0); + CT_EQ_PTR(t, nil, activeowner); CT_EQ_INT(t, 0, im.pre.n); CT_EQ_INT(t, 0, im.raw.n); - ownerrequest(c, Keypress, Kmodfirst, 0); - CT_EQ_UINT(t, 0, activeowner); - res = ownerrequest(c, Keypress, 'k', 0); - CT_EQ_UINT(t, c, activeowner); + ownerrequest(&c, Keypress, Kmodfirst, 0); + CT_EQ_PTR(t, nil, activeowner); + res = ownerrequest(&c, Keypress, 'k', 0); + CT_EQ_PTR(t, &c, activeowner); checkstr(t, "next owner first key", "k", &res.preedit); } +void +engine_active_owner_reset(struct ct *t) +{ + Caret at; + Keyres res; + char owner; + + memset(&at, 0, sizeof at); + at.valid = 1; + at.x = 10; + at.y = 20; + at.h = 14; + init(); + im.l = getlang(LangJP); + ownerrequestat(&owner, Keypress, 'k', 0, &at); + res = ownerrequest(&owner, Keypress, 'a', 0); + checkstr(t, "preedit before reset", "か", &res.preedit); + res = ownerrequest(&owner, Keyreset, 0, 0); + CT_EQ_PTR(t, &owner, activeowner); + CT_EQ_INT(t, 0, res.preedit.n); + CT_CHECK(t, !caret.valid); + res = ownerrequest(&owner, Keypress, 'n', 0); + checkstr(t, "same owner after reset", "ん", &res.preedit); +} + void engine_active_owner_caret(struct ct *t) { Caret a, moved; - uvlong one, two; + char one, two; - one = ownernew(); - two = ownernew(); memset(&a, 0, sizeof a); a.valid = 1; a.x = 10; @@ -254,15 +271,15 @@ engine_active_owner_caret(struct ct *t) moved.x = 80; init(); im.l = getlang(LangJP); - ownerrequestat(one, Keypress, 'k', 0, &a); + ownerrequestat(&one, Keypress, 'k', 0, &a); CT_CHECK(t, caret.valid); CT_EQ_INT(t, 10, caret.x); - ownerrequestat(two, Keycaret, 0, 0, &moved); + ownerrequestat(&two, Keycaret, 0, 0, &moved); CT_EQ_INT(t, 10, caret.x); - ownerrequestat(one, Keycaret, 0, 0, &moved); + ownerrequestat(&one, Keycaret, 0, 0, &moved); CT_EQ_INT(t, 80, caret.x); - ownerrequest(two, Keypress, 'n', 0); - CT_EQ_UINT(t, two, activeowner); + ownerrequest(&two, Keypress, 'n', 0); + CT_EQ_PTR(t, &two, activeowner); CT_CHECK(t, !caret.valid); } @@ -1430,7 +1447,8 @@ engine_randomized_stress(struct ct *t) Keyres res; Caret pos; u32int rnd, mod; - uvlong owners[3], owner; + char contexts[3]; + void *owner, *owners[3]; int i, j, op; vi = getlang(LangVI); @@ -1439,9 +1457,9 @@ engine_randomized_stress(struct ct *t) vimap = vi->map; vi->map = testvi.map; emojibegin(&f, 0); - owners[0] = ownernew(); - owners[1] = ownernew(); - owners[2] = ownernew(); + owners[0] = &contexts[0]; + owners[1] = &contexts[1]; + owners[2] = &contexts[2]; rnd = 0x5eed1234U; for(i = 0; i < 16000; i++){ rnd = stressrand(&rnd); @@ -1506,7 +1524,7 @@ engine_randomized_stress(struct ct *t) i = 16000; break; } - if(activeowner != 0 && activeowner != owners[0] && + if(activeowner != nil && activeowner != owners[0] && activeowner != owners[1] && activeowner != owners[2]){ CT_ERRORF(t, "unknown active owner after stress operation %d", i); break; diff --git a/tests/test.h b/tests/test.h index dc37e75..195e81d 100644 --- a/tests/test.h +++ b/tests/test.h @@ -34,6 +34,7 @@ void engine_selects_visible_candidate(struct ct*); void engine_candidate_shortcut_modifiers(struct ct*); void engine_dictionary_queue_latest_wins(struct ct*); void engine_active_owner_lifecycle(struct ct*); +void engine_active_owner_reset(struct ct*); void engine_active_owner_caret(struct ct*); void engine_commit_contract(struct ct*); void engine_language_switch_state(struct ct*); diff --git a/tests/unit_test.c b/tests/unit_test.c index 80a88be..9583dbf 100644 --- a/tests/unit_test.c +++ b/tests/unit_test.c @@ -88,6 +88,7 @@ static const struct ct_test tests[] = { { "engine/candidate-shortcut-modifiers", engine_candidate_shortcut_modifiers }, { "engine/dictionary-queue-latest", engine_dictionary_queue_latest_wins }, { "engine/active-owner-lifecycle", engine_active_owner_lifecycle }, + { "engine/active-owner-reset", engine_active_owner_reset }, { "engine/active-owner-caret", engine_active_owner_caret }, { "engine/commit-contract", engine_commit_contract }, { "engine/language-switch-state", engine_language_switch_state },