diff --git a/README.md b/README.md index 0e7338f..bef85ad 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,6 @@ Vietnamese Telex is also available as a compatibility mode. | `Ctrl+V` | Vietnamese Telex | | `Ctrl+E` | Emoji and symbol search | | `Ctrl+H` | One-shot Hanja search | -| `Ctrl+P` | Toggle popup preedit | Use `Up`/`Down` to move through candidates, `Enter` or `1`-`9` to select, `Tab` to cycle temporary search results, and `Esc` to cancel. `0` commits the diff --git a/dat.h b/dat.h index e08250a..63262b1 100644 --- a/dat.h +++ b/dat.h @@ -138,6 +138,10 @@ struct Drawcmd typedef struct Keyreq Keyreq; typedef struct Keyres Keyres; enum +{ + Cclientpreedit = 1<<0, +}; +enum { Keypress, Keyreset, @@ -154,6 +158,7 @@ struct Keyres struct Keyreq { void *owner; /* stable until the context's release is acknowledged */ + int cap; int op; u32int ks; u32int mod; diff --git a/ibus.c b/ibus.c index 31320a0..fff3588 100644 --- a/ibus.c +++ b/ibus.c @@ -303,6 +303,7 @@ sendrequest(Ictx *ctx, int op, u32int ks, u32int mod, Keyres *res) memset(&kr, 0, sizeof kr); kr.owner = ctx; + kr.cap = Cclientpreedit; kr.op = op; kr.ks = ks; kr.mod = mod; diff --git a/srv.c b/srv.c index 45eedf0..4178069 100644 --- a/srv.c +++ b/srv.c @@ -41,6 +41,7 @@ clientthread(void *arg) reply = chancreate(sizeof(Keyres), 0); kr.reply = reply; kr.owner = &fd; + kr.cap = Cclientpreedit; while((want = srvreadkey(fd, &kr)) >= 0){ chansend(keyc, &kr); chanrecv(reply, &res); diff --git a/strans.c b/strans.c index d1c8b98..41e2039 100644 --- a/strans.c +++ b/strans.c @@ -2,9 +2,9 @@ #include "fn.h" static Im im; -static int popup = 0; static int visible = 0; static void *activeowner; +static int activecap; static Caret caret; static void dictqmap(Im*); static void dictqjp(Im*); @@ -105,7 +105,7 @@ show(void) pre = search.text; else impre(&pre); - if(popup){ + if(!(activecap & Cclientpreedit)){ if(search.lang || isjp(&im) || im.l->map == nil || !mapget(im.l->map, &pre, &dc.pre)) dc.pre = pre; @@ -632,11 +632,6 @@ searchkey(u32int ks, u32int mod, Str *com) startsearch(n, com); return 1; } - if(c == 0x10){ - popup = !popup; - show(); - return 1; - } endsearch(); if(setlang(c)) return 1; @@ -725,11 +720,6 @@ keystroke(u32int ks, u32int mod, Str *com) startsearch(n, com); return 1; } - if(c == 0x10){ - popup = !popup; - show(); - return 1; - } if(getlang(c) != nil){ if(isjp(&im) && haspre(&im)) commit(com); @@ -778,6 +768,7 @@ init(void) memset(&search, 0, sizeof search); memset(&caret, 0, sizeof caret); activeowner = nil; + activecap = 0; visible = 0; } @@ -800,6 +791,7 @@ imhandlekey(Keyreq *kr) if(kr->owner == activeowner){ reset(); activeowner = nil; + activecap = 0; } break; case Keyreset: @@ -818,6 +810,7 @@ imhandlekey(Keyreq *kr) if(kr->owner != activeowner){ reset(); activeowner = kr->owner; + activecap = kr->cap; caret = kr->caret; }else if(kr->caret.valid) caret = kr->caret; diff --git a/tests/engine_test.c b/tests/engine_test.c index 3f853ba..599aecb 100644 --- a/tests/engine_test.c +++ b/tests/engine_test.c @@ -192,7 +192,8 @@ engine_dictionary_queue_latest_wins(struct ct *t) } static Keyres -ownerrequestat(void *owner, int op, Rune key, u32int mod, Caret *caret) +ownerrequestatcap(void *owner, int cap, int op, Rune key, u32int mod, + Caret *caret) { Channel *reply; Keyreq req; @@ -201,6 +202,7 @@ ownerrequestat(void *owner, int op, Rune key, u32int mod, Caret *caret) reply = chancreate(sizeof(Keyres), 1); memset(&req, 0, sizeof req); req.owner = owner; + req.cap = cap; req.op = op; req.ks = key; req.mod = mod; @@ -213,12 +215,24 @@ ownerrequestat(void *owner, int op, Rune key, u32int mod, Caret *caret) return res; } +static Keyres +ownerrequestat(void *owner, int op, Rune key, u32int mod, Caret *caret) +{ + return ownerrequestatcap(owner, 0, op, key, mod, caret); +} + static Keyres ownerrequest(void *owner, int op, Rune key, u32int mod) { return ownerrequestat(owner, op, key, mod, nil); } +static Keyres +ownerrequestcap(void *owner, int cap, int op, Rune key, u32int mod) +{ + return ownerrequestatcap(owner, cap, op, key, mod, nil); +} + void engine_active_owner_lifecycle(struct ct *t) { @@ -566,7 +580,7 @@ struct Searchfix Search search; Lang *dictlang; Hmap *dict; - int popup; + int activecap; int visible; }; @@ -601,7 +615,7 @@ searchsave(Searchfix *f, int lang) f->search = search; f->dictlang = getlang(lang); f->dict = f->dictlang->dict; - f->popup = popup; + f->activecap = activecap; f->visible = visible; draindraw(nil); } @@ -629,7 +643,7 @@ emojibegin(Searchfix *f, int showpre) "c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12"); init(); im.l = getlang(LangKO); - popup = showpre; + activecap = showpre ? 0 : Cclientpreedit; } static void @@ -643,10 +657,54 @@ searchend(Searchfix *f) draindraw(nil); im = f->im; search = f->search; - popup = f->popup; + activecap = f->activecap; visible = f->visible; } +void +engine_popup_preedit_capability(struct ct *t) +{ + Dictres res; + Drawcmd dc; + char client, popupowner; + + init(); + im.l = getlang(LangJP); + draindraw(nil); + ownerrequestcap(&client, Cclientpreedit, Keypress, 'k', 0); + ownerrequestcap(&client, Cclientpreedit, Keypress, 'a', 0); + memset(&res, 0, sizeof res); + res.lang = LangJP; + res.key = mkstr("か"); + res.kouho[0] = mkstr("家"); + res.nkouho = 1; + dictresult(&res); + if(CT_CHECK(t, draindraw(&dc) > 0)){ + CT_EQ_INT(t, 0, dc.pre.n); + CT_EQ_INT(t, 1, dc.nkouho); + checkstr(t, "client-preedit candidate", "家", &dc.kouho[0]); + } + + ownerrequestcap(&popupowner, 0, Keypress, 'n', 0); + 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.kouho[0] = mkstr("ン"); + res.nkouho = 1; + dictresult(&res); + if(CT_CHECK(t, draindraw(&dc) > 0)){ + checkstr(t, "async popup preedit", "ん", &dc.pre); + CT_EQ_INT(t, 1, dc.nkouho); + checkstr(t, "popup candidate", "ン", &dc.kouho[0]); + } + ownerrequest(&popupowner, Keyrelease, 0, 0); + draindraw(nil); +} + static void hanjabegin(Searchfix *f, int lang) { @@ -841,10 +899,8 @@ engine_emoji_single_candidate(struct ct *t) Searchfix f; Str com; - emojibegin(&f, 1); + emojibegin(&f, 0); sclear(&com); - CT_CHECK(t, keystroke('p', Mctrl, &com)); - CT_EQ_INT(t, 0, popup); CT_CHECK(t, keystroke('e', Mctrl, &com)); CT_CHECK(t, search.lang); CT_EQ_INT(t, LangKO, im.l->lang); @@ -1083,7 +1139,6 @@ engine_emoji_preedit_languages(struct ct *t) { Searchfix f; Str com, shown; - int p; emojibegin(&f, 0); init(); @@ -1105,15 +1160,10 @@ engine_emoji_preedit_languages(struct ct *t) CT_CHECK(t, keystroke('E', Mctrl|Mshift, &com)); CT_EQ_INT(t, LangJP, im.l->lang); CT_CHECK(t, keystroke('a', 0, &com)); - p = popup; CT_CHECK(t, !keystroke(Kmodfirst+2, 0, &com)); CT_CHECK(t, search.lang); checkstr(t, "modifier preserves search", "a", &search.text); - CT_CHECK(t, keystroke('P', Mctrl|Mshift, &com)); - CT_EQ_INT(t, !p, popup); - CT_CHECK(t, search.lang); - CT_CHECK(t, !keystroke(Kmodfirst+2, 0, &com)); - CT_CHECK(t, keystroke('E', Mctrl|Mshift, &com)); + CT_CHECK(t, !keystroke('P', Mctrl|Mshift, &com)); CT_CHECK(t, !search.lang); sclear(&com); if(typekeys(t, "na", &com)){ diff --git a/tests/ibus_test.c b/tests/ibus_test.c index 77c88ae..a8a6128 100644 --- a/tests/ibus_test.c +++ b/tests/ibus_test.c @@ -238,6 +238,7 @@ nexttrace(struct ct *t, Ibusfix *f, int op, Ictx *ctx) return req; CT_EQ_INT(t, op, req.op); CT_EQ_PTR(t, ctx, req.owner); + CT_EQ_INT(t, Cclientpreedit, req.cap); CT_EQ_PTR(t, replyc, req.reply); return req; } diff --git a/tests/server_test.c b/tests/server_test.c index 954a92e..c6a76e1 100644 --- a/tests/server_test.c +++ b/tests/server_test.c @@ -149,6 +149,7 @@ nextrequest(struct ct *t, Enginegate *g, int op) memset(&req, 0, sizeof req); chanrecv(g->seen, &req); CT_EQ_INT(t, op, req.op); + CT_EQ_INT(t, Cclientpreedit, req.cap); return req; } diff --git a/tests/test.h b/tests/test.h index a50ccd9..04ead8a 100644 --- a/tests/test.h +++ b/tests/test.h @@ -36,6 +36,7 @@ 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_popup_preedit_capability(struct ct*); void engine_commit_contract(struct ct*); void engine_language_switch_state(struct ct*); void engine_telex_history_bound(struct ct*); diff --git a/tests/unit_test.c b/tests/unit_test.c index 0ca7813..4201d0a 100644 --- a/tests/unit_test.c +++ b/tests/unit_test.c @@ -90,6 +90,7 @@ static const struct ct_test tests[] = { { "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/popup-preedit-capability", engine_popup_preedit_capability }, { "engine/commit-contract", engine_commit_contract }, { "engine/language-switch-state", engine_language_switch_state }, { "engine/telex-history-bound", engine_telex_history_bound },