fix(frontends): preserve preedit lifecycle
This commit is contained in:
35
gtk/main.c
35
gtk/main.c
@@ -50,7 +50,7 @@ setpreedit(Im *im, const char *s, int n)
|
|||||||
|
|
||||||
if(n < 0 || n > Ipcfieldmax)
|
if(n < 0 || n > Ipcfieldmax)
|
||||||
n = 0;
|
n = 0;
|
||||||
if(n == im->prelen && memcmp(im->pre, s, n) == 0)
|
if(n == 0 && im->prelen == 0)
|
||||||
return;
|
return;
|
||||||
was = im->prelen;
|
was = im->prelen;
|
||||||
if(n > 0)
|
if(n > 0)
|
||||||
@@ -94,12 +94,10 @@ validtext(const char *s, size_t n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
readresp(Im *im, int want, int update, char *commit, int ncommit,
|
readresp(Im *im, int want, char *commit, int ncommit, char *pre, int npre,
|
||||||
Ipcresp *resp)
|
Ipcresp *resp)
|
||||||
{
|
{
|
||||||
char pre[Ipcfieldmax+1];
|
if(ipcreadresp(im->fd, want, commit, ncommit, pre, npre,
|
||||||
|
|
||||||
if(ipcreadresp(im->fd, want, commit, ncommit, pre, sizeof pre,
|
|
||||||
resp) < 0)
|
resp) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if(!validtext(commit, resp->commitlen) ||
|
if(!validtext(commit, resp->commitlen) ||
|
||||||
@@ -107,8 +105,6 @@ readresp(Im *im, int want, int update, char *commit, int ncommit,
|
|||||||
errno = EPROTO;
|
errno = EPROTO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(update)
|
|
||||||
setpreedit(im, pre, resp->preeditlen);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,6 +195,7 @@ srvconnect(Im *im)
|
|||||||
{
|
{
|
||||||
unsigned char buf[Ipcreqsz];
|
unsigned char buf[Ipcreqsz];
|
||||||
char commit[Ipcfieldmax+1];
|
char commit[Ipcfieldmax+1];
|
||||||
|
char pre[Ipcfieldmax+1];
|
||||||
Ipcresp resp;
|
Ipcresp resp;
|
||||||
|
|
||||||
if(im->fd >= 0)
|
if(im->fd >= 0)
|
||||||
@@ -209,11 +206,13 @@ srvconnect(Im *im)
|
|||||||
/* Marker zero is an old daemon's harmless key-zero response. */
|
/* Marker zero is an old daemon's harmless key-zero response. */
|
||||||
ipcpackcap(buf, im->usepreedit);
|
ipcpackcap(buf, im->usepreedit);
|
||||||
if(ipcsend(im->fd, buf, sizeof buf) < 0 ||
|
if(ipcsend(im->fd, buf, sizeof buf) < 0 ||
|
||||||
readresp(im, im->usepreedit, im->usepreedit, commit,
|
readresp(im, im->usepreedit, commit, sizeof commit,
|
||||||
sizeof commit, &resp) < 0){
|
pre, sizeof pre, &resp) < 0){
|
||||||
srvclose(im);
|
srvclose(im);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if(im->usepreedit)
|
||||||
|
setpreedit(im, pre, resp.preeditlen);
|
||||||
im->ext = resp.eaten != 0;
|
im->ext = resp.eaten != 0;
|
||||||
if(!im->usepreedit)
|
if(!im->usepreedit)
|
||||||
setpreedit(im, "", 0);
|
setpreedit(im, "", 0);
|
||||||
@@ -293,6 +292,7 @@ sendreset(Im *im)
|
|||||||
{
|
{
|
||||||
unsigned char buf[Ipcreqsz];
|
unsigned char buf[Ipcreqsz];
|
||||||
char commit[Ipcfieldmax+1];
|
char commit[Ipcfieldmax+1];
|
||||||
|
char pre[Ipcfieldmax+1];
|
||||||
Ipcresp resp;
|
Ipcresp resp;
|
||||||
|
|
||||||
if(im->fd < 0){
|
if(im->fd < 0){
|
||||||
@@ -301,8 +301,8 @@ sendreset(Im *im)
|
|||||||
}
|
}
|
||||||
ipcpackreset(buf, im->usepreedit);
|
ipcpackreset(buf, im->usepreedit);
|
||||||
if(ipcsend(im->fd, buf, sizeof buf) < 0 ||
|
if(ipcsend(im->fd, buf, sizeof buf) < 0 ||
|
||||||
readresp(im, im->usepreedit, 0, commit,
|
readresp(im, im->usepreedit, commit, sizeof commit,
|
||||||
sizeof commit, &resp) < 0){
|
pre, sizeof pre, &resp) < 0){
|
||||||
srvclose(im);
|
srvclose(im);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -315,6 +315,7 @@ kpress(GtkIMContext *ctx, GdkEventKey *ev)
|
|||||||
Im *im;
|
Im *im;
|
||||||
unsigned char buf[Ipcreqsz];
|
unsigned char buf[Ipcreqsz];
|
||||||
char commit[Ipcfieldmax+1];
|
char commit[Ipcfieldmax+1];
|
||||||
|
char pre[Ipcfieldmax+1];
|
||||||
uint32_t key, mod;
|
uint32_t key, mod;
|
||||||
Ipcresp resp;
|
Ipcresp resp;
|
||||||
|
|
||||||
@@ -339,13 +340,15 @@ kpress(GtkIMContext *ctx, GdkEventKey *ev)
|
|||||||
}
|
}
|
||||||
ipcpackreq(buf, im->usepreedit, mod, key);
|
ipcpackreq(buf, im->usepreedit, mod, key);
|
||||||
if(ipcsend(im->fd, buf, sizeof buf) < 0 ||
|
if(ipcsend(im->fd, buf, sizeof buf) < 0 ||
|
||||||
readresp(im, im->usepreedit, im->usepreedit, commit,
|
readresp(im, im->usepreedit, commit, sizeof commit,
|
||||||
sizeof commit, &resp) < 0){
|
pre, sizeof pre, &resp) < 0){
|
||||||
srvclose(im);
|
srvclose(im);
|
||||||
return simplefilter(ctx, ev, 0);
|
return simplefilter(ctx, ev, 0);
|
||||||
}
|
}
|
||||||
if(commit[0] != '\0')
|
if(commit[0] != '\0')
|
||||||
g_signal_emit_by_name(ctx, "commit", commit);
|
g_signal_emit_by_name(ctx, "commit", commit);
|
||||||
|
if(im->usepreedit)
|
||||||
|
setpreedit(im, pre, resp.preeditlen);
|
||||||
if(resp.eaten)
|
if(resp.eaten)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
return simplefilter(ctx, ev, 0);
|
return simplefilter(ctx, ev, 0);
|
||||||
@@ -407,6 +410,7 @@ setusepreedit(GtkIMContext *ctx, gboolean use)
|
|||||||
Im *im;
|
Im *im;
|
||||||
unsigned char buf[Ipcreqsz];
|
unsigned char buf[Ipcreqsz];
|
||||||
char commit[Ipcfieldmax+1];
|
char commit[Ipcfieldmax+1];
|
||||||
|
char pre[Ipcfieldmax+1];
|
||||||
Ipcresp resp;
|
Ipcresp resp;
|
||||||
|
|
||||||
im = (Im*)ctx;
|
im = (Im*)ctx;
|
||||||
@@ -422,11 +426,14 @@ setusepreedit(GtkIMContext *ctx, gboolean use)
|
|||||||
return;
|
return;
|
||||||
ipcpackcap(buf, use);
|
ipcpackcap(buf, use);
|
||||||
if(ipcsend(im->fd, buf, sizeof buf) < 0 ||
|
if(ipcsend(im->fd, buf, sizeof buf) < 0 ||
|
||||||
readresp(im, use, use, commit, sizeof commit, &resp) < 0 ||
|
readresp(im, use, commit, sizeof commit,
|
||||||
|
pre, sizeof pre, &resp) < 0 ||
|
||||||
!resp.eaten){
|
!resp.eaten){
|
||||||
srvclose(im);
|
srvclose(im);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(use)
|
||||||
|
setpreedit(im, pre, resp.preeditlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
28
ibus.c
28
ibus.c
@@ -55,10 +55,12 @@ static int icctr;
|
|||||||
static int busctr;
|
static int busctr;
|
||||||
static Channel *replyc;
|
static Channel *replyc;
|
||||||
static const char ibusowner[] = ":1.0";
|
static const char ibusowner[] = ":1.0";
|
||||||
|
static Ictx *preowner;
|
||||||
|
|
||||||
static DBusHandlerResult onmsg(DBusConnection*, DBusMessage*, void*);
|
static DBusHandlerResult onmsg(DBusConnection*, DBusMessage*, void*);
|
||||||
static DBusHandlerResult handleerror(DBusConnection*, DBusMessage*,
|
static DBusHandlerResult handleerror(DBusConnection*, DBusMessage*,
|
||||||
const char*, const char*);
|
const char*, const char*);
|
||||||
|
static void checkpreowner(void);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
unlinkaddr(void)
|
unlinkaddr(void)
|
||||||
@@ -355,6 +357,8 @@ static void
|
|||||||
dropcontext(Ictx *ctx)
|
dropcontext(Ictx *ctx)
|
||||||
{
|
{
|
||||||
releasecontext(ctx);
|
releasecontext(ctx);
|
||||||
|
if(preowner == ctx)
|
||||||
|
preowner = nil;
|
||||||
memset(ctx, 0, sizeof *ctx);
|
memset(ctx, 0, sizeof *ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,6 +386,8 @@ processkey(Ictx *ctx, u32int sym, u32int state, Keyres *res)
|
|||||||
if(state & Relmask || !ctx->focused || hidden(ctx))
|
if(state & Relmask || !ctx->focused || hidden(ctx))
|
||||||
return 0;
|
return 0;
|
||||||
sendrequest(ctx, Keypress, kget(sym), mget(state), res);
|
sendrequest(ctx, Keypress, kget(sym), mget(state), res);
|
||||||
|
if(preowner != nil && preowner != ctx)
|
||||||
|
checkpreowner();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,10 +494,29 @@ emitpreedit(Ictx *ctx, const char *text)
|
|||||||
dbus_message_iter_append_basic(&it, DBUS_TYPE_UINT32, &mode);
|
dbus_message_iter_append_basic(&it, DBUS_TYPE_UINT32, &mode);
|
||||||
}
|
}
|
||||||
dbus_message_set_sender(sig, ibusowner);
|
dbus_message_set_sender(sig, ibusowner);
|
||||||
dbus_connection_send(ctx->conn, sig, nil);
|
if(dbus_connection_send(ctx->conn, sig, nil)){
|
||||||
|
if(text[0] != '\0')
|
||||||
|
preowner = ctx;
|
||||||
|
else if(preowner == ctx)
|
||||||
|
preowner = nil;
|
||||||
|
}
|
||||||
dbus_message_unref(sig);
|
dbus_message_unref(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
checkpreowner(void)
|
||||||
|
{
|
||||||
|
Ictx *ctx;
|
||||||
|
Keyres res;
|
||||||
|
|
||||||
|
ctx = preowner;
|
||||||
|
if(ctx == nil)
|
||||||
|
return;
|
||||||
|
sendrequest(ctx, Keycap, 0, 0, &res);
|
||||||
|
if(!res.eaten)
|
||||||
|
emitpreedit(ctx, "");
|
||||||
|
}
|
||||||
|
|
||||||
static DBusHandlerResult
|
static DBusHandlerResult
|
||||||
handlehello(DBusConnection *c, DBusMessage *m)
|
handlehello(DBusConnection *c, DBusMessage *m)
|
||||||
{
|
{
|
||||||
@@ -1183,5 +1208,6 @@ ibusthread(void *_)
|
|||||||
while(dbus_connection_dispatch(conns[i]) == DBUS_DISPATCH_DATA_REMAINS)
|
while(dbus_connection_dispatch(conns[i]) == DBUS_DISPATCH_DATA_REMAINS)
|
||||||
;
|
;
|
||||||
pruneconns();
|
pruneconns();
|
||||||
|
checkpreowner();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -396,7 +396,25 @@ engine_active_owner_caret(struct ct *t)
|
|||||||
void
|
void
|
||||||
engine_commit_contract(struct ct *t)
|
engine_commit_contract(struct ct *t)
|
||||||
{
|
{
|
||||||
Str com;
|
Keyres res;
|
||||||
|
Str all, com;
|
||||||
|
char owner;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
init();
|
||||||
|
im.l = getlang(LangKO);
|
||||||
|
sclear(&all);
|
||||||
|
for(i = 0; i < 3; i++){
|
||||||
|
res = ownerrequestcap(&owner, Cclientpreedit,
|
||||||
|
Keypress, 'z', 0);
|
||||||
|
CT_CHECK(t, res.eaten);
|
||||||
|
checkstr(t, "repeated consonant commit",
|
||||||
|
i == 0 ? "" : "ㅋ", &res.commit);
|
||||||
|
checkstr(t, "repeated consonant preedit", "ㅋ", &res.preedit);
|
||||||
|
sappend(&all, &res.commit);
|
||||||
|
}
|
||||||
|
sappend(&all, &res.preedit);
|
||||||
|
checkstr(t, "repeated consonant total", "ㅋㅋㅋ", &all);
|
||||||
|
|
||||||
init();
|
init();
|
||||||
im.l = getlang(LangJP);
|
im.l = getlang(LangJP);
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ enum
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
Rnormal,
|
Rnormal,
|
||||||
|
Rcommitpre,
|
||||||
Rbadcommit,
|
Rbadcommit,
|
||||||
Rbadpreedit,
|
Rbadpreedit,
|
||||||
};
|
};
|
||||||
@@ -156,7 +157,10 @@ sendresponse(Server *s, int fd, int eaten, int want, int key)
|
|||||||
commit = "";
|
commit = "";
|
||||||
ncommit = 0;
|
ncommit = 0;
|
||||||
npreedit = strlen(pre);
|
npreedit = strlen(pre);
|
||||||
if(key && response == Rbadcommit){
|
if(key && response == Rcommitpre){
|
||||||
|
commit = pre;
|
||||||
|
ncommit = npreedit;
|
||||||
|
}else if(key && response == Rbadcommit){
|
||||||
commit = "\xc3(";
|
commit = "\xc3(";
|
||||||
ncommit = 2;
|
ncommit = 2;
|
||||||
}else if(key && response == Rbadpreedit){
|
}else if(key && response == Rbadpreedit){
|
||||||
@@ -581,6 +585,7 @@ commit(GtkIMContext *ctx, gchar *s, Siglog *l)
|
|||||||
{
|
{
|
||||||
(void)ctx;
|
(void)ctx;
|
||||||
snprintf(l->commit, sizeof l->commit, "%s", s);
|
snprintf(l->commit, sizeof l->commit, "%s", s);
|
||||||
|
l->pre[0] = '\0';
|
||||||
logsig(l, 'K');
|
logsig(l, 'K');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -721,7 +726,7 @@ main(int argc, char **argv)
|
|||||||
rect.height = 19;
|
rect.height = 19;
|
||||||
gtk_im_context_set_cursor_location(ctx, &rect);
|
gtk_im_context_set_cursor_location(ctx, &rect);
|
||||||
Check(eventcount(&srv) == 0, "cursor reporting opened the socket");
|
Check(eventcount(&srv) == 0, "cursor reporting opened the socket");
|
||||||
setpre(&srv, "pre");
|
setpre(&srv, "");
|
||||||
Check(key(ctx, win, GDK_KEY_a), "initial key was not eaten");
|
Check(key(ctx, win, GDK_KEY_a), "initial key was not eaten");
|
||||||
Check(waitcount(&srv, 3), "initial protocol frames timed out");
|
Check(waitcount(&srv, 3), "initial protocol frames timed out");
|
||||||
e = getevent(&srv, 0);
|
e = getevent(&srv, 0);
|
||||||
@@ -739,8 +744,22 @@ main(int argc, char **argv)
|
|||||||
(oy + rect.y) * scale, rect.height * scale);
|
(oy + rect.y) * scale, rect.height * scale);
|
||||||
e = getevent(&srv, 2);
|
e = getevent(&srv, 2);
|
||||||
Check(e.type == Ekey && e.want == 1, "initial key framing changed");
|
Check(e.type == Ekey && e.want == 1, "initial key framing changed");
|
||||||
Check(strcmp(log.event, "SC") == 0 && strcmp(log.pre, "pre") == 0,
|
Check(log.n == 0, "initial empty preedit emitted %s", log.event);
|
||||||
"initial preedit signals were %s (%s)", log.event, log.pre);
|
setpre(&srv, "ㅋ");
|
||||||
|
clearlog(&log);
|
||||||
|
Check(key(ctx, win, GDK_KEY_z), "first preedit key was not eaten");
|
||||||
|
Check(strcmp(log.event, "SC") == 0 && strcmp(log.pre, "ㅋ") == 0,
|
||||||
|
"first preedit signals were %s (%s)", log.event, log.pre);
|
||||||
|
clearlog(&log);
|
||||||
|
setreply(&srv, 1, Rcommitpre, 0);
|
||||||
|
Check(key(ctx, win, GDK_KEY_z), "repeated preedit key was not eaten");
|
||||||
|
Check(strcmp(log.event, "KC") == 0 &&
|
||||||
|
strcmp(log.commit, "ㅋ") == 0 && strcmp(log.pre, "ㅋ") == 0,
|
||||||
|
"repeated preedit signals were %s (commit %s, preedit %s)",
|
||||||
|
log.event, log.commit, log.pre);
|
||||||
|
Check(g_utf8_strlen(log.commit, -1) + g_utf8_strlen(log.pre, -1) == 2,
|
||||||
|
"two physical keys produced commit %s and preedit %s",
|
||||||
|
log.commit, log.pre);
|
||||||
|
|
||||||
/* Unconsumed input uses GtkIMContextSimple, including its stateful forms. */
|
/* Unconsumed input uses GtkIMContextSimple, including its stateful forms. */
|
||||||
setpre(&srv, "");
|
setpre(&srv, "");
|
||||||
|
|||||||
@@ -8,12 +8,19 @@ typedef struct Log Log;
|
|||||||
struct Log
|
struct Log
|
||||||
{
|
{
|
||||||
GMainLoop *loop;
|
GMainLoop *loop;
|
||||||
|
int *waiting;
|
||||||
|
IBusInputContext *a;
|
||||||
|
IBusInputContext *clearctx;
|
||||||
int legacy;
|
int legacy;
|
||||||
int modern;
|
int modern;
|
||||||
int commit;
|
int commit;
|
||||||
int invalid;
|
int invalid;
|
||||||
int sawpreedit;
|
int sawpreedit;
|
||||||
int sawcommit;
|
int sawcommit;
|
||||||
|
int done;
|
||||||
|
int transfer;
|
||||||
|
int atext;
|
||||||
|
int aclear;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -38,10 +45,25 @@ legacy(IBusInputContext *ctx, IBusText *text, guint cursor,
|
|||||||
a->start_index != 0 || a->end_index != 1 ||
|
a->start_index != 0 || a->end_index != 1 ||
|
||||||
ibus_attr_list_get(attrs, 1) != NULL)
|
ibus_attr_list_get(attrs, 1) != NULL)
|
||||||
log->invalid = 1;
|
log->invalid = 1;
|
||||||
else
|
else{
|
||||||
log->sawpreedit = 1;
|
log->sawpreedit = 1;
|
||||||
|
if(log->transfer && ctx == log->a)
|
||||||
|
log->atext = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(log->loop != NULL && log->sawpreedit && log->sawcommit)
|
if(log->transfer && log->atext && !log->aclear && s[0] == '\0'){
|
||||||
|
if(cursor != 0 || visible)
|
||||||
|
log->invalid = 1;
|
||||||
|
else{
|
||||||
|
log->clearctx = ctx;
|
||||||
|
if(ctx == log->a)
|
||||||
|
log->aclear = 1;
|
||||||
|
else
|
||||||
|
log->invalid = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log->done = log->sawpreedit && log->sawcommit;
|
||||||
|
if(log->loop != NULL && log->waiting != NULL && *log->waiting)
|
||||||
g_main_loop_quit(log->loop);
|
g_main_loop_quit(log->loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +102,8 @@ commit(IBusInputContext *ctx, IBusText *text, void *arg)
|
|||||||
log->invalid = 1;
|
log->invalid = 1;
|
||||||
else
|
else
|
||||||
log->sawcommit = 1;
|
log->sawcommit = 1;
|
||||||
if(log->loop != NULL && log->sawpreedit && log->sawcommit)
|
log->done = log->sawpreedit && log->sawcommit;
|
||||||
|
if(log->loop != NULL && log->waiting != NULL && *log->waiting)
|
||||||
g_main_loop_quit(log->loop);
|
g_main_loop_quit(log->loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,12 +115,13 @@ timeout(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
waitdone(Log *log)
|
waitflag(Log *log, int *flag)
|
||||||
{
|
{
|
||||||
guint timer;
|
guint timer;
|
||||||
|
|
||||||
if(log->sawpreedit && log->sawcommit)
|
if(*flag)
|
||||||
return 1;
|
return 1;
|
||||||
|
log->waiting = flag;
|
||||||
log->loop = g_main_loop_new(NULL, FALSE);
|
log->loop = g_main_loop_new(NULL, FALSE);
|
||||||
timer = g_timeout_add_seconds(4, timeout, log->loop);
|
timer = g_timeout_add_seconds(4, timeout, log->loop);
|
||||||
g_main_loop_run(log->loop);
|
g_main_loop_run(log->loop);
|
||||||
@@ -105,14 +129,15 @@ waitdone(Log *log)
|
|||||||
g_source_remove(timer);
|
g_source_remove(timer);
|
||||||
g_main_loop_unref(log->loop);
|
g_main_loop_unref(log->loop);
|
||||||
log->loop = NULL;
|
log->loop = NULL;
|
||||||
return log->sawpreedit && log->sawcommit;
|
log->waiting = NULL;
|
||||||
|
return *flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
IBusBus *bus;
|
IBusBus *bus;
|
||||||
IBusInputContext *ctx;
|
IBusInputContext *a, *b;
|
||||||
Log log;
|
Log log;
|
||||||
int ok;
|
int ok;
|
||||||
|
|
||||||
@@ -127,6 +152,7 @@ main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
memset(&log, 0, sizeof log);
|
memset(&log, 0, sizeof log);
|
||||||
|
b = NULL;
|
||||||
ibus_init();
|
ibus_init();
|
||||||
bus = ibus_bus_new();
|
bus = ibus_bus_new();
|
||||||
if(bus == NULL || !ibus_bus_is_connected(bus)){
|
if(bus == NULL || !ibus_bus_is_connected(bus)){
|
||||||
@@ -134,36 +160,56 @@ main(int argc, char **argv)
|
|||||||
if(bus != NULL) g_object_unref(bus);
|
if(bus != NULL) g_object_unref(bus);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
ctx = ibus_bus_create_input_context(bus, "strans-libibus-smoke");
|
a = ibus_bus_create_input_context(bus, "strans-libibus-smoke-a");
|
||||||
if(ctx == NULL){
|
if(a == NULL){
|
||||||
fprintf(stderr, "ibus_client_smoke: cannot create input context\n");
|
fprintf(stderr, "ibus_client_smoke: cannot create input context\n");
|
||||||
g_object_unref(bus);
|
g_object_unref(bus);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
g_signal_connect(ctx, "update-preedit-text", G_CALLBACK(legacy), &log);
|
log.a = a;
|
||||||
g_signal_connect(ctx, "update-preedit-text-with-mode", G_CALLBACK(modern),
|
g_signal_connect(a, "update-preedit-text", G_CALLBACK(legacy), &log);
|
||||||
|
g_signal_connect(a, "update-preedit-text-with-mode", G_CALLBACK(modern),
|
||||||
&log);
|
&log);
|
||||||
g_signal_connect(ctx, "commit-text", G_CALLBACK(commit), &log);
|
g_signal_connect(a, "commit-text", G_CALLBACK(commit), &log);
|
||||||
ibus_input_context_set_capabilities(ctx, IBUS_CAP_PREEDIT_TEXT);
|
ibus_input_context_set_capabilities(a, IBUS_CAP_PREEDIT_TEXT);
|
||||||
ibus_input_context_focus_in(ctx);
|
ibus_input_context_focus_in(a);
|
||||||
ok = ibus_input_context_process_key_event(ctx, 'n', 0, IBUS_CONTROL_MASK) &&
|
ok = ibus_input_context_process_key_event(a, 'n', 0, IBUS_CONTROL_MASK) &&
|
||||||
ibus_input_context_process_key_event(ctx, 'k', 0, 0) &&
|
ibus_input_context_process_key_event(a, 'k', 0, 0) &&
|
||||||
ibus_input_context_process_key_event(ctx, 'a', 0, 0) &&
|
ibus_input_context_process_key_event(a, 'a', 0, 0) &&
|
||||||
ibus_input_context_process_key_event(ctx, '0', 0, 0) &&
|
ibus_input_context_process_key_event(a, '0', 0, 0) &&
|
||||||
waitdone(&log);
|
waitflag(&log, &log.done);
|
||||||
ibus_input_context_focus_out(ctx);
|
b = ibus_bus_create_input_context(bus, "strans-libibus-smoke-b");
|
||||||
if(log.legacy == 0 || log.modern != 0 || log.commit != 1 ||
|
if(b == NULL)
|
||||||
log.invalid || !log.sawpreedit || !log.sawcommit)
|
|
||||||
ok = 0;
|
ok = 0;
|
||||||
g_object_unref(ctx);
|
else{
|
||||||
|
g_signal_connect(b, "update-preedit-text", G_CALLBACK(legacy), &log);
|
||||||
|
g_signal_connect(b, "update-preedit-text-with-mode",
|
||||||
|
G_CALLBACK(modern), &log);
|
||||||
|
ibus_input_context_set_capabilities(b, IBUS_CAP_PREEDIT_TEXT);
|
||||||
|
log.transfer = 1;
|
||||||
|
ok = ok && ibus_input_context_process_key_event(a, 'k', 0, 0) &&
|
||||||
|
waitflag(&log, &log.atext);
|
||||||
|
ibus_input_context_focus_in(b);
|
||||||
|
ok = ok && ibus_input_context_process_key_event(b, 'n', 0, 0) &&
|
||||||
|
waitflag(&log, &log.aclear);
|
||||||
|
ibus_input_context_focus_out(b);
|
||||||
|
}
|
||||||
|
ibus_input_context_focus_out(a);
|
||||||
|
if(log.legacy == 0 || log.modern != 0 || log.commit != 1 ||
|
||||||
|
log.invalid || !log.done || !log.atext || !log.aclear ||
|
||||||
|
log.clearctx != a)
|
||||||
|
ok = 0;
|
||||||
|
if(b != NULL)
|
||||||
|
g_object_unref(b);
|
||||||
|
g_object_unref(a);
|
||||||
g_object_unref(bus);
|
g_object_unref(bus);
|
||||||
if(!ok){
|
if(!ok){
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"ibus_client_smoke: legacy=%d modern=%d commit=%d invalid=%d preedit=%d committed=%d\n",
|
"ibus_client_smoke: legacy=%d modern=%d commit=%d invalid=%d preedit=%d committed=%d transfer-text=%d a-clear=%d\n",
|
||||||
log.legacy, log.modern, log.commit, log.invalid,
|
log.legacy, log.modern, log.commit, log.invalid,
|
||||||
log.sawpreedit, log.sawcommit);
|
log.sawpreedit, log.sawcommit, log.atext, log.aclear);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
printf("official libibus client preedit and commit: ok\n");
|
printf("official libibus client preedit, commit, and owner clear: ok\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,6 +199,7 @@ ibusbegin(struct ct *t, Ibusfix *f)
|
|||||||
memset(contexts, 0, sizeof contexts);
|
memset(contexts, 0, sizeof contexts);
|
||||||
memset(conns, 0, sizeof conns);
|
memset(conns, 0, sizeof conns);
|
||||||
nconns = 0;
|
nconns = 0;
|
||||||
|
preowner = nil;
|
||||||
while(channbrecv(drawc, &dc) > 0)
|
while(channbrecv(drawc, &dc) > 0)
|
||||||
;
|
;
|
||||||
testengineinit(LangEN);
|
testengineinit(LangEN);
|
||||||
@@ -234,6 +235,7 @@ ibusend(Ibusfix *f)
|
|||||||
memset(contexts, 0, sizeof contexts);
|
memset(contexts, 0, sizeof contexts);
|
||||||
memset(conns, 0, sizeof conns);
|
memset(conns, 0, sizeof conns);
|
||||||
nconns = 0;
|
nconns = 0;
|
||||||
|
preowner = nil;
|
||||||
testengineinit(LangEN);
|
testengineinit(LangEN);
|
||||||
while(channbrecv(drawc, &dc) > 0)
|
while(channbrecv(drawc, &dc) > 0)
|
||||||
;
|
;
|
||||||
|
|||||||
Reference in New Issue
Block a user