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
This commit is contained in:
Matthias Clasen 2017-11-22 16:47:43 -05:00
parent 462a77ffb5
commit 567447456e
2 changed files with 77 additions and 1 deletions

View File

@ -57,6 +57,7 @@
#include "gtkpopover.h"
#include "gtktoolbar.h"
#include "gtkmagnifierprivate.h"
#include "gtkemojichooser.h"
#include "a11y/gtktextviewaccessibleprivate.h"
@ -325,6 +326,7 @@ enum
TOGGLE_CURSOR_VISIBLE,
PREEDIT_CHANGED,
EXTEND_SELECTION,
INSERT_EMOJI,
LAST_SIGNAL
};
@ -575,6 +577,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,
@ -754,6 +757,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
@ -1401,6 +1405,25 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
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
*/
@ -1599,6 +1622,12 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
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);
@ -8887,6 +8916,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);
@ -10299,3 +10338,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));
}

View File

@ -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