Skip to content

Commit

Permalink
Rework gtk event (#570)
Browse files Browse the repository at this point in the history
* Remove workaround patch from #536 #565
* Let handle preedit change in delayed event
  • Loading branch information
Riey authored Apr 23, 2022
1 parent 655f3f4 commit 753b106
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 47 deletions.
5 changes: 3 additions & 2 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
* Added Qt 5.12.9 library build
* Fix sebeolsik-391 "S-Equal" key
* Let indicator shown on Gnome tray (requires Gnome shell extension, https://extensions.gnome.org/extension/615/appindicator-support/)
* Fix space error in some firefox sites[#561](https://github.com/Riey/kime/issues/561).
* Fix duplicated commit string in some firefox sites[#562](https://github.com/Riey/kime/issues/562).
* Fix space error in some firefox sites [#561](https://github.com/Riey/kime/issues/561).
* Fix duplicated commit string in some firefox sites [#562](https://github.com/Riey/kime/issues/562).
* Delaying preedit, bypass processes in gtk module [#570](https://github.com/Riey/kime/issues/570)

## 2.5.6

Expand Down
93 changes: 48 additions & 45 deletions src/frontends/gtk2/src/immodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
static GType KIME_TYPE_IM_CONTEXT = 0;
// for many buggy gtk apps
static const guint HANDLED_MASK = 1 << 25;
static const guint BYPASS_MASK = 1 << 24;

#if GTK_CHECK_VERSION(3, 98, 4)
typedef GtkWidget ClientType;
Expand All @@ -19,6 +20,11 @@ typedef GdkEventKey EventType;
static const guint NOT_ENGLISH_MASK =
GDK_ALT_MASK | GDK_CONTROL_MASK | GDK_SUPER_MASK;

typedef struct _KeyRet {
gboolean bypassed;
gboolean has_preedit;
} KeyRet;

typedef struct KimeSignals {
guint commit;
guint preedit_start;
Expand All @@ -40,11 +46,6 @@ typedef struct KimeImContext {
KimeInputEngine *engine;
gboolean preedit_visible;

// for firefox edge case
gboolean preedit_has_ended;
// prevent commit triggering reset event
gboolean is_committing;

gboolean engine_ready;
KimeConfig *config;
} KimeImContext;
Expand All @@ -55,7 +56,10 @@ typedef struct KimeImContext {

#define debug(...) g_log("kime", G_LOG_LEVEL_DEBUG, __VA_ARGS__)

void update_preedit(KimeImContext *ctx, gboolean visible) {
void update_preedit(KimeImContext *ctx) {
KimeRustStr str = kime_engine_preedit_str(ctx->engine);

gboolean visible = str.len != 0;
debug("preedit(%d)", visible);

if (ctx->preedit_visible != visible) {
Expand All @@ -74,11 +78,6 @@ void update_preedit(KimeImContext *ctx, gboolean visible) {
}

void commit(KimeImContext *ctx) {
// https://github.com/Riey/kime/issues/535
ctx->is_committing = TRUE;
update_preedit(ctx, FALSE);
ctx->is_committing = FALSE;

// Don't commit zero size string
if (ctx->buf.len == 0) {
return;
Expand All @@ -97,8 +96,10 @@ void commit(KimeImContext *ctx) {
ctx->buf.len = 0;
}

gboolean process_input_result(KimeImContext *ctx, KimeInputResult ret) {
gboolean bypassed = (ret & KimeInputResult_CONSUMED) != 0;
KeyRet process_input_result(KimeImContext *ctx, KimeInputResult ret) {
KeyRet key_ret;
key_ret.bypassed = (ret & KimeInputResult_CONSUMED) == 0;
key_ret.has_preedit = (ret & KimeInputResult_HAS_PREEDIT) != 0;

if (ret & KimeInputResult_NOT_READY) {
ctx->engine_ready = FALSE;
Expand All @@ -115,22 +116,13 @@ gboolean process_input_result(KimeImContext *ctx, KimeInputResult ret) {
kime_engine_update_layout_state(ctx->engine);
}

if (!(ret & KimeInputResult_HAS_PREEDIT)) {
ctx->preedit_has_ended = ctx->preedit_visible;
update_preedit(ctx, FALSE);
}

if (ret & KimeInputResult_HAS_COMMIT) {
str_buf_set_str(&ctx->buf, kime_engine_commit_str(ctx->engine));
commit(ctx);
kime_engine_clear_commit(ctx->engine);
}

if (ret & KimeInputResult_HAS_PREEDIT) {
update_preedit(ctx, TRUE);
}

return bypassed;
return key_ret;
}

void focus_in(GtkIMContext *im) {
Expand Down Expand Up @@ -158,11 +150,6 @@ void kime_reset(KimeImContext *ctx) {
void reset(GtkIMContext *im) {
KIME_IM_CONTEXT(im);

if (ctx->is_committing) {
// dummy
return;
}

debug("reset");

kime_reset(ctx);
Expand All @@ -179,15 +166,15 @@ void focus_out(GtkIMContext *im) {
}
}

void put_event(KimeImContext *ctx, EventType *key) {
void put_event(KimeImContext *ctx, EventType *key, guint mask) {
#if GTK_CHECK_VERSION(3, 98, 4)
gtk_im_context_filter_key(
GTK_IM_CONTEXT(ctx), gdk_event_get_event_type(key) == GDK_KEY_PRESS,
gdk_event_get_surface(key), gdk_event_get_device(key),
gdk_event_get_time(key), gdk_key_event_get_keycode(key),
gdk_event_get_modifier_state(key) | HANDLED_MASK, 0);
gdk_event_get_modifier_state(key) | mask, 0);
#else
key->state |= HANDLED_MASK;
key->state |= mask;
gdk_event_put((GdkEvent *)key);
#endif
}
Expand All @@ -207,10 +194,7 @@ gboolean commit_event(KimeImContext *ctx, GdkModifierType state, guint keyval) {
return FALSE;
}

gboolean on_key_input(KimeImContext *ctx, guint16 code,
KimeModifierState state) {
ctx->preedit_has_ended = FALSE;

KeyRet on_key_input(KimeImContext *ctx, guint16 code, KimeModifierState state) {
KimeInputResult ret =
kime_engine_press_key(ctx->engine, ctx->config, code, state);

Expand Down Expand Up @@ -239,8 +223,16 @@ gboolean filter_keypress(GtkIMContext *im, EventType *key) {
GdkModifierType state = key->state;
#endif

// delayed event
if (state & HANDLED_MASK) {
return commit_event(ctx, state, keyval);
// preedit change can't mixed with commit
update_preedit(ctx);

if (state & BYPASS_MASK) {
return commit_event(ctx, state, keyval);
} else {
return TRUE;
}
}

KimeModifierState kime_state = 0;
Expand All @@ -261,15 +253,28 @@ gboolean filter_keypress(GtkIMContext *im, EventType *key) {
kime_state |= KimeModifierState_SUPER;
}

if (on_key_input(ctx, code, kime_state)) {
return TRUE;
} else if (ctx->preedit_has_ended) {
// Can't just return FALSE because firefox can't accept FALSE when
// preedit-end is called
put_event(ctx, key);
KeyRet key_ret = on_key_input(ctx, code, kime_state);

if (ctx->preedit_visible || key_ret.has_preedit) {
guint mask = HANDLED_MASK;

if (key_ret.bypassed) {
mask |= BYPASS_MASK;
}

// need change on next event
put_event(ctx, key, mask);

// debug("trip: preedit cur(%d) will(%d))", ctx->preedit_visible, key_ret.has_preedit);

// never return `FALSE` here
return TRUE;
} else {
} else if (key_ret.bypassed) {
// debug("commit_event");
return commit_event(ctx, state, keyval);
} else {
// debug("consume");
return TRUE;
}
}

Expand Down Expand Up @@ -358,8 +363,6 @@ void im_context_init(KimeImContext *ctx, KimeImContextClass *klass) {
ctx->buf = str_buf_new();
ctx->widget = NULL;
ctx->preedit_visible = FALSE;
ctx->is_committing = FALSE;
ctx->preedit_has_ended = FALSE;
ctx->engine_ready = TRUE;
ctx->signals = klass->signals;
ctx->engine = kime_engine_new(klass->config);
Expand Down

0 comments on commit 753b106

Please sign in to comment.