fix(frontends): restart preedit around commits
This commit is contained in:
@@ -345,6 +345,8 @@ kpress(GtkIMContext *ctx, GdkEventKey *ev)
|
|||||||
srvclose(im);
|
srvclose(im);
|
||||||
return simplefilter(ctx, ev, 0);
|
return simplefilter(ctx, ev, 0);
|
||||||
}
|
}
|
||||||
|
if(im->usepreedit && commit[0] != '\0' && im->prelen > 0)
|
||||||
|
setpreedit(im, "", 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)
|
if(im->usepreedit)
|
||||||
|
|||||||
6
ibus.c
6
ibus.c
@@ -629,6 +629,7 @@ handlekey(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
|||||||
dbus_uint32_t sym, code, state;
|
dbus_uint32_t sym, code, state;
|
||||||
Keyres res;
|
Keyres res;
|
||||||
char commit[Maxutf], preedit[Maxutf];
|
char commit[Maxutf], preedit[Maxutf];
|
||||||
|
int restart;
|
||||||
|
|
||||||
dbus_error_init(&err);
|
dbus_error_init(&err);
|
||||||
if(!dbus_message_get_args(m, &err,
|
if(!dbus_message_get_args(m, &err,
|
||||||
@@ -645,9 +646,12 @@ handlekey(DBusConnection *c, DBusMessage *m, Ictx *ctx)
|
|||||||
return handlebool(c, m, 0);
|
return handlebool(c, m, 0);
|
||||||
stoutf(&res.commit, commit, sizeof commit);
|
stoutf(&res.commit, commit, sizeof commit);
|
||||||
stoutf(&res.preedit, preedit, sizeof preedit);
|
stoutf(&res.preedit, preedit, sizeof preedit);
|
||||||
|
restart = clientpreedit(ctx) && commit[0] != '\0' && preowner == ctx;
|
||||||
|
if(restart)
|
||||||
|
emitpreedit(ctx, "");
|
||||||
if(commit[0] != '\0')
|
if(commit[0] != '\0')
|
||||||
emitcommit(c, dbus_message_get_path(m), commit);
|
emitcommit(c, dbus_message_get_path(m), commit);
|
||||||
if(clientpreedit(ctx))
|
if(clientpreedit(ctx) && (!restart || preedit[0] != '\0'))
|
||||||
emitpreedit(ctx, preedit);
|
emitpreedit(ctx, preedit);
|
||||||
return handlebool(c, m, res.eaten);
|
return handlebool(c, m, res.eaten);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -420,25 +420,38 @@ engine_active_owner_caret(struct ct *t)
|
|||||||
void
|
void
|
||||||
engine_commit_contract(struct ct *t)
|
engine_commit_contract(struct ct *t)
|
||||||
{
|
{
|
||||||
|
static const struct {
|
||||||
|
Rune key;
|
||||||
|
char *one;
|
||||||
|
char *all;
|
||||||
|
} cases[] = {
|
||||||
|
{ 'z', "ㅋ", "ㅋㅋㅋ" },
|
||||||
|
{ 'r', "ㄱ", "ㄱㄱㄱ" },
|
||||||
|
{ 'd', "ㅇ", "ㅇㅇㅇ" },
|
||||||
|
{ 'k', "ㅏ", "ㅏㅏㅏ" },
|
||||||
|
};
|
||||||
Keyres res;
|
Keyres res;
|
||||||
Str all, com;
|
Str all, com;
|
||||||
char owner;
|
char owner;
|
||||||
int i;
|
int i, j;
|
||||||
|
|
||||||
init();
|
for(j = 0; j < nelem(cases); j++){
|
||||||
im.l = getlang(LangKO);
|
init();
|
||||||
sclear(&all);
|
im.l = getlang(LangKO);
|
||||||
for(i = 0; i < 3; i++){
|
sclear(&all);
|
||||||
res = ownerrequestcap(&owner, Cclientpreedit,
|
for(i = 0; i < 3; i++){
|
||||||
Keypress, 'z', 0);
|
res = ownerrequestcap(&owner, Cclientpreedit,
|
||||||
CT_CHECK(t, res.eaten);
|
Keypress, cases[j].key, 0);
|
||||||
checkstr(t, "repeated consonant commit",
|
CT_CHECK(t, res.eaten);
|
||||||
i == 0 ? "" : "ㅋ", &res.commit);
|
checkstr(t, "repeated jamo commit",
|
||||||
checkstr(t, "repeated consonant preedit", "ㅋ", &res.preedit);
|
i == 0 ? "" : cases[j].one, &res.commit);
|
||||||
sappend(&all, &res.commit);
|
checkstr(t, "repeated jamo preedit", cases[j].one,
|
||||||
|
&res.preedit);
|
||||||
|
sappend(&all, &res.commit);
|
||||||
|
}
|
||||||
|
sappend(&all, &res.preedit);
|
||||||
|
checkstr(t, "repeated jamo total", cases[j].all, &all);
|
||||||
}
|
}
|
||||||
sappend(&all, &res.preedit);
|
|
||||||
checkstr(t, "repeated consonant total", "ㅋㅋㅋ", &all);
|
|
||||||
|
|
||||||
init();
|
init();
|
||||||
im.l = getlang(LangJP);
|
im.l = getlang(LangJP);
|
||||||
|
|||||||
@@ -80,7 +80,9 @@ struct Siglog
|
|||||||
char event[128];
|
char event[128];
|
||||||
int n;
|
int n;
|
||||||
char pre[Ipcfieldmax+1];
|
char pre[Ipcfieldmax+1];
|
||||||
|
char shown[Ipcfieldmax+1];
|
||||||
char commit[Ipcfieldmax+1];
|
char commit[Ipcfieldmax+1];
|
||||||
|
int prechanged;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -568,6 +570,8 @@ prechange(GtkIMContext *ctx, Siglog *l)
|
|||||||
gchar *s;
|
gchar *s;
|
||||||
|
|
||||||
gtk_im_context_get_preedit_string(ctx, &s, NULL, NULL);
|
gtk_im_context_get_preedit_string(ctx, &s, NULL, NULL);
|
||||||
|
if(strcmp(l->pre, s) != 0)
|
||||||
|
l->prechanged = 1;
|
||||||
snprintf(l->pre, sizeof l->pre, "%s", s);
|
snprintf(l->pre, sizeof l->pre, "%s", s);
|
||||||
g_free(s);
|
g_free(s);
|
||||||
logsig(l, 'C');
|
logsig(l, 'C');
|
||||||
@@ -585,10 +589,27 @@ 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');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clearevent(Siglog *l)
|
||||||
|
{
|
||||||
|
l->event[0] = '\0';
|
||||||
|
l->n = 0;
|
||||||
|
l->commit[0] = '\0';
|
||||||
|
l->prechanged = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
applyclient(Siglog *l)
|
||||||
|
{
|
||||||
|
if(l->commit[0] != '\0')
|
||||||
|
l->shown[0] = '\0';
|
||||||
|
if(l->prechanged)
|
||||||
|
snprintf(l->shown, sizeof l->shown, "%s", l->pre);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clearlog(Siglog *l)
|
clearlog(Siglog *l)
|
||||||
{
|
{
|
||||||
@@ -748,18 +769,23 @@ main(int argc, char **argv)
|
|||||||
setpre(&srv, "ㅋ");
|
setpre(&srv, "ㅋ");
|
||||||
clearlog(&log);
|
clearlog(&log);
|
||||||
Check(key(ctx, win, GDK_KEY_z), "first preedit key was not eaten");
|
Check(key(ctx, win, GDK_KEY_z), "first preedit key was not eaten");
|
||||||
Check(strcmp(log.event, "SC") == 0 && strcmp(log.pre, "ㅋ") == 0,
|
applyclient(&log);
|
||||||
"first preedit signals were %s (%s)", log.event, log.pre);
|
Check(strcmp(log.event, "SC") == 0 && strcmp(log.pre, "ㅋ") == 0 &&
|
||||||
clearlog(&log);
|
strcmp(log.shown, "ㅋ") == 0,
|
||||||
|
"first preedit signals were %s (preedit %s, shown %s)",
|
||||||
|
log.event, log.pre, log.shown);
|
||||||
|
clearevent(&log);
|
||||||
setreply(&srv, 1, Rcommitpre, 0);
|
setreply(&srv, 1, Rcommitpre, 0);
|
||||||
Check(key(ctx, win, GDK_KEY_z), "repeated preedit key was not eaten");
|
Check(key(ctx, win, GDK_KEY_z), "repeated preedit key was not eaten");
|
||||||
Check(strcmp(log.event, "KC") == 0 &&
|
applyclient(&log);
|
||||||
strcmp(log.commit, "ㅋ") == 0 && strcmp(log.pre, "ㅋ") == 0,
|
Check(strcmp(log.event, "CEKSC") == 0 &&
|
||||||
"repeated preedit signals were %s (commit %s, preedit %s)",
|
strcmp(log.commit, "ㅋ") == 0 && strcmp(log.pre, "ㅋ") == 0 &&
|
||||||
log.event, log.commit, log.pre);
|
strcmp(log.shown, "ㅋ") == 0,
|
||||||
Check(g_utf8_strlen(log.commit, -1) + g_utf8_strlen(log.pre, -1) == 2,
|
"repeated preedit signals were %s (commit %s, preedit %s, shown %s)",
|
||||||
"two physical keys produced commit %s and preedit %s",
|
log.event, log.commit, log.pre, log.shown);
|
||||||
log.commit, log.pre);
|
Check(g_utf8_strlen(log.commit, -1) + g_utf8_strlen(log.shown, -1) == 2,
|
||||||
|
"two physical keys produced commit %s and shown preedit %s",
|
||||||
|
log.commit, log.shown);
|
||||||
|
|
||||||
/* Unconsumed input uses GtkIMContextSimple, including its stateful forms. */
|
/* Unconsumed input uses GtkIMContextSimple, including its stateful forms. */
|
||||||
setpre(&srv, "");
|
setpre(&srv, "");
|
||||||
|
|||||||
@@ -21,8 +21,23 @@ struct Log
|
|||||||
int transfer;
|
int transfer;
|
||||||
int atext;
|
int atext;
|
||||||
int aclear;
|
int aclear;
|
||||||
|
char revent[16];
|
||||||
|
int rn;
|
||||||
|
int repeat;
|
||||||
|
int rfirst;
|
||||||
|
int rcommit;
|
||||||
|
int rdone;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
revent(Log *log, char c)
|
||||||
|
{
|
||||||
|
if(log->rn + 1 < (int)sizeof log->revent){
|
||||||
|
log->revent[log->rn++] = c;
|
||||||
|
log->revent[log->rn] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
legacy(IBusInputContext *ctx, IBusText *text, guint cursor,
|
legacy(IBusInputContext *ctx, IBusText *text, guint cursor,
|
||||||
gboolean visible, void *arg)
|
gboolean visible, void *arg)
|
||||||
@@ -36,6 +51,28 @@ legacy(IBusInputContext *ctx, IBusText *text, guint cursor,
|
|||||||
log = arg;
|
log = arg;
|
||||||
log->legacy++;
|
log->legacy++;
|
||||||
s = ibus_text_get_text(text);
|
s = ibus_text_get_text(text);
|
||||||
|
if(log->repeat != 0){
|
||||||
|
revent(log, 'P');
|
||||||
|
if(log->repeat == 1){
|
||||||
|
if(s[0] == '\0'){
|
||||||
|
if(cursor != 0 || visible)
|
||||||
|
log->invalid = 1;
|
||||||
|
}else if(strcmp(s, "ㅋ") != 0 || cursor != 1 || !visible)
|
||||||
|
log->invalid = 1;
|
||||||
|
else
|
||||||
|
log->rfirst = 1;
|
||||||
|
}else if(s[0] == '\0'){
|
||||||
|
if(cursor != 0 || visible || log->rcommit)
|
||||||
|
log->invalid = 1;
|
||||||
|
}else if(strcmp(s, "ㅋ") != 0 || cursor != 1 || !visible ||
|
||||||
|
!log->rcommit)
|
||||||
|
log->invalid = 1;
|
||||||
|
else
|
||||||
|
log->rdone = 1;
|
||||||
|
if(log->loop != NULL && log->waiting != NULL && *log->waiting)
|
||||||
|
g_main_loop_quit(log->loop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(strcmp(s, "k") == 0){
|
if(strcmp(s, "k") == 0){
|
||||||
attrs = ibus_text_get_attributes(text);
|
attrs = ibus_text_get_attributes(text);
|
||||||
a = attrs == NULL ? NULL : ibus_attr_list_get(attrs, 0);
|
a = attrs == NULL ? NULL : ibus_attr_list_get(attrs, 0);
|
||||||
@@ -97,6 +134,17 @@ commit(IBusInputContext *ctx, IBusText *text, void *arg)
|
|||||||
log->commit++;
|
log->commit++;
|
||||||
s = ibus_text_get_text(text);
|
s = ibus_text_get_text(text);
|
||||||
attrs = ibus_text_get_attributes(text);
|
attrs = ibus_text_get_attributes(text);
|
||||||
|
if(log->repeat != 0){
|
||||||
|
revent(log, 'K');
|
||||||
|
if(log->repeat != 2 || strcmp(s, "ㅋ") != 0 || attrs == NULL ||
|
||||||
|
ibus_attr_list_get(attrs, 0) != NULL)
|
||||||
|
log->invalid = 1;
|
||||||
|
else
|
||||||
|
log->rcommit = 1;
|
||||||
|
if(log->loop != NULL && log->waiting != NULL && *log->waiting)
|
||||||
|
g_main_loop_quit(log->loop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(strcmp(s, "か") != 0 || attrs == NULL ||
|
if(strcmp(s, "か") != 0 || attrs == NULL ||
|
||||||
ibus_attr_list_get(attrs, 0) != NULL)
|
ibus_attr_list_get(attrs, 0) != NULL)
|
||||||
log->invalid = 1;
|
log->invalid = 1;
|
||||||
@@ -194,10 +242,22 @@ main(int argc, char **argv)
|
|||||||
waitflag(&log, &log.aclear);
|
waitflag(&log, &log.aclear);
|
||||||
ibus_input_context_focus_out(b);
|
ibus_input_context_focus_out(b);
|
||||||
}
|
}
|
||||||
|
ibus_input_context_focus_in(a);
|
||||||
|
ok = ok && ibus_input_context_process_key_event(a, 's', 0,
|
||||||
|
IBUS_CONTROL_MASK);
|
||||||
|
log.repeat = 1;
|
||||||
|
ok = ok && ibus_input_context_process_key_event(a, 'z', 0, 0) &&
|
||||||
|
waitflag(&log, &log.rfirst);
|
||||||
|
log.repeat = 2;
|
||||||
|
log.revent[0] = '\0';
|
||||||
|
log.rn = 0;
|
||||||
|
ok = ok && ibus_input_context_process_key_event(a, 'z', 0, 0) &&
|
||||||
|
waitflag(&log, &log.rdone) && strcmp(log.revent, "PKP") == 0;
|
||||||
|
log.repeat = 0;
|
||||||
ibus_input_context_focus_out(a);
|
ibus_input_context_focus_out(a);
|
||||||
if(log.legacy == 0 || log.modern != 0 || log.commit != 1 ||
|
if(log.legacy == 0 || log.modern != 0 || log.commit != 2 ||
|
||||||
log.invalid || !log.done || !log.atext || !log.aclear ||
|
log.invalid || !log.done || !log.atext || !log.aclear ||
|
||||||
log.clearctx != a)
|
log.clearctx != a || !log.rdone)
|
||||||
ok = 0;
|
ok = 0;
|
||||||
if(b != NULL)
|
if(b != NULL)
|
||||||
g_object_unref(b);
|
g_object_unref(b);
|
||||||
@@ -205,9 +265,10 @@ main(int argc, char **argv)
|
|||||||
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 transfer-text=%d a-clear=%d\n",
|
"ibus_client_smoke: legacy=%d modern=%d commit=%d invalid=%d preedit=%d committed=%d transfer-text=%d a-clear=%d repeat=%s\n",
|
||||||
log.legacy, log.modern, log.commit, log.invalid,
|
log.legacy, log.modern, log.commit, log.invalid,
|
||||||
log.sawpreedit, log.sawcommit, log.atext, log.aclear);
|
log.sawpreedit, log.sawcommit, log.atext, log.aclear,
|
||||||
|
log.revent);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
printf("official libibus client preedit, commit, and owner clear: ok\n");
|
printf("official libibus client preedit, commit, and owner clear: ok\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user