[gtk+/gtk-3-22] text view: Support the Emoji chooser



commit f922aee5e292688621b1162d775e496edbb7e8fd
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Nov 22 16:47:43 2017 -0500

    text view: Support the Emoji chooser
    
    Similar to GtkEntry, add an "Insert Emoji" context
    menu item, and add the same keybindings. We don't
    add the icon here, since it is not clear where it
    would go.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=790029

 gtk/gtktextview.c |   76 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 gtk/gtktextview.h |    2 +-
 2 files changed, 77 insertions(+), 1 deletions(-)
---
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index c5f76b0..61395ef 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -57,6 +57,7 @@
 #include "gtktoolbar.h"
 #include "gtkpixelcacheprivate.h"
 #include "gtkmagnifierprivate.h"
+#include "gtkemojichooser.h"
 
 #include "a11y/gtktextviewaccessibleprivate.h"
 
@@ -332,6 +333,7 @@ enum
   TOGGLE_CURSOR_VISIBLE,
   PREEDIT_CHANGED,
   EXTEND_SELECTION,
+  INSERT_EMOJI,
   LAST_SIGNAL
 };
 
@@ -584,6 +586,7 @@ static void     gtk_text_view_set_hadjustment_values (GtkTextView   *text_view);
 static void     gtk_text_view_set_vadjustment_values (GtkTextView   *text_view);
 
 static void gtk_text_view_update_im_spot_location (GtkTextView *text_view);
+static void gtk_text_view_insert_emoji (GtkTextView *text_view);
 
 /* Container methods */
 static void gtk_text_view_add    (GtkContainer *container,
@@ -785,6 +788,7 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
   klass->toggle_overwrite = gtk_text_view_toggle_overwrite;
   klass->create_buffer = gtk_text_view_create_buffer;
   klass->extend_selection = gtk_text_view_extend_selection;
+  klass->insert_emoji = gtk_text_view_insert_emoji;
 
   /*
    * Properties
@@ -1444,6 +1448,25 @@ G_GNUC_END_IGNORE_DEPRECATIONS
                   GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE,
                   GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE);
 
+  /**
+   * GtkTextView::insert-emoji:
+   * @text_view: the object which received the signal
+   *
+   * The ::insert-emoji signal is a
+   * [keybinding signal][GtkBindingSignal]
+   * which gets emitted to present the Emoji chooser for the text_view.
+   *
+   * The default bindings for this signal are Ctrl-. and Ctrl-;
+   */
+  signals[INSERT_EMOJI] =
+    g_signal_new (I_("insert-emoji"),
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                  G_STRUCT_OFFSET (GtkTextViewClass, insert_emoji),
+                  NULL, NULL,
+                  NULL,
+                  G_TYPE_NONE, 0);
+
   /*
    * Key bindings
    */
@@ -1642,6 +1665,12 @@ G_GNUC_END_IGNORE_DEPRECATIONS
   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, 0,
                                "toggle-overwrite", 0);
 
+  /* Emoji */
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_period, GDK_CONTROL_MASK,
+                                "insert-emoji", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_semicolon, GDK_CONTROL_MASK,
+                                "insert-emoji", 0);
+
   /* Caret mode */
   gtk_binding_entry_add_signal (binding_set, GDK_KEY_F7, 0,
                                "toggle-cursor-visible", 0);
@@ -9484,6 +9513,16 @@ popup_targets_received (GtkClipboard     *clipboard,
       gtk_widget_show (menuitem);
       gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
 
+      if ((gtk_text_view_get_input_hints (text_view) & GTK_INPUT_HINT_NO_EMOJI) == 0)
+        {
+          menuitem = gtk_menu_item_new_with_mnemonic (_("Insert _Emoji"));
+          gtk_widget_set_sensitive (menuitem, can_insert);
+          g_signal_connect_swapped (menuitem, "activate",
+                                    G_CALLBACK (gtk_text_view_insert_emoji), text_view);
+          gtk_widget_show (menuitem);
+          gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
+        }
+
       g_signal_emit (text_view, signals[POPULATE_POPUP],
                     0, priv->popup_menu);
 
@@ -11402,3 +11441,40 @@ gtk_text_view_get_monospace (GtkTextView *text_view)
   
   return gtk_style_context_has_class (context, GTK_STYLE_CLASS_MONOSPACE);
 }
+
+static void
+gtk_text_view_insert_emoji (GtkTextView *text_view)
+{
+  GtkWidget *chooser;
+  GtkTextIter iter;
+  GdkRectangle rect;
+  GtkTextBuffer *buffer;
+
+  if (gtk_widget_get_ancestor (GTK_WIDGET (text_view), GTK_TYPE_EMOJI_CHOOSER) != NULL)
+    return;
+
+  chooser = GTK_WIDGET (g_object_get_data (G_OBJECT (text_view), "gtk-emoji-chooser"));
+  if (!chooser)
+    {
+      chooser = gtk_emoji_chooser_new ();
+      g_object_set_data (G_OBJECT (text_view), "gtk-emoji-chooser", chooser);
+
+      gtk_popover_set_relative_to (GTK_POPOVER (chooser), GTK_WIDGET (text_view));
+      g_signal_connect_swapped (chooser, "emoji-picked",
+                                G_CALLBACK (gtk_text_view_insert_at_cursor), text_view);
+    }
+
+  buffer = get_buffer (text_view);
+  gtk_text_buffer_get_iter_at_mark (buffer, &iter,
+                                    gtk_text_buffer_get_insert (buffer));
+
+  gtk_text_view_get_iter_location (text_view, &iter, (GdkRectangle *) &rect);
+  gtk_text_view_buffer_to_window_coords (text_view, GTK_TEXT_WINDOW_TEXT,
+                                         rect.x, rect.y, &rect.x, &rect.y);
+  _text_window_to_widget_coords (text_view, &rect.x, &rect.y);
+
+  gtk_popover_set_pointing_to (GTK_POPOVER (chooser), &rect);
+
+  gtk_popover_popup (GTK_POPOVER (chooser));
+}
+
diff --git a/gtk/gtktextview.h b/gtk/gtktextview.h
index 21d0056..f70dc49 100644
--- a/gtk/gtktextview.h
+++ b/gtk/gtktextview.h
@@ -191,6 +191,7 @@ struct _GtkTextViewClass
                                   const GtkTextIter      *location,
                                   GtkTextIter            *start,
                                   GtkTextIter            *end);
+  void (* insert_emoji)          (GtkTextView      *text_view);
 
   /*< private >*/
 
@@ -199,7 +200,6 @@ struct _GtkTextViewClass
   void (*_gtk_reserved2) (void);
   void (*_gtk_reserved3) (void);
   void (*_gtk_reserved4) (void);
-  void (*_gtk_reserved5) (void);
 };
 
 GDK_AVAILABLE_IN_ALL


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]