From b536573622dd4ce4d9082a07caab41d43c0e266a Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Fri, 14 Aug 2026 18:44:52 +0900 Subject: [PATCH] engine: update active preedit capability --- dat.h | 3 ++- strans.c | 24 +++++++++++++++++- tests/engine_test.c | 59 +++++++++++++++++++++++++++++++++------------ 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/dat.h b/dat.h index e3d2507..2dcbc69 100644 --- a/dat.h +++ b/dat.h @@ -147,10 +147,11 @@ enum Keyreset, Keyrelease, Keycaret, + Keycap, }; struct Keyres { - int eaten; + int eaten; /* Keycap: caller is active and capability was applied. */ Str commit; Str preedit; }; diff --git a/strans.c b/strans.c index 51da19a..fc4c441 100644 --- a/strans.c +++ b/strans.c @@ -783,6 +783,17 @@ meaningful(Keyreq *kr) return kr->ks != 0 && !ismodkey(kr->ks); } +static int +setactivecap(int cap) +{ + int old; + + old = activecap & Cclientpreedit; + activecap &= ~Cclientpreedit; + activecap |= cap & Cclientpreedit; + return old != (activecap & Cclientpreedit); +} + static void imhandlekey(Keyreq *kr) { @@ -809,13 +820,24 @@ imhandlekey(Keyreq *kr) show(); } break; + case Keycap: + res.eaten = 0; + if(activeowner != nil && kr->owner == activeowner){ + res.eaten = 1; + if(setactivecap(kr->cap)) + show(); + } + break; case Keypress: res.eaten = 0; + if(activeowner != nil && kr->owner == activeowner && + setactivecap(kr->cap)) + show(); if(meaningful(kr)){ if(kr->owner != activeowner){ reset(); activeowner = kr->owner; - activecap = kr->cap; + activecap = kr->cap & Cclientpreedit; caret = kr->caret; }else if(kr->caret.valid) caret = kr->caret; diff --git a/tests/engine_test.c b/tests/engine_test.c index d8cc725..a5303c3 100644 --- a/tests/engine_test.c +++ b/tests/engine_test.c @@ -728,7 +728,8 @@ engine_popup_preedit_capability(struct ct *t) { Dictres res; Drawcmd dc; - char client, popupowner; + Keyres kres; + char client, inactive; init(); im.l = getlang(LangJP); @@ -742,30 +743,56 @@ engine_popup_preedit_capability(struct ct *t) res.kouho[0] = mkstr("家"); res.nkouho = 1; dictresult(&res); + im.sel = 0; + show(); if(CT_CHECK(t, draindraw(&dc) > 0)){ CT_EQ_INT(t, 0, dc.pre.n); CT_EQ_INT(t, 1, dc.nkouho); + CT_EQ_INT(t, 0, dc.sel); checkstr(t, "client-preedit candidate", "家", &dc.kouho[0]); } - ownerrequestcap(&popupowner, 0, Keypress, 'n', 0); + kres = ownerrequestcap(&client, 0, Keycap, 0, 0); + CT_CHECK(t, kres.eaten); + checkstr(t, "capability response preedit", "か", &kres.preedit); if(CT_CHECK(t, draindraw(&dc) > 0)){ - checkstr(t, "popup preedit", "ん", &dc.pre); - CT_EQ_INT(t, 0, dc.nkouho); - } - memset(&res, 0, sizeof res); - res.lang = LangJP; - res.key = mkstr("ん"); - res.seq = dictseq; - res.kouho[0] = mkstr("ン"); - res.nkouho = 1; - dictresult(&res); - if(CT_CHECK(t, draindraw(&dc) > 0)){ - checkstr(t, "async popup preedit", "ん", &dc.pre); + checkstr(t, "popup preedit", "か", &dc.pre); CT_EQ_INT(t, 1, dc.nkouho); - checkstr(t, "popup candidate", "ン", &dc.kouho[0]); + CT_EQ_INT(t, 0, dc.sel); + checkstr(t, "popup candidate", "家", &dc.kouho[0]); } - ownerrequest(&popupowner, Keyrelease, 0, 0); + CT_EQ_INT(t, 1, im.nkouho); + CT_EQ_INT(t, 0, im.sel); + checkstr(t, "retained popup candidate", "家", &im.kouho[0]); + + kres = ownerrequestcap(&client, 0, Keycap, 0, 0); + CT_CHECK(t, kres.eaten); + CT_EQ_INT(t, 0, draindraw(nil)); + + kres = ownerrequestcap(&inactive, Cclientpreedit, Keycap, 0, 0); + CT_CHECK(t, !kres.eaten); + CT_EQ_INT(t, 0, kres.preedit.n); + CT_EQ_PTR(t, &client, activeowner); + CT_EQ_INT(t, 0, activecap & Cclientpreedit); + CT_EQ_INT(t, 0, draindraw(nil)); + + kres = ownerrequestcap(&client, Cclientpreedit, Keycap, 0, 0); + CT_CHECK(t, kres.eaten); + checkstr(t, "restored client preedit", "か", &kres.preedit); + if(CT_CHECK(t, draindraw(&dc) > 0)){ + CT_EQ_INT(t, 0, dc.pre.n); + CT_EQ_INT(t, 1, dc.nkouho); + CT_EQ_INT(t, 0, dc.sel); + checkstr(t, "restored client candidate", "家", &dc.kouho[0]); + } + CT_EQ_INT(t, 1, im.nkouho); + CT_EQ_INT(t, 0, im.sel); + checkstr(t, "retained client candidate", "家", &im.kouho[0]); + kres = ownerrequestcap(&client, Cclientpreedit, Keycap, 0, 0); + CT_CHECK(t, kres.eaten); + CT_EQ_INT(t, 0, draindraw(nil)); + + ownerrequest(&client, Keyrelease, 0, 0); draindraw(nil); }