ibus: the text before the cursor, and the runes to take back
RequireSurroundingText asks the client to send its text; it arrives through SetSurroundingText as an IBusText and a cursor counted in runes, and DeleteSurroundingText asks for runes back before the commit that replaces them. The official libibus client now proves the whole turn: 한자 typed, the Hanja key, Enter, and 漢字 arrives with the 한 taken away. A client that has set EffectivePostProcessKeyEvent is never asked for its text. It reads the key's commits back after ProcessKeyEvent returns, and a DeleteSurroundingText signal is not one of the things that reply can carry, so the deletion would land after the text it was meant to make room for and eat the wrong runes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,12 @@ struct Log
|
||||
int rcommit;
|
||||
int rdone;
|
||||
int flushed;
|
||||
int hanja;
|
||||
int required;
|
||||
int deleted;
|
||||
int delbefore;
|
||||
int delcount;
|
||||
int converted;
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -142,6 +148,17 @@ commit(IBusInputContext *ctx, IBusText *text, void *arg)
|
||||
log->commit++;
|
||||
s = ibus_text_get_text(text);
|
||||
attrs = ibus_text_get_attributes(text);
|
||||
if(log->hanja){
|
||||
/* The word converted, with the client\'s own syllable taken back. */
|
||||
if(strcmp(s, "漢字") == 0 && log->deleted && log->delbefore == -1 &&
|
||||
log->delcount == 1)
|
||||
log->converted = 1;
|
||||
else
|
||||
log->invalid = 1;
|
||||
if(log->loop != NULL && log->waiting != NULL && *log->waiting)
|
||||
g_main_loop_quit(log->loop);
|
||||
return;
|
||||
}
|
||||
if(log->repeat == 3){
|
||||
/* Focus loss hands the pending syllable back as a commit. */
|
||||
if(strcmp(s, "ㅋ") == 0)
|
||||
@@ -184,6 +201,32 @@ commit(IBusInputContext *ctx, IBusText *text, void *arg)
|
||||
g_main_loop_quit(log->loop);
|
||||
}
|
||||
|
||||
static void
|
||||
required(IBusInputContext *ctx, void *arg)
|
||||
{
|
||||
Log *log;
|
||||
|
||||
(void)ctx;
|
||||
log = arg;
|
||||
log->required = 1;
|
||||
if(log->loop != NULL && log->waiting != NULL && *log->waiting)
|
||||
g_main_loop_quit(log->loop);
|
||||
}
|
||||
|
||||
static void
|
||||
deleted(IBusInputContext *ctx, gint offset, guint n, void *arg)
|
||||
{
|
||||
Log *log;
|
||||
|
||||
(void)ctx;
|
||||
log = arg;
|
||||
log->deleted = 1;
|
||||
log->delbefore = offset;
|
||||
log->delcount = n;
|
||||
if(log->loop != NULL && log->waiting != NULL && *log->waiting)
|
||||
g_main_loop_quit(log->loop);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
timeout(void *arg)
|
||||
{
|
||||
@@ -214,7 +257,8 @@ int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
IBusBus *bus;
|
||||
IBusInputContext *a, *b;
|
||||
IBusInputContext *a, *b, *c;
|
||||
IBusText *around;
|
||||
Log log;
|
||||
int ok;
|
||||
|
||||
@@ -229,7 +273,7 @@ main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
memset(&log, 0, sizeof log);
|
||||
b = NULL;
|
||||
b = c = NULL;
|
||||
ibus_init();
|
||||
bus = ibus_bus_new();
|
||||
if(bus == NULL || !ibus_bus_is_connected(bus)){
|
||||
@@ -286,20 +330,55 @@ main(int argc, char **argv)
|
||||
log.repeat = 3;
|
||||
ibus_input_context_focus_out(a);
|
||||
ok = ok && waitflag(&log, &log.flushed);
|
||||
if(log.legacy == 0 || log.modern != 0 || log.commit != 4 ||
|
||||
log.invalid || !log.done || !log.atext || !log.aclear ||
|
||||
!log.retook || log.clearctx != a || !log.rdone)
|
||||
/*
|
||||
* A word is committed a syllable at a time, so the Hanja key must
|
||||
* reach into what the client already holds and ask for it back.
|
||||
*/
|
||||
c = ibus_bus_create_input_context(bus, "strans-libibus-smoke-c");
|
||||
if(c == NULL)
|
||||
ok = 0;
|
||||
else{
|
||||
g_signal_connect(c, "commit-text", G_CALLBACK(commit), &log);
|
||||
g_signal_connect(c, "require-surrounding-text",
|
||||
G_CALLBACK(required), &log);
|
||||
g_signal_connect(c, "delete-surrounding-text",
|
||||
G_CALLBACK(deleted), &log);
|
||||
log.repeat = 0;
|
||||
ibus_input_context_set_capabilities(c,
|
||||
IBUS_CAP_PREEDIT_TEXT|IBUS_CAP_SURROUNDING_TEXT);
|
||||
ibus_input_context_focus_in(c);
|
||||
ok = ok && waitflag(&log, &log.required);
|
||||
around = ibus_text_new_from_string("저는 한");
|
||||
ibus_input_context_set_surrounding_text(c, around, 4, 4);
|
||||
log.hanja = 1;
|
||||
ok = ok && ibus_input_context_process_key_event(c, 's', 0,
|
||||
IBUS_CONTROL_MASK) &&
|
||||
ibus_input_context_process_key_event(c, 'w', 0, 0) &&
|
||||
ibus_input_context_process_key_event(c, 'k', 0, 0) &&
|
||||
ibus_input_context_process_key_event(c, 'h', 0,
|
||||
IBUS_CONTROL_MASK) &&
|
||||
ibus_input_context_process_key_event(c, IBUS_KEY_Return,
|
||||
0, 0) && waitflag(&log, &log.converted);
|
||||
log.hanja = 0;
|
||||
}
|
||||
|
||||
if(log.legacy == 0 || log.modern != 0 || log.commit != 5 ||
|
||||
log.invalid || !log.done || !log.atext || !log.aclear ||
|
||||
!log.retook || log.clearctx != a || !log.rdone || !log.converted)
|
||||
ok = 0;
|
||||
if(c != NULL)
|
||||
g_object_unref(c);
|
||||
if(b != NULL)
|
||||
g_object_unref(b);
|
||||
g_object_unref(a);
|
||||
g_object_unref(bus);
|
||||
if(!ok){
|
||||
fprintf(stderr,
|
||||
"ibus_client_smoke: legacy=%d modern=%d commit=%d invalid=%d preedit=%d committed=%d transfer-text=%d a-clear=%d retook=%d repeat=%s flushed=%d\n",
|
||||
"ibus_client_smoke: legacy=%d modern=%d commit=%d invalid=%d preedit=%d committed=%d transfer-text=%d a-clear=%d retook=%d repeat=%s flushed=%d required=%d deleted=%d,%d converted=%d\n",
|
||||
log.legacy, log.modern, log.commit, log.invalid,
|
||||
log.sawpreedit, log.sawcommit, log.atext, log.aclear,
|
||||
log.retook, log.revent, log.flushed);
|
||||
log.retook, log.revent, log.flushed, log.required,
|
||||
log.delbefore, log.delcount, log.converted);
|
||||
return 1;
|
||||
}
|
||||
printf("official libibus client preedit, commit, owner clear, take-back and focus-out hand-back: ok\n");
|
||||
|
||||
@@ -129,6 +129,7 @@ runcontract(char *address)
|
||||
"SetCapabilities",
|
||||
"SetCursorLocation",
|
||||
"SetCursorLocationRelative",
|
||||
"SetSurroundingText",
|
||||
};
|
||||
DBusConnection *conn;
|
||||
char path[96];
|
||||
|
||||
Reference in New Issue
Block a user