summaryrefslogtreecommitdiff
path: root/gtk/gtkentry.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2017-08-11 12:05:24 -0400
committerMatthias Clasen <mclasen@redhat.com>2017-08-12 18:48:14 -0400
commit558aebfbc4699bf4182df16509fd8c19c0ffd6e3 (patch)
tree2a9fc72b7ee8aa65c9f9e5126a0571bdcdc76b71 /gtk/gtkentry.c
parent46f7804f3aac1e4007a93e6247d1587705e56e90 (diff)
downloadgtk+-558aebfbc4699bf4182df16509fd8c19c0ffd6e3.tar.gz
entry: Add support for an Emoji chooser
Add an "Insert Emoji" item to the context menu in entries. We also add a show-emoji-icon property, which when set to TRUE, will add an icon that can be clicked to bring up the Emoji chooser.
Diffstat (limited to 'gtk/gtkentry.c')
-rw-r--r--gtk/gtkentry.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index 7240ec9b0a..a0c2f5ca25 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -68,6 +68,7 @@
#include "gtkmagnifierprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkimageprivate.h"
+#include "gtkemojichooser.h"
#include "a11y/gtkentryaccessible.h"
@@ -235,6 +236,7 @@ struct _GtkEntryPrivate
gint64 handle_place_time;
guint editable : 1;
+ guint show_emoji_icon : 1;
guint in_drag : 1;
guint overwrite_mode : 1;
guint visible : 1;
@@ -354,6 +356,7 @@ enum {
PROP_ATTRIBUTES,
PROP_POPULATE_ALL,
PROP_TABS,
+ PROP_SHOW_EMOJI_ICON,
PROP_EDITING_CANCELED,
NUM_PROPERTIES = PROP_EDITING_CANCELED
};
@@ -645,6 +648,8 @@ static void buffer_notify_max_length (GtkEntryBuffer *buffer,
static void buffer_connect_signals (GtkEntry *entry);
static void buffer_disconnect_signals (GtkEntry *entry);
static GtkEntryBuffer *get_buffer (GtkEntry *entry);
+static void set_show_emoji_icon (GtkEntry *entry,
+ gboolean value);
static void gtk_entry_measure (GtkWidget *widget,
GtkOrientation orientation,
@@ -1375,6 +1380,21 @@ gtk_entry_class_init (GtkEntryClass *class)
PANGO_TYPE_TAB_ARRAY,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+ /**
+ * GtkEntry::show-emoji-icon:
+ *
+ * When this is %TRUE, the entry will show an emoji icon in the secondary
+ * icon position that brings up the Emoji chooser when clicked.
+ *
+ * Since: 3.92
+ */
+ entry_props[PROP_SHOW_EMOJI_ICON] =
+ g_param_spec_boolean ("show-emoji-icon",
+ P_("Emoji icon"),
+ P_("Whether to show an icon for Emoji"),
+ FALSE,
+ GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, entry_props);
/**
@@ -2130,6 +2150,10 @@ gtk_entry_set_property (GObject *object,
gtk_entry_set_tabs (entry, g_value_get_boxed (value));
break;
+ case PROP_SHOW_EMOJI_ICON:
+ set_show_emoji_icon (entry, g_value_get_boolean (value));
+ break;
+
case PROP_SCROLL_OFFSET:
case PROP_CURSOR_POSITION:
default:
@@ -2358,6 +2382,10 @@ gtk_entry_get_property (GObject *object,
g_value_set_boxed (value, priv->tabs);
break;
+ case PROP_SHOW_EMOJI_ICON:
+ g_value_set_boolean (value, priv->show_emoji_icon);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -8406,6 +8434,8 @@ typedef struct
GdkEvent *trigger_event;
} PopupInfo;
+static void gtk_entry_choose_emoji (GtkEntry *entry);
+
static void
popup_targets_received (GtkClipboard *clipboard,
GtkSelectionData *data,
@@ -8462,6 +8492,15 @@ popup_targets_received (GtkClipboard *clipboard,
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ menuitem = gtk_menu_item_new_with_mnemonic (_("Insert _Emoji"));
+ gtk_widget_set_sensitive (menuitem,
+ mode == DISPLAY_NORMAL &&
+ info_entry_priv->editable);
+ g_signal_connect_swapped (menuitem, "activate",
+ G_CALLBACK (gtk_entry_choose_emoji), entry);
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+
g_signal_emit (entry, signals[POPULATE_POPUP], 0, menu);
if (info->trigger_event && gdk_event_triggers_context_menu (info->trigger_event))
@@ -9792,3 +9831,68 @@ gtk_entry_get_tabs (GtkEntry *entry)
return entry->priv->tabs;
}
+
+static void
+gtk_entry_choose_emoji (GtkEntry *entry)
+{
+ GtkWidget *chooser;
+ GdkRectangle rect;
+
+ chooser = GTK_WIDGET (g_object_get_data (G_OBJECT (entry), "gtk-emoji-chooser"));
+ if (!chooser)
+ {
+ chooser = gtk_emoji_chooser_new ();
+ g_object_set_data_full (G_OBJECT (entry), "gtk-emoji-chooser", chooser, (GDestroyNotify)gtk_widget_destroy);
+
+ gtk_popover_set_relative_to (GTK_POPOVER (chooser), GTK_WIDGET (entry));
+ if (entry->priv->show_emoji_icon)
+ {
+ gtk_entry_get_icon_area (entry, GTK_ENTRY_ICON_SECONDARY, &rect);
+ gtk_popover_set_pointing_to (GTK_POPOVER (chooser), &rect);
+ }
+ g_signal_connect_swapped (chooser, "emoji-picked", G_CALLBACK (gtk_entry_enter_text), entry);
+ }
+
+ gtk_popover_popup (GTK_POPOVER (chooser));
+}
+
+static void
+pick_emoji (GtkEntry *entry,
+ int icon,
+ GdkEvent *event,
+ gpointer data)
+{
+ gtk_entry_choose_emoji (entry);
+}
+
+static void
+set_show_emoji_icon (GtkEntry *entry,
+ gboolean value)
+{
+ GtkEntryPrivate *priv = entry->priv;
+
+ if (priv->show_emoji_icon == value)
+ return;
+
+ priv->show_emoji_icon = value;
+
+ if (priv->show_emoji_icon)
+ {
+ gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry),
+ GTK_ENTRY_ICON_SECONDARY,
+ "face-smile-symbolic");
+
+ gtk_entry_set_icon_sensitive (GTK_ENTRY (entry),
+ GTK_ENTRY_ICON_SECONDARY,
+ TRUE);
+
+ gtk_entry_set_icon_activatable (GTK_ENTRY (entry),
+ GTK_ENTRY_ICON_SECONDARY,
+ TRUE);
+
+ g_signal_connect (entry, "icon-press", G_CALLBACK (pick_emoji), NULL);
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (entry), entry_props[PROP_SHOW_EMOJI_ICON]);
+ gtk_widget_queue_resize (GTK_WIDGET (entry));
+}