fix: assign one active engine owner
This commit is contained in:
8
dat.h
8
dat.h
@@ -128,6 +128,12 @@ struct Drawcmd
|
|||||||
|
|
||||||
typedef struct Keyreq Keyreq;
|
typedef struct Keyreq Keyreq;
|
||||||
typedef struct Keyres Keyres;
|
typedef struct Keyres Keyres;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
Keypress,
|
||||||
|
Keyreset,
|
||||||
|
Keyrelease,
|
||||||
|
};
|
||||||
struct Keyres
|
struct Keyres
|
||||||
{
|
{
|
||||||
int eaten;
|
int eaten;
|
||||||
@@ -137,6 +143,8 @@ struct Keyres
|
|||||||
|
|
||||||
struct Keyreq
|
struct Keyreq
|
||||||
{
|
{
|
||||||
|
uvlong owner;
|
||||||
|
int op;
|
||||||
u32int ks;
|
u32int ks;
|
||||||
u32int mod;
|
u32int mod;
|
||||||
int want; /* nonzero: include preedit in reply */
|
int want; /* nonzero: include preedit in reply */
|
||||||
|
|||||||
1
fn.h
1
fn.h
@@ -35,6 +35,7 @@ Emit transvi(Im*, Rune);
|
|||||||
void backko(Im*);
|
void backko(Im*);
|
||||||
void backvi(Im*);
|
void backvi(Im*);
|
||||||
void dictsend(Im*, Str*);
|
void dictsend(Im*, Str*);
|
||||||
|
uvlong ownernew(void);
|
||||||
|
|
||||||
int srvreadkey(int, Keyreq*);
|
int srvreadkey(int, Keyreq*);
|
||||||
void srvthread(void*);
|
void srvthread(void*);
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ sendreset(Im *im)
|
|||||||
srvclose(im);
|
srvclose(im);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ipcpackreq(buf, 1, 0, Kesc);
|
ipcpackreset(buf, 1);
|
||||||
if(ipcsend(im->fd, buf, sizeof buf) < 0 ||
|
if(ipcsend(im->fd, buf, sizeof buf) < 0 ||
|
||||||
readresp(im, resp, sizeof(resp)) < 0)
|
readresp(im, resp, sizeof(resp)) < 0)
|
||||||
srvclose(im);
|
srvclose(im);
|
||||||
|
|||||||
12
ibus.c
12
ibus.c
@@ -32,6 +32,7 @@ static char addrfile[256];
|
|||||||
static int icctr;
|
static int icctr;
|
||||||
static int busctr;
|
static int busctr;
|
||||||
static Channel *replyc;
|
static Channel *replyc;
|
||||||
|
static uvlong owner;
|
||||||
|
|
||||||
static DBusHandlerResult onmsg(DBusConnection*, DBusMessage*, void*);
|
static DBusHandlerResult onmsg(DBusConnection*, DBusMessage*, void*);
|
||||||
|
|
||||||
@@ -212,6 +213,8 @@ sendkey(u32int ks, u32int mod, Keyres *res)
|
|||||||
{
|
{
|
||||||
Keyreq kr;
|
Keyreq kr;
|
||||||
|
|
||||||
|
kr.owner = owner;
|
||||||
|
kr.op = Keypress;
|
||||||
kr.ks = ks;
|
kr.ks = ks;
|
||||||
kr.mod = mod;
|
kr.mod = mod;
|
||||||
kr.want = 1;
|
kr.want = 1;
|
||||||
@@ -223,9 +226,15 @@ sendkey(u32int ks, u32int mod, Keyres *res)
|
|||||||
static void
|
static void
|
||||||
sendreset(void)
|
sendreset(void)
|
||||||
{
|
{
|
||||||
|
Keyreq kr;
|
||||||
Keyres res;
|
Keyres res;
|
||||||
|
|
||||||
sendkey(Kesc, 0, &res);
|
memset(&kr, 0, sizeof kr);
|
||||||
|
kr.owner = owner;
|
||||||
|
kr.op = Keyreset;
|
||||||
|
kr.reply = replyc;
|
||||||
|
chansend(keyc, &kr);
|
||||||
|
chanrecv(replyc, &res);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -561,6 +570,7 @@ ibusthread(void *_)
|
|||||||
if(ibusinit() < 0)
|
if(ibusinit() < 0)
|
||||||
return;
|
return;
|
||||||
replyc = chancreate(sizeof(Keyres), 0);
|
replyc = chancreate(sizeof(Keyres), 0);
|
||||||
|
owner = ownernew();
|
||||||
for(;;){
|
for(;;){
|
||||||
n = 0;
|
n = 0;
|
||||||
for(i = 0; i < nwatches && n < Maxwatches; i++){
|
for(i = 0; i < nwatches && n < Maxwatches; i++){
|
||||||
|
|||||||
17
ipc.c
17
ipc.c
@@ -25,7 +25,7 @@ void
|
|||||||
ipcpackreq(unsigned char req[Ipcreqsz], int want, unsigned int mod,
|
ipcpackreq(unsigned char req[Ipcreqsz], int want, unsigned int mod,
|
||||||
unsigned int key)
|
unsigned int key)
|
||||||
{
|
{
|
||||||
req[0] = want != 0;
|
req[0] = want ? Ipcreqwant : 0;
|
||||||
req[1] = mod;
|
req[1] = mod;
|
||||||
req[2] = key;
|
req[2] = key;
|
||||||
req[3] = key >> 8;
|
req[3] = key >> 8;
|
||||||
@@ -33,11 +33,18 @@ ipcpackreq(unsigned char req[Ipcreqsz], int want, unsigned int mod,
|
|||||||
req[5] = key >> 24;
|
req[5] = key >> 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipcpackreset(unsigned char req[Ipcreqsz], int want)
|
||||||
|
{
|
||||||
|
memset(req, 0, Ipcreqsz);
|
||||||
|
req[0] = Ipcreqreset | (want ? Ipcreqwant : 0);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ipcunpackreq(const unsigned char req[Ipcreqsz], int *want, unsigned int *mod,
|
ipcunpackreq(const unsigned char req[Ipcreqsz], int *want, unsigned int *mod,
|
||||||
unsigned int *key)
|
unsigned int *key)
|
||||||
{
|
{
|
||||||
*want = req[0] != 0;
|
*want = (req[0] & Ipcreqwant) != 0;
|
||||||
*mod = req[1] & Mmask;
|
*mod = req[1] & Mmask;
|
||||||
*key = (unsigned int)req[2] |
|
*key = (unsigned int)req[2] |
|
||||||
((unsigned int)req[3] << 8) |
|
((unsigned int)req[3] << 8) |
|
||||||
@@ -45,6 +52,12 @@ ipcunpackreq(const unsigned char req[Ipcreqsz], int *want, unsigned int *mod,
|
|||||||
((unsigned int)req[5] << 24);
|
((unsigned int)req[5] << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipcreqreset(const unsigned char req[Ipcreqsz])
|
||||||
|
{
|
||||||
|
return (req[0] & Ipcreqreset) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ipcpackresp(unsigned char *dst, size_t cap, int eaten,
|
ipcpackresp(unsigned char *dst, size_t cap, int eaten,
|
||||||
const char *commit, size_t ncommit, const char *preedit, size_t npreedit,
|
const char *commit, size_t ncommit, const char *preedit, size_t npreedit,
|
||||||
|
|||||||
10
ipc.h
10
ipc.h
@@ -6,7 +6,10 @@
|
|||||||
#define IPCPATH "/tmp/strans.%d"
|
#define IPCPATH "/tmp/strans.%d"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Request: [want-preedit, modifiers, key byte 0, ..., key byte 3].
|
* 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.
|
||||||
* Only Mmask modifier bits are retained.
|
* Only Mmask modifier bits are retained.
|
||||||
* Response: [eaten, commit-length-low, commit-length-high, commit...],
|
* Response: [eaten, commit-length-low, commit-length-high, commit...],
|
||||||
* followed, when requested, by
|
* followed, when requested, by
|
||||||
@@ -16,6 +19,9 @@
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
Ipcreqwant = 1<<0,
|
||||||
|
Ipcreqreset = 1<<1,
|
||||||
|
|
||||||
Kspec = 0x110000,
|
Kspec = 0x110000,
|
||||||
Kback = Kspec|0x08,
|
Kback = Kspec|0x08,
|
||||||
Ktab = Kspec|0x09,
|
Ktab = Kspec|0x09,
|
||||||
@@ -48,7 +54,9 @@ struct Ipcresp
|
|||||||
};
|
};
|
||||||
|
|
||||||
void ipcpackreq(unsigned char[Ipcreqsz], int, unsigned int, unsigned int);
|
void ipcpackreq(unsigned char[Ipcreqsz], int, unsigned int, unsigned int);
|
||||||
|
void ipcpackreset(unsigned char[Ipcreqsz], int);
|
||||||
void ipcunpackreq(const unsigned char[Ipcreqsz], int*, unsigned int*, unsigned int*);
|
void ipcunpackreq(const unsigned char[Ipcreqsz], int*, unsigned int*, unsigned int*);
|
||||||
|
int ipcreqreset(const unsigned char[Ipcreqsz]);
|
||||||
int ipcpackresp(unsigned char*, size_t, int, const char*, size_t, const char*, size_t, int);
|
int ipcpackresp(unsigned char*, size_t, int, const char*, size_t, const char*, size_t, int);
|
||||||
int ipcreadn(int, void*, size_t);
|
int ipcreadn(int, void*, size_t);
|
||||||
int ipcsend(int, const void*, size_t);
|
int ipcsend(int, const void*, size_t);
|
||||||
|
|||||||
25
srv.c
25
srv.c
@@ -4,6 +4,13 @@
|
|||||||
static char adir[40];
|
static char adir[40];
|
||||||
static Channel *clientc;
|
static Channel *clientc;
|
||||||
|
|
||||||
|
typedef struct Client Client;
|
||||||
|
struct Client
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
uvlong owner;
|
||||||
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
srvreadkey(int fd, Keyreq *kr)
|
srvreadkey(int fd, Keyreq *kr)
|
||||||
{
|
{
|
||||||
@@ -14,6 +21,7 @@ srvreadkey(int fd, Keyreq *kr)
|
|||||||
if(ipcreadn(fd, req, sizeof req) < 0)
|
if(ipcreadn(fd, req, sizeof req) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
ipcunpackreq(req, &want, &mod, &ks);
|
ipcunpackreq(req, &want, &mod, &ks);
|
||||||
|
kr->op = ipcreqreset(req) ? Keyreset : Keypress;
|
||||||
kr->ks = ks;
|
kr->ks = ks;
|
||||||
kr->mod = mod;
|
kr->mod = mod;
|
||||||
kr->want = want;
|
kr->want = want;
|
||||||
@@ -23,6 +31,7 @@ srvreadkey(int fd, Keyreq *kr)
|
|||||||
static void
|
static void
|
||||||
clientthread(void *arg)
|
clientthread(void *arg)
|
||||||
{
|
{
|
||||||
|
Client *client;
|
||||||
Channel *reply;
|
Channel *reply;
|
||||||
int fd;
|
int fd;
|
||||||
Keyreq kr;
|
Keyreq kr;
|
||||||
@@ -32,10 +41,12 @@ clientthread(void *arg)
|
|||||||
int n, ncommit, npreedit;
|
int n, ncommit, npreedit;
|
||||||
uchar token;
|
uchar token;
|
||||||
|
|
||||||
fd = (int)(uintptr)arg;
|
client = arg;
|
||||||
|
fd = client->fd;
|
||||||
threadsetname("client %d", fd);
|
threadsetname("client %d", fd);
|
||||||
reply = chancreate(sizeof(Keyres), 0);
|
reply = chancreate(sizeof(Keyres), 0);
|
||||||
kr.reply = reply;
|
kr.reply = reply;
|
||||||
|
kr.owner = client->owner;
|
||||||
while(srvreadkey(fd, &kr) == 0){
|
while(srvreadkey(fd, &kr) == 0){
|
||||||
chansend(keyc, &kr);
|
chansend(keyc, &kr);
|
||||||
chanrecv(reply, &res);
|
chanrecv(reply, &res);
|
||||||
@@ -46,8 +57,13 @@ clientthread(void *arg)
|
|||||||
if(n < 0 || ipcsend(fd, out, n) < 0)
|
if(n < 0 || ipcsend(fd, out, n) < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
kr.op = Keyrelease;
|
||||||
|
kr.want = 0;
|
||||||
|
chansend(keyc, &kr);
|
||||||
|
chanrecv(reply, &res);
|
||||||
chanfree(reply);
|
chanfree(reply);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
free(client);
|
||||||
chanrecv(clientc, &token);
|
chanrecv(clientc, &token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +81,7 @@ srvinit(void)
|
|||||||
void
|
void
|
||||||
srvthread(void*)
|
srvthread(void*)
|
||||||
{
|
{
|
||||||
|
Client *client;
|
||||||
char ldir[40];
|
char ldir[40];
|
||||||
int fd;
|
int fd;
|
||||||
uchar token;
|
uchar token;
|
||||||
@@ -81,9 +98,13 @@ srvthread(void*)
|
|||||||
close(fd);
|
close(fd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(proccreate(clientthread, (void*)(uintptr)fd, 8192) < 0){
|
client = emalloc(sizeof *client);
|
||||||
|
client->fd = fd;
|
||||||
|
client->owner = ownernew();
|
||||||
|
if(proccreate(clientthread, client, 8192) < 0){
|
||||||
chanrecv(clientc, &token);
|
chanrecv(clientc, &token);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
free(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
50
strans.c
50
strans.c
@@ -4,6 +4,9 @@
|
|||||||
static Im im;
|
static Im im;
|
||||||
static int popup = 0;
|
static int popup = 0;
|
||||||
static int visible = 0;
|
static int visible = 0;
|
||||||
|
static Lock ownerlock;
|
||||||
|
static uvlong ownerctr;
|
||||||
|
static uvlong activeowner;
|
||||||
static void dictqmap(Im*);
|
static void dictqmap(Im*);
|
||||||
static void dictqjp(Im*);
|
static void dictqjp(Im*);
|
||||||
static void backjp(Im*);
|
static void backjp(Im*);
|
||||||
@@ -18,6 +21,19 @@ struct Search
|
|||||||
};
|
};
|
||||||
static Search search;
|
static Search search;
|
||||||
|
|
||||||
|
uvlong
|
||||||
|
ownernew(void)
|
||||||
|
{
|
||||||
|
uvlong n;
|
||||||
|
|
||||||
|
lock(&ownerlock);
|
||||||
|
n = ++ownerctr;
|
||||||
|
if(n == 0)
|
||||||
|
n = ++ownerctr;
|
||||||
|
unlock(&ownerlock);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
Lang langs[] = {
|
Lang langs[] = {
|
||||||
{LangEN, nil, nil, nil, nil, nil, nil, nil},
|
{LangEN, nil, nil, nil, nil, nil, nil, nil},
|
||||||
{LangJP, "hira", "kanji", transmap, backjp, dictqjp, nil, nil},
|
{LangJP, "hira", "kanji", transmap, backjp, dictqjp, nil, nil},
|
||||||
@@ -128,6 +144,9 @@ reset(void)
|
|||||||
{
|
{
|
||||||
sclear(&im.pre);
|
sclear(&im.pre);
|
||||||
sclear(&im.raw);
|
sclear(&im.raw);
|
||||||
|
search.on = 0;
|
||||||
|
sclear(&search.raw);
|
||||||
|
sclear(&search.text);
|
||||||
clearkouho();
|
clearkouho();
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
@@ -715,9 +734,16 @@ init(void)
|
|||||||
memset(&im, 0, sizeof(im));
|
memset(&im, 0, sizeof(im));
|
||||||
im.l = getlang(LangEN);
|
im.l = getlang(LangEN);
|
||||||
memset(&search, 0, sizeof search);
|
memset(&search, 0, sizeof search);
|
||||||
|
activeowner = 0;
|
||||||
visible = 0;
|
visible = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
meaningful(Keyreq *kr)
|
||||||
|
{
|
||||||
|
return kr->ks != 0 && !ismodkey(kr->ks);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
imhandlekey(Keyreq *kr)
|
imhandlekey(Keyreq *kr)
|
||||||
{
|
{
|
||||||
@@ -725,8 +751,30 @@ imhandlekey(Keyreq *kr)
|
|||||||
|
|
||||||
sclear(&res.commit);
|
sclear(&res.commit);
|
||||||
sclear(&res.preedit);
|
sclear(&res.preedit);
|
||||||
|
res.eaten = 1;
|
||||||
|
switch(kr->op){
|
||||||
|
case Keyrelease:
|
||||||
|
if(kr->owner == activeowner){
|
||||||
|
reset();
|
||||||
|
activeowner = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Keyreset:
|
||||||
|
if(kr->owner == activeowner)
|
||||||
|
reset();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
res.eaten = 0;
|
||||||
|
if(meaningful(kr)){
|
||||||
|
if(kr->owner != activeowner){
|
||||||
|
reset();
|
||||||
|
activeowner = kr->owner;
|
||||||
|
}
|
||||||
res.eaten = keystroke(kr->ks, kr->mod, &res.commit);
|
res.eaten = keystroke(kr->ks, kr->mod, &res.commit);
|
||||||
if(kr->want){
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(kr->want && kr->owner == activeowner){
|
||||||
if(search.on)
|
if(search.on)
|
||||||
res.preedit = search.text;
|
res.preedit = search.text;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -155,6 +155,75 @@ engine_dictionary_queue_latest_wins(struct ct *t)
|
|||||||
dictreqc = saved;
|
dictreqc = saved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Keyres
|
||||||
|
ownerrequest(uvlong owner, int op, Rune key, u32int mod)
|
||||||
|
{
|
||||||
|
Channel *reply;
|
||||||
|
Keyreq req;
|
||||||
|
Keyres res;
|
||||||
|
|
||||||
|
reply = chancreate(sizeof(Keyres), 1);
|
||||||
|
memset(&req, 0, sizeof req);
|
||||||
|
req.owner = owner;
|
||||||
|
req.op = op;
|
||||||
|
req.ks = key;
|
||||||
|
req.mod = mod;
|
||||||
|
req.want = 1;
|
||||||
|
req.reply = reply;
|
||||||
|
imhandlekey(&req);
|
||||||
|
chanrecv(reply, &res);
|
||||||
|
chanfree(reply);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
engine_active_owner_lifecycle(struct ct *t)
|
||||||
|
{
|
||||||
|
Keyres res;
|
||||||
|
Str shown;
|
||||||
|
uvlong 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);
|
||||||
|
CT_CHECK(t, res.eaten);
|
||||||
|
res = ownerrequest(a, Keypress, 'a', 0);
|
||||||
|
checkstr(t, "first owner preedit", "か", &res.preedit);
|
||||||
|
CT_EQ_UINT(t, a, activeowner);
|
||||||
|
|
||||||
|
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_INT(t, 0, res.preedit.n);
|
||||||
|
shown = shownpre(&im);
|
||||||
|
checkstr(t, "stale reset preserves owner", "ん", &shown);
|
||||||
|
CT_EQ_UINT(t, b, activeowner);
|
||||||
|
|
||||||
|
res = ownerrequest(b, Keypress, 'y', 0);
|
||||||
|
res = ownerrequest(b, Keypress, 'a', 0);
|
||||||
|
checkstr(t, "current owner continues", "にゃ", &res.preedit);
|
||||||
|
ownerrequest(a, Keyrelease, 0, 0);
|
||||||
|
shown = shownpre(&im);
|
||||||
|
checkstr(t, "stale release preserves owner", "にゃ", &shown);
|
||||||
|
CT_EQ_UINT(t, b, activeowner);
|
||||||
|
|
||||||
|
ownerrequest(b, Keyrelease, 0, 0);
|
||||||
|
CT_EQ_UINT(t, 0, 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);
|
||||||
|
checkstr(t, "next owner first key", "k", &res.preedit);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
engine_commit_contract(struct ct *t)
|
engine_commit_contract(struct ct *t)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,4 +12,12 @@ ipc_masks_modifiers(struct ct *t)
|
|||||||
CT_EQ_INT(t, 1, want);
|
CT_EQ_INT(t, 1, want);
|
||||||
CT_EQ_UINT(t, Mctrl|Malt, mod);
|
CT_EQ_UINT(t, Mctrl|Malt, mod);
|
||||||
CT_EQ_UINT(t, 0x1f642, key);
|
CT_EQ_UINT(t, 0x1f642, key);
|
||||||
|
CT_CHECK(t, !ipcreqreset(buf));
|
||||||
|
|
||||||
|
ipcpackreset(buf, 1);
|
||||||
|
ipcunpackreq(buf, &want, &mod, &key);
|
||||||
|
CT_EQ_INT(t, 1, want);
|
||||||
|
CT_EQ_UINT(t, 0, mod);
|
||||||
|
CT_EQ_UINT(t, 0, key);
|
||||||
|
CT_CHECK(t, ipcreqreset(buf));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ void engine_backspace_clears_candidates(struct ct*);
|
|||||||
void engine_selects_visible_candidate(struct ct*);
|
void engine_selects_visible_candidate(struct ct*);
|
||||||
void engine_candidate_shortcut_modifiers(struct ct*);
|
void engine_candidate_shortcut_modifiers(struct ct*);
|
||||||
void engine_dictionary_queue_latest_wins(struct ct*);
|
void engine_dictionary_queue_latest_wins(struct ct*);
|
||||||
|
void engine_active_owner_lifecycle(struct ct*);
|
||||||
void engine_commit_contract(struct ct*);
|
void engine_commit_contract(struct ct*);
|
||||||
void engine_language_switch_state(struct ct*);
|
void engine_language_switch_state(struct ct*);
|
||||||
void engine_telex_history_bound(struct ct*);
|
void engine_telex_history_bound(struct ct*);
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ static const struct ct_test tests[] = {
|
|||||||
{ "engine/selects-visible-candidate", engine_selects_visible_candidate },
|
{ "engine/selects-visible-candidate", engine_selects_visible_candidate },
|
||||||
{ "engine/candidate-shortcut-modifiers", engine_candidate_shortcut_modifiers },
|
{ "engine/candidate-shortcut-modifiers", engine_candidate_shortcut_modifiers },
|
||||||
{ "engine/dictionary-queue-latest", engine_dictionary_queue_latest_wins },
|
{ "engine/dictionary-queue-latest", engine_dictionary_queue_latest_wins },
|
||||||
|
{ "engine/active-owner-lifecycle", engine_active_owner_lifecycle },
|
||||||
{ "engine/commit-contract", engine_commit_contract },
|
{ "engine/commit-contract", engine_commit_contract },
|
||||||
{ "engine/language-switch-state", engine_language_switch_state },
|
{ "engine/language-switch-state", engine_language_switch_state },
|
||||||
{ "engine/telex-history-bound", engine_telex_history_bound },
|
{ "engine/telex-history-bound", engine_telex_history_bound },
|
||||||
|
|||||||
17
wayland.c
17
wayland.c
@@ -26,12 +26,15 @@ static int active;
|
|||||||
static int pending;
|
static int pending;
|
||||||
static u32int imserial;
|
static u32int imserial;
|
||||||
static Channel *replyc;
|
static Channel *replyc;
|
||||||
|
static uvlong owner;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sendkey(u32int ks, u32int mod, Keyres *res)
|
sendkey(u32int ks, u32int mod, Keyres *res)
|
||||||
{
|
{
|
||||||
Keyreq kr;
|
Keyreq kr;
|
||||||
|
|
||||||
|
kr.owner = owner;
|
||||||
|
kr.op = Keypress;
|
||||||
kr.ks = ks;
|
kr.ks = ks;
|
||||||
kr.mod = mod;
|
kr.mod = mod;
|
||||||
kr.want = 1;
|
kr.want = 1;
|
||||||
@@ -41,11 +44,17 @@ sendkey(u32int ks, u32int mod, Keyres *res)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sendreset(void)
|
sendrelease(void)
|
||||||
{
|
{
|
||||||
|
Keyreq kr;
|
||||||
Keyres res;
|
Keyres res;
|
||||||
|
|
||||||
sendkey(Kesc, 0, &res);
|
memset(&kr, 0, sizeof kr);
|
||||||
|
kr.owner = owner;
|
||||||
|
kr.op = Keyrelease;
|
||||||
|
kr.reply = replyc;
|
||||||
|
chansend(keyc, &kr);
|
||||||
|
chanrecv(replyc, &res);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32int
|
static u32int
|
||||||
@@ -243,13 +252,15 @@ im_done(void *data, struct zwp_input_method_v2 *m)
|
|||||||
imserial++;
|
imserial++;
|
||||||
if(pending && !active){
|
if(pending && !active){
|
||||||
active = 1;
|
active = 1;
|
||||||
|
owner = ownernew();
|
||||||
grab = zwp_input_method_v2_grab_keyboard(im);
|
grab = zwp_input_method_v2_grab_keyboard(im);
|
||||||
if(grab != nil)
|
if(grab != nil)
|
||||||
zwp_input_method_keyboard_grab_v2_add_listener(grab,
|
zwp_input_method_keyboard_grab_v2_add_listener(grab,
|
||||||
&grab_listener, nil);
|
&grab_listener, nil);
|
||||||
}else if(!pending && active){
|
}else if(!pending && active){
|
||||||
active = 0;
|
active = 0;
|
||||||
sendreset();
|
sendrelease();
|
||||||
|
owner = 0;
|
||||||
if(grab != nil){
|
if(grab != nil){
|
||||||
zwp_input_method_keyboard_grab_v2_release(grab);
|
zwp_input_method_keyboard_grab_v2_release(grab);
|
||||||
grab = nil;
|
grab = nil;
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ reset(xcb_im_input_context_t *ic)
|
|||||||
{
|
{
|
||||||
unsigned char buf[Ipcreqsz];
|
unsigned char buf[Ipcreqsz];
|
||||||
|
|
||||||
ipcpackreq(buf, 0, 0, Kesc);
|
ipcpackreset(buf, 0);
|
||||||
if(srvconnect() < 0)
|
if(srvconnect() < 0)
|
||||||
return;
|
return;
|
||||||
if(ipcsend(srvfd, buf, sizeof buf) < 0 || readresp(ic) < 0)
|
if(ipcsend(srvfd, buf, sizeof buf) < 0 || readresp(ic) < 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user