fix: retain the active owner's caret

This commit is contained in:
2026-08-12 15:44:04 +09:00
parent 5ba5cf209c
commit bc5712b6ac
8 changed files with 70 additions and 2 deletions

13
dat.h
View File

@@ -118,12 +118,23 @@ struct Im
};
typedef struct Drawcmd Drawcmd;
typedef struct Caret Caret;
struct Caret
{
int valid;
int x;
int y;
int w;
int h;
};
struct Drawcmd
{
Str pre;
Str kouho[Maxdisp];
int nkouho;
int sel;
Caret caret;
};
typedef struct Keyreq Keyreq;
@@ -133,6 +144,7 @@ enum
Keypress,
Keyreset,
Keyrelease,
Keycaret,
};
struct Keyres
{
@@ -147,6 +159,7 @@ struct Keyreq
int op;
u32int ks;
u32int mod;
Caret caret;
int want; /* nonzero: include preedit in reply */
Channel *reply;
};

1
ibus.c
View File

@@ -213,6 +213,7 @@ sendkey(u32int ks, u32int mod, Keyres *res)
{
Keyreq kr;
memset(&kr, 0, sizeof kr);
kr.owner = owner;
kr.op = Keypress;
kr.ks = ks;

1
srv.c
View File

@@ -25,6 +25,7 @@ srvreadkey(int fd, Keyreq *kr)
kr->ks = ks;
kr->mod = mod;
kr->want = want;
memset(&kr->caret, 0, sizeof kr->caret);
return 0;
}

View File

@@ -7,6 +7,7 @@ static int visible = 0;
static Lock ownerlock;
static uvlong ownerctr;
static uvlong activeowner;
static Caret caret;
static void dictqmap(Im*);
static void dictqjp(Im*);
static void backjp(Im*);
@@ -128,6 +129,7 @@ show(void)
if(n > Maxdisp) n = Maxdisp;
dc.nkouho = n;
dc.sel = im.sel >= 0 ? im.sel - first : -1;
dc.caret = caret;
for(i = 0; i < n; i++)
dc.kouho[i] = im.kouho[first + i];
if(dc.pre.n == 0 && n == 0 && !visible)
@@ -147,6 +149,7 @@ reset(void)
search.on = 0;
sclear(&search.raw);
sclear(&search.text);
memset(&caret, 0, sizeof caret);
clearkouho();
show();
}
@@ -734,6 +737,7 @@ init(void)
memset(&im, 0, sizeof(im));
im.l = getlang(LangEN);
memset(&search, 0, sizeof search);
memset(&caret, 0, sizeof caret);
activeowner = 0;
visible = 0;
}
@@ -763,13 +767,21 @@ imhandlekey(Keyreq *kr)
if(kr->owner == activeowner)
reset();
break;
case Keycaret:
if(kr->owner == activeowner){
caret = kr->caret;
show();
}
break;
default:
res.eaten = 0;
if(meaningful(kr)){
if(kr->owner != activeowner){
reset();
activeowner = kr->owner;
}
caret = kr->caret;
}else if(kr->caret.valid)
caret = kr->caret;
res.eaten = keystroke(kr->ks, kr->mod, &res.commit);
}
break;

View File

@@ -156,7 +156,7 @@ engine_dictionary_queue_latest_wins(struct ct *t)
}
static Keyres
ownerrequest(uvlong owner, int op, Rune key, u32int mod)
ownerrequestat(uvlong owner, int op, Rune key, u32int mod, Caret *caret)
{
Channel *reply;
Keyreq req;
@@ -168,6 +168,8 @@ ownerrequest(uvlong owner, int op, Rune key, u32int mod)
req.op = op;
req.ks = key;
req.mod = mod;
if(caret != nil)
req.caret = *caret;
req.want = 1;
req.reply = reply;
imhandlekey(&req);
@@ -176,6 +178,12 @@ ownerrequest(uvlong owner, int op, Rune key, u32int mod)
return res;
}
static Keyres
ownerrequest(uvlong owner, int op, Rune key, u32int mod)
{
return ownerrequestat(owner, op, key, mod, nil);
}
void
engine_active_owner_lifecycle(struct ct *t)
{
@@ -224,6 +232,36 @@ engine_active_owner_lifecycle(struct ct *t)
checkstr(t, "next owner first key", "k", &res.preedit);
}
void
engine_active_owner_caret(struct ct *t)
{
Caret a, moved;
uvlong one, two;
one = ownernew();
two = ownernew();
memset(&a, 0, sizeof a);
a.valid = 1;
a.x = 10;
a.y = 20;
a.w = 3;
a.h = 14;
moved = a;
moved.x = 80;
init();
im.l = getlang(LangJP);
ownerrequestat(one, Keypress, 'k', 0, &a);
CT_CHECK(t, caret.valid);
CT_EQ_INT(t, 10, caret.x);
ownerrequestat(two, Keycaret, 0, 0, &moved);
CT_EQ_INT(t, 10, caret.x);
ownerrequestat(one, Keycaret, 0, 0, &moved);
CT_EQ_INT(t, 80, caret.x);
ownerrequest(two, Keypress, 'n', 0);
CT_EQ_UINT(t, two, activeowner);
CT_CHECK(t, !caret.valid);
}
void
engine_commit_contract(struct ct *t)
{

View File

@@ -35,6 +35,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_caret(struct ct*);
void engine_commit_contract(struct ct*);
void engine_language_switch_state(struct ct*);
void engine_telex_history_bound(struct ct*);

View File

@@ -84,6 +84,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-caret", engine_active_owner_caret },
{ "engine/commit-contract", engine_commit_contract },
{ "engine/language-switch-state", engine_language_switch_state },
{ "engine/telex-history-bound", engine_telex_history_bound },

View File

@@ -33,6 +33,7 @@ sendkey(u32int ks, u32int mod, Keyres *res)
{
Keyreq kr;
memset(&kr, 0, sizeof kr);
kr.owner = owner;
kr.op = Keypress;
kr.ks = ks;