From 4d3755770c8dad4b6cb7c9df441504aaadd18556 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Mon, 20 Feb 2023 17:14:30 +0100 Subject: [PATCH] fix(linux): Collect consecutive backspaces When using Wayland `im-wayland.so` (which is part of libgtk) gets loaded into the client app instead of `im-ibus.so`. This means that our ordered output doesn't work with Wayland. This change works around a problem with keyboards that use multiple consecutive backspace actions. Because method calls get processed asynchronously some backspaces get lost. In clients that support surrounding text we can count the consecutive backspaces and then do one call to delete surrounding text with the appropriate number of characters. This can be tested with "Khmer Angkor" keyboard by typing `xEjmr`, or with "Vedic Sanskrit Devanagari Phonetic (ITRANS)" keyboard by typing `shrI`. Part of #4273. --- linux/ibus-keyman/src/engine.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/linux/ibus-keyman/src/engine.c b/linux/ibus-keyman/src/engine.c index 368fe94182..6273d3ecd9 100644 --- a/linux/ibus-keyman/src/engine.c +++ b/linux/ibus-keyman/src/engine.c @@ -99,6 +99,7 @@ struct _IBusKeymanEngine { commit_queue_item commit_queue[MAX_QUEUE_SIZE]; commit_queue_item *commit_item; + guint consecutive_backspaces; }; struct _IBusKeymanEngineClass { @@ -467,6 +468,7 @@ ibus_keyman_engine_constructor( keyman->lctrl_pressed = FALSE; keyman->ralt_pressed = FALSE; keyman->rctrl_pressed = FALSE; + keyman->consecutive_backspaces = 0; initialize_queue(keyman, 0, MAX_QUEUE_SIZE); keyman->commit_item = &keyman->commit_queue[0]; gchar **split_name = g_strsplit(engine_name, ":", 2); @@ -656,8 +658,8 @@ process_backspace_action( "DAR: %s - client_capabilities=%x, %x", __FUNCTION__, engine->client_capabilities, IBUS_CAP_SURROUNDING_TEXT); if (client_supports_surrounding_text(engine)) { - g_message("%s: deleting surrounding text 1 char", __FUNCTION__); - ibus_engine_delete_surrounding_text(engine, -1, 1); + keyman->consecutive_backspaces++; + g_message("%s: increment consecutive backspaces to %d", __FUNCTION__, keyman->consecutive_backspaces); } else { g_message("%s: forwarding backspace with reset context", __FUNCTION__); km_kbp_context_item *context_items; @@ -671,6 +673,21 @@ process_backspace_action( return TRUE; } +static gboolean +finish_backspace_action( + IBusEngine *engine +) { + IBusKeymanEngine *keyman = (IBusKeymanEngine *)engine; + if (keyman->consecutive_backspaces <= 0) + return TRUE; + + g_assert(client_supports_surrounding_text(engine)); + g_message("%s: deleting surrounding text %d char", __FUNCTION__, keyman->consecutive_backspaces); + ibus_engine_delete_surrounding_text(engine, -keyman->consecutive_backspaces, keyman->consecutive_backspaces); + keyman->consecutive_backspaces = 0; + return TRUE; +} + static gboolean process_persist_action( IBusKeymanEngine *keyman, @@ -816,6 +833,9 @@ process_actions( IBusKeymanEngine *keyman = (IBusKeymanEngine *)engine; for (int i = 0; i < num_action_items; i++) { gboolean continue_with_next_action = TRUE; + if (action_items[i].type != KM_KBP_IT_BACK && keyman->consecutive_backspaces > 0) { + finish_backspace_action(engine); + } switch (action_items[i].type) { case KM_KBP_IT_CHAR: g_message("CHAR action %d/%d", i + 1, (int)num_action_items);