From 523d5121d303fb91e004ea37ce55867008cb2dd7 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 17 Feb 2021 19:59:28 -0500 Subject: imcontext: Make Compose preedit less intrusive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tweak the preedit display for Compose sequences to be not so distracting. We only show the Compose key when it occurs in the middle of the sequence or is the only key so far, and use · instead of ⎄ for it. Also, make sure to display dead keys more adequately. --- gtk/gtkimcontextsimple.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/gtk/gtkimcontextsimple.c b/gtk/gtkimcontextsimple.c index 627ed71c23..39a659edda 100644 --- a/gtk/gtkimcontextsimple.c +++ b/gtk/gtkimcontextsimple.c @@ -907,9 +907,99 @@ gtk_im_context_simple_get_preedit_string (GtkIMContext *context, for (i = 0; priv->compose_buffer[i]; i++) { if (priv->compose_buffer[i] == GDK_KEY_Multi_key) - g_string_append_unichar (s, 0x2384); /* U+2384 COMPOSITION SYMBOL */ + { + /* We only show the Compose key visibly when it is the + * only glyph in the preedit, or when it occurs in the + * middle of the sequence. Sadly, the official character, + * U+2384, COMPOSITION SYMBOL, is bit too distracting, so + * we use U+00B7, MIDDLE DOT. + */ + if (priv->compose_buffer[1] == 0 || i > 0) + g_string_append (s, "·"); + } else - g_string_append_unichar (s, gdk_keyval_to_unicode (priv->compose_buffer[i])); + { + gunichar ch; + gboolean need_space; + + if (GDK_KEY_dead_grave <= priv->compose_buffer[i] && priv->compose_buffer[i] <= GDK_KEY_dead_greek) + { + /* Sadly, not all the dead keysyms have spacing mark equivalents + * in Unicode. For those that don't, we use space + the non-spacing + * mark as an approximation + */ + switch (priv->compose_buffer[i]) + { +#define CASE(keysym, unicode, sp) \ + case GDK_KEY_dead_##keysym: ch = unicode; need_space = sp; break + + CASE (grave, 0x60, 0); + CASE (acute, 0xb4, 0); + CASE (circumflex, 0x5e, 0); + CASE (tilde, 0x7e, 0); + CASE (macron, 0xaf, 0); + CASE (breve, 0x2d8, 0); + CASE (abovedot, 0x307, 1); + CASE (diaeresis, 0xa8, 0); + CASE (abovering, 0x2da, 0); + CASE (hook, 0x2c0, 0); + CASE (doubleacute, 0x2dd, 0); + CASE (caron, 0x2c7, 0); + CASE (cedilla, 0xb8, 0); + CASE (ogonek, 0x2db, 0); + CASE (iota, 0x37a, 0); + CASE (voiced_sound, 0x3099, 1); + CASE (semivoiced_sound, 0x309a, 1); + CASE (belowdot, 0x323, 1); + CASE (horn, 0x31b, 1); + CASE (stroke, 0x335, 1); + CASE (abovecomma, 0x2bc, 0); + CASE (abovereversedcomma, 0x2bd, 1); + CASE (doublegrave, 0x30f, 1); + CASE (belowring, 0x2f3, 0); + CASE (belowmacron, 0x2cd, 0); + CASE (belowcircumflex, 0x32d, 1); + CASE (belowtilde, 0x330, 1); + CASE (belowbreve, 0x32e, 1); + CASE (belowdiaeresis, 0x324, 1); + CASE (invertedbreve, 0x32f, 1); + CASE (belowcomma, 0x326, 1); + CASE (lowline, 0x5f, 0); + CASE (aboveverticalline, 0x2c8, 0); + CASE (belowverticalline, 0x2cc, 0); + CASE (longsolidusoverlay, 0x338, 1); + CASE (a, 0x363, 1); + CASE (A, 0x363, 1); + CASE (e, 0x364, 1); + CASE (E, 0x364, 1); + CASE (i, 0x365, 1); + CASE (I, 0x365, 1); + CASE (o, 0x366, 1); + CASE (O, 0x366, 1); + CASE (u, 0x367, 1); + CASE (U, 0x367, 1); + CASE (small_schwa, 0x1dea, 1); + CASE (capital_schwa, 0x1dea, 1); +#undef CASE + default: + need_space = FALSE; + ch = gdk_keyval_to_unicode (priv->compose_buffer[i]); + break; + } + if (ch) + { + if (need_space) + g_string_append_c (s, ' '); + g_string_append_unichar (s, ch); + } + } + else + { + ch = gdk_keyval_to_unicode (priv->compose_buffer[i]); + if (ch) + g_string_append_unichar (s, ch); + } + } } } -- cgit v1.2.1 From f8206f18b1c1c311174795cea9afdc20ba76a5bb Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 18 Feb 2021 13:14:31 -0500 Subject: imwayland: Tweak preedit text Tweak the preedit text we get from IBus (via the compositor) to match what GtkIMContextSimple produces for Compose sequences now. This provides a unified experience. --- modules/input/imwayland.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/modules/input/imwayland.c b/modules/input/imwayland.c index 87c4ae806f..a9bddd29bb 100644 --- a/modules/input/imwayland.c +++ b/modules/input/imwayland.c @@ -483,6 +483,39 @@ gtk_im_context_wayland_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } +/* We want a unified experience between GtkIMContextSimple and IBus / Wayland + * when it comes to Compose sequences. IBus initial implementation of preedit + * for Compose sequences shows U+2384, which has been described as 'distracting'. + * This function tries to detect this case, and tweaks the text to match what + * GtkIMContextSimple produces. + */ +static char * +tweak_preedit (const char *text) +{ + GString *s; + guint len; + + s = g_string_new (""); + + len = g_utf8_strlen (text, -1); + + for (const char *p = text; *p; p = g_utf8_next_char (p)) + { + gunichar ch = g_utf8_get_char (p); + + if (ch == 0x2384) + { + if (len == 1 || p > text) + g_string_append (s, "·"); + } + else + g_string_append_unichar (s, ch); + } + + return g_string_free (s, FALSE); +} + + static void gtk_im_context_wayland_get_preedit_string (GtkIMContext *context, gchar **str, @@ -512,7 +545,7 @@ gtk_im_context_wayland_get_preedit_string (GtkIMContext *context, context_wayland->current_preedit.text ? context_wayland->current_preedit.text : ""; if (str) - *str = g_strdup (preedit_str); + *str = tweak_preedit (preedit_str); if (cursor_pos) *cursor_pos = g_utf8_strlen (preedit_str, context_wayland->current_preedit.cursor_begin); -- cgit v1.2.1