Commit 1f37cbfb authored by Matthias Clasen's avatar Matthias Clasen

Drop Ctrl-Shift-e support

Now that we have Emoji completion, drop the rather limited
Ctrl-Shift-e support in GtkIMContextSimple, and leave this
sequence to input methods.
parent f5957914
Pipeline #14126 passed with stage
in 8 minutes
......@@ -59,63 +59,19 @@
* Compose file). The syntax of these files is described in the Compose(5)
* manual page.
*
* ## Unicode characters
*
* GtkIMContextSimple also supports numeric entry of Unicode characters
* by typing Ctrl-Shift-u, followed by a hexadecimal Unicode codepoint.
* For example, Ctrl-Shift-u 1 2 3 Enter yields U+0123 LATIN SMALL LETTER
* G WITH CEDILLA, i.e. ģ.
*
* ## Emoji
*
* GtkIMContextSimple also supports entry of Emoji by their name.
* This works by first typing Ctrl-Shift-e, followed by an Emoji name.
*
* The following names are supported:
* - :-) 🙂
* - 8-) 😍
* - <3 ❤
* - kiss 💋
* - grin 😁
* - joy 😂
* - :-* 😚
* - xD 😆
* - like 👍
* - dislike 👎
* - up 👆
* - v ✌
* - ok 👌
* - B-) 😎
* - ;-) 😉
* - ;-P 😜
* - :-p 😋
* - 3( 😔
* - :-( 😞
* - :] 😏
* - :'( 😢
* - :_( 😭
* - :(( 😩
* - :o 😨
* - :| 😐
* - 3-) 😌
* - >( 😠
* - >(( 😡
* - O:) 😇
* - ;o 😰
* - 8| 😳
* - 8o 😲
* - :X 😷
* - }:) 😈
*/
struct _GtkIMContextSimplePrivate
{
guint16 compose_buffer[MAX(GTK_MAX_COMPOSE_LEN + 1, 9)];
guint16 compose_buffer[GTK_MAX_COMPOSE_LEN + 1];
gunichar tentative_match;
gint tentative_match_len;
guint in_hex_sequence : 1;
guint in_emoji_sequence : 1;
guint modifiers_dropped : 1;
};
......@@ -339,10 +295,9 @@ gtk_im_context_simple_commit_char (GtkIMContext *context,
len = g_unichar_to_utf8 (ch, buf);
buf[len] = '\0';
if (priv->tentative_match || priv->in_hex_sequence || priv->in_emoji_sequence)
if (priv->tentative_match || priv->in_hex_sequence)
{
priv->in_hex_sequence = FALSE;
priv->in_emoji_sequence = FALSE;
priv->tentative_match = 0;
priv->tentative_match_len = 0;
g_signal_emit_by_name (context_simple, "preedit-changed");
......@@ -910,110 +865,6 @@ check_hex (GtkIMContextSimple *context_simple,
return TRUE;
}
typedef struct {
const char *name;
gunichar ch;
} EmojiItem;
static EmojiItem emoji[] = {
{ ":-)", 0x1f642 },
{ "8-)", 0x1f60d },
{ "<3", 0x02764 },
{ "kiss", 0x1f48b },
{ "grin", 0x1f601 },
{ "joy", 0x1f602 },
{ ":-*", 0x1f61a },
{ "xD", 0x1f606 },
{ "like", 0x1f44d },
{ "dislike", 0x1f44e },
{ "up", 0x1f446 },
{ "v", 0x0270c },
{ "ok", 0x1f44c },
{ "B-)", 0x1f60e },
{ ":-D", 0x1f603 },
{ ";-)", 0x1f609 },
{ ";-P", 0x1f61c },
{ ":-p", 0x1f60b },
{ "3(", 0x1f614 },
{ ":-(", 0x1f61e },
{ ":]", 0x1f60f },
{ ":'(", 0x1f622 },
{ ":_(", 0x1f62d },
{ ":((", 0x1f629 },
{ ":o", 0x1f628 },
{ ":|", 0x1f610 },
{ "3-)", 0x1f60c },
{ ">(", 0x1f620 },
{ ">((", 0x1f621 },
{ "O:)", 0x1f607 },
{ ";o", 0x1f630 },
{ "8|", 0x1f633 },
{ "8o", 0x1f632 },
{ ":X", 0x1f637 },
{ "}:)", 0x1f608 },
{ NULL, 0 }
};
static gboolean
check_emoji (GtkIMContextSimple *context_simple,
gint n_compose)
{
GtkIMContextSimplePrivate *priv = context_simple->priv;
GString *str;
gint i;
gchar buf[7];
char *lower;
gboolean has_completion;
priv->tentative_match = 0;
priv->tentative_match_len = 0;
str = g_string_new (NULL);
i = 0;
while (i < n_compose)
{
gunichar ch;
ch = gdk_keyval_to_unicode (priv->compose_buffer[i]);
if (ch == 0)
return FALSE;
buf[g_unichar_to_utf8 (ch, buf)] = '\0';
g_string_append (str, buf);
++i;
}
lower = g_utf8_strdown (str->str, str->len);
has_completion = FALSE;
for (i = 0; emoji[i].name; i++)
{
if (strcmp (str->str, emoji[i].name) == 0 ||
strcmp (lower, emoji[i].name) == 0)
{
priv->tentative_match = emoji[i].ch;
priv->tentative_match_len = n_compose;
break;
}
if (!has_completion &&
(g_str_has_prefix (emoji[i].name, str->str) ||
g_str_has_prefix (emoji[i].name, lower)))
{
has_completion = TRUE;
}
}
g_string_free (str, TRUE);
g_free (lower);
return priv->tentative_match != 0 || has_completion;
}
static void
beep_window (GdkWindow *window)
{
......@@ -1133,12 +984,6 @@ canonical_hex_keyval (GdkEventKey *event)
return 0;
}
static guint
canonical_emoji_keyval (GdkEventKey *event)
{
return event->keyval;
}
static gboolean
gtk_im_context_simple_filter_keypress (GtkIMContext *context,
GdkEventKey *event)
......@@ -1146,17 +991,15 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
GtkIMContextSimple *context_simple = GTK_IM_CONTEXT_SIMPLE (context);
GtkIMContextSimplePrivate *priv = context_simple->priv;
GdkDisplay *display = gdk_window_get_display (event->window);
GSList *tmp_list;
GSList *tmp_list;
int n_compose = 0;
GdkModifierType hex_mod_mask;
gboolean have_hex_mods;
gboolean is_hex_start;
gboolean is_end;
gboolean is_emoji_start;
gboolean is_hex_end;
gboolean is_backspace;
gboolean is_escape;
guint hex_keyval;
guint emoji_keyval;
int i;
gboolean compose_finish;
gboolean compose_match;
......@@ -1167,43 +1010,38 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
if (event->type == GDK_KEY_RELEASE)
{
if ((event->keyval == GDK_KEY_Control_L || event->keyval == GDK_KEY_Control_R ||
if (priv->in_hex_sequence &&
(event->keyval == GDK_KEY_Control_L || event->keyval == GDK_KEY_Control_R ||
event->keyval == GDK_KEY_Shift_L || event->keyval == GDK_KEY_Shift_R))
{
if ((priv->in_hex_sequence || priv->in_emoji_sequence) &&
priv->tentative_match &&
if (priv->tentative_match &&
g_unichar_validate (priv->tentative_match))
{
gtk_im_context_simple_commit_char (context, priv->tentative_match);
priv->compose_buffer[0] = 0;
return TRUE;
}
else if (priv->in_emoji_sequence ||
(priv->in_hex_sequence && n_compose == 0))
else if (n_compose == 0)
{
priv->modifiers_dropped = TRUE;
return TRUE;
}
else if (priv->in_hex_sequence)
else
{
/* invalid hex sequence */
beep_window (event->window);
priv->tentative_match = 0;
priv->in_hex_sequence = FALSE;
priv->in_emoji_sequence = FALSE;
priv->compose_buffer[0] = 0;
g_signal_emit_by_name (context_simple, "preedit-changed");
g_signal_emit_by_name (context_simple, "preedit-end");
return TRUE;
}
}
return FALSE;
return TRUE;
}
else
return FALSE;
}
/* Ignore modifier key presses */
......@@ -1215,21 +1053,19 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR);
hex_mod_mask |= GDK_SHIFT_MASK;
if ((priv->in_hex_sequence || priv->in_emoji_sequence) && priv->modifiers_dropped)
if (priv->in_hex_sequence && priv->modifiers_dropped)
have_hex_mods = TRUE;
else
have_hex_mods = (event->state & (hex_mod_mask)) == hex_mod_mask;
is_hex_start = event->keyval == GDK_KEY_U;
is_emoji_start = (event->keyval == GDK_KEY_E) && !priv->in_hex_sequence;
is_end = (event->keyval == GDK_KEY_space ||
event->keyval == GDK_KEY_KP_Space ||
event->keyval == GDK_KEY_Return ||
event->keyval == GDK_KEY_ISO_Enter ||
event->keyval == GDK_KEY_KP_Enter);
is_hex_end = (event->keyval == GDK_KEY_space ||
event->keyval == GDK_KEY_KP_Space ||
event->keyval == GDK_KEY_Return ||
event->keyval == GDK_KEY_ISO_Enter ||
event->keyval == GDK_KEY_KP_Enter);
is_backspace = event->keyval == GDK_KEY_BackSpace;
is_escape = event->keyval == GDK_KEY_Escape;
hex_keyval = canonical_hex_keyval (event);
emoji_keyval = canonical_emoji_keyval (event);
/* If we are already in a non-hex sequence, or
* this keystroke is not hex modifiers + hex digit, don't filter
......@@ -1239,11 +1075,10 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
* ISO_Level3_Switch.
*/
if (!have_hex_mods ||
(n_compose > 0 && !priv->in_hex_sequence && !priv->in_emoji_sequence) ||
(n_compose == 0 && !priv->in_hex_sequence && !priv->in_emoji_sequence &&
!is_hex_start && !is_emoji_start) ||
(n_compose > 0 && !priv->in_hex_sequence) ||
(n_compose == 0 && !priv->in_hex_sequence && !is_hex_start) ||
(priv->in_hex_sequence && !hex_keyval &&
!is_hex_start && !is_end && !is_escape && !is_backspace))
!is_hex_start && !is_hex_end && !is_escape && !is_backspace))
{
GdkModifierType no_text_input_mask;
......@@ -1252,7 +1087,7 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
GDK_MODIFIER_INTENT_NO_TEXT_INPUT);
if (event->state & no_text_input_mask ||
((priv->in_hex_sequence || priv->in_emoji_sequence) && priv->modifiers_dropped &&
(priv->in_hex_sequence && priv->modifiers_dropped &&
(event->keyval == GDK_KEY_Return ||
event->keyval == GDK_KEY_ISO_Enter ||
event->keyval == GDK_KEY_KP_Enter)))
......@@ -1262,21 +1097,17 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
}
/* Handle backspace */
if ((priv->in_hex_sequence || priv->in_emoji_sequence) && have_hex_mods && is_backspace)
if (priv->in_hex_sequence && have_hex_mods && is_backspace)
{
if (n_compose > 0)
{
n_compose--;
priv->compose_buffer[n_compose] = 0;
if (priv->in_hex_sequence)
check_hex (context_simple, n_compose);
else if (priv->in_emoji_sequence)
check_emoji (context_simple, n_compose);
check_hex (context_simple, n_compose);
}
else
{
priv->in_hex_sequence = FALSE;
priv->in_emoji_sequence = FALSE;
}
g_signal_emit_by_name (context_simple, "preedit-changed");
......@@ -1296,7 +1127,7 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
gtk_im_context_simple_commit_char (context, priv->tentative_match);
priv->compose_buffer[0] = 0;
}
else
else
{
/* invalid hex sequence */
if (n_compose > 0)
......@@ -1322,20 +1153,6 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
return TRUE;
}
/* Check for emoji sequence start */
if (!priv->in_emoji_sequence && have_hex_mods && is_emoji_start)
{
priv->compose_buffer[0] = 0;
priv->in_emoji_sequence = TRUE;
priv->modifiers_dropped = FALSE;
priv->tentative_match = 0;
g_signal_emit_by_name (context_simple, "preedit-start");
g_signal_emit_by_name (context_simple, "preedit-changed");
return TRUE;
}
/* Then, check for compose sequences */
if (priv->in_hex_sequence)
{
......@@ -1344,54 +1161,29 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
else if (is_escape)
{
gtk_im_context_simple_reset (context);
return TRUE;
}
else if (!is_end)
else if (!is_hex_end)
{
/* non-hex character in hex sequence */
beep_window (event->window);
return TRUE;
}
}
else if (priv->in_emoji_sequence)
{
if (emoji_keyval)
priv->compose_buffer[n_compose++] = emoji_keyval;
else if (is_escape)
{
gtk_im_context_simple_reset (context);
return TRUE;
}
else
{
beep_window (event->window);
return TRUE;
}
}
else
priv->compose_buffer[n_compose++] = event->keyval;
if (n_compose == MAX(GTK_MAX_COMPOSE_LEN + 1, 9))
{
beep_window (event->window);
priv->tentative_match = 0;
priv->in_hex_sequence = FALSE;
priv->in_emoji_sequence = FALSE;
priv->compose_buffer[0] = 0;
g_signal_emit_by_name (context_simple, "preedit-changed");
return TRUE;
}
priv->compose_buffer[n_compose] = 0;
if (priv->in_hex_sequence || priv->in_emoji_sequence)
if (priv->in_hex_sequence)
{
/* If the modifiers are still held down, consider the sequence again */
if (have_hex_mods)
{
/* space or return ends the sequence, and we eat the key */
if (n_compose > 0 && is_end)
if (n_compose > 0 && is_hex_end)
{
if (priv->tentative_match &&
g_unichar_validate (priv->tentative_match))
......@@ -1406,17 +1198,15 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
priv->tentative_match = 0;
priv->in_hex_sequence = FALSE;
priv->in_emoji_sequence = FALSE;
priv->compose_buffer[0] = 0;
}
}
else if ((priv->in_hex_sequence && !check_hex (context_simple, n_compose)) ||
(priv->in_emoji_sequence && !check_emoji (context_simple, n_compose)))
else if (!check_hex (context_simple, n_compose))
beep_window (event->window);
g_signal_emit_by_name (context_simple, "preedit-changed");
if (!priv->in_hex_sequence && !priv->in_emoji_sequence)
if (!priv->in_hex_sequence)
g_signal_emit_by_name (context_simple, "preedit-end");
return TRUE;
......@@ -1540,10 +1330,9 @@ gtk_im_context_simple_reset (GtkIMContext *context)
priv->compose_buffer[0] = 0;
if (priv->tentative_match || priv->in_hex_sequence || priv->in_emoji_sequence)
if (priv->tentative_match || priv->in_hex_sequence)
{
priv->in_hex_sequence = FALSE;
priv->in_emoji_sequence = FALSE;
priv->tentative_match = 0;
priv->tentative_match_len = 0;
g_signal_emit_by_name (context_simple, "preedit-changed");
......@@ -1562,11 +1351,11 @@ gtk_im_context_simple_get_preedit_string (GtkIMContext *context,
char outbuf[37]; /* up to 6 hex digits */
int len = 0;
if (priv->in_hex_sequence || priv->in_emoji_sequence)
if (priv->in_hex_sequence)
{
int hexchars = 0;
outbuf[0] = priv->in_hex_sequence ? 'u' : 'e';
outbuf[0] = 'u';
len = 1;
while (priv->compose_buffer[hexchars] != 0)
......@@ -1580,8 +1369,8 @@ gtk_im_context_simple_get_preedit_string (GtkIMContext *context,
}
else if (priv->tentative_match)
len = g_unichar_to_utf8 (priv->tentative_match, outbuf);
outbuf[len] = '\0';
outbuf[len] = '\0';
if (str)
*str = g_strdup (outbuf);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment