summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-02-18 17:36:08 +0000
committerMatthias Clasen <mclasen@redhat.com>2021-02-18 17:36:08 +0000
commit07295ac169f39ffd1caf55e1d381e0f52a852210 (patch)
treef2257285ea77bfb6db3a86c568439b6fd81a34b7
parent447e6db847b970902561bb7f47366072c0f25be3 (diff)
parentd84a028455cadbf146e4cd234f57dc1df2e69cd6 (diff)
downloadgtk+-07295ac169f39ffd1caf55e1d381e0f52a852210.tar.gz
Merge branch 'unintrusive-compose-preedit' into 'master'
Unintrusive compose preedit See merge request GNOME/gtk!3220
-rw-r--r--gtk/gtkimcontextsimple.c94
-rw-r--r--gtk/gtkimcontextwayland.c34
2 files changed, 125 insertions, 3 deletions
diff --git a/gtk/gtkimcontextsimple.c b/gtk/gtkimcontextsimple.c
index b8fec2f384..86e133fc86 100644
--- a/gtk/gtkimcontextsimple.c
+++ b/gtk/gtkimcontextsimple.c
@@ -930,9 +930,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);
+ }
+ }
}
}
diff --git a/gtk/gtkimcontextwayland.c b/gtk/gtkimcontextwayland.c
index 915ad9e854..397909064d 100644
--- a/gtk/gtkimcontextwayland.c
+++ b/gtk/gtkimcontextwayland.c
@@ -570,6 +570,38 @@ gtk_im_context_wayland_set_client_widget (GtkIMContext *context,
}
}
+/* 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,
char **str,
@@ -599,7 +631,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);