[gnome-builder] terminal: add context menu
- From: Sébastien Lafargue <slafargue src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] terminal: add context menu
- Date: Sat, 5 Mar 2016 11:26:08 +0000 (UTC)
commit 992b88370e2a09d594a732b9ca4165175b233450
Author: Sebastien Lafargue <slafargue gnome org>
Date: Fri Mar 4 17:13:26 2016 +0100
terminal: add context menu
plugins/terminal/gb-terminal.c | 189 +++++++++++++++++++++++++++++++++++++++-
plugins/terminal/gtk/menus.ui | 28 ++++++
2 files changed, 216 insertions(+), 1 deletions(-)
---
diff --git a/plugins/terminal/gb-terminal.c b/plugins/terminal/gb-terminal.c
index 946b934..c216f28 100644
--- a/plugins/terminal/gb-terminal.c
+++ b/plugins/terminal/gb-terminal.c
@@ -16,25 +16,211 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <glib/gi18n.h>
+#include <ide.h>
+
+#include "egg-widget-action-group.h"
+
#include "gb-terminal.h"
+typedef struct
+{
+ GbTerminal *terminal;
+ guint button;
+ guint time;
+ GdkDevice *device;
+} PopupInfo;
+
struct _GbTerminal
{
- VteTerminal parent;
+ VteTerminal parent;
+
+ GtkWidget *popup_menu;
};
struct _GbTerminalClass
{
VteTerminalClass parent;
+
+ void (*populate_popup) (GbTerminal *self,
+ GtkWidget *widget);
+ void (*select_all) (GbTerminal *self,
+ gboolean all);
};
G_DEFINE_TYPE (GbTerminal, gb_terminal, VTE_TYPE_TERMINAL)
+enum {
+ POPULATE_POPUP,
+ SELECT_ALL,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL];
+
+/* The popup code is an adaptation of GtktextView popupmenu functions */
+static void
+popup_menu_detach (GtkWidget *attach_widget,
+ GtkMenu *menu)
+{
+ GbTerminal *terminal = GB_TERMINAL (attach_widget);
+
+ terminal->popup_menu = NULL;
+}
+
+static void
+popup_targets_received (GtkClipboard *clipboard,
+ GtkSelectionData *data,
+ gpointer user_data)
+{
+ GMenu *menu;
+ PopupInfo *popup_info = user_data;
+ GbTerminal *terminal = popup_info->terminal;
+
+ if (gtk_widget_get_realized (GTK_WIDGET (terminal)))
+ {
+ GActionGroup *group;
+ GAction *action;
+ gboolean clipboard_contains_text;
+ gboolean have_selection;
+
+ clipboard_contains_text = gtk_selection_data_targets_include_text (data);
+ have_selection = vte_terminal_get_has_selection (VTE_TERMINAL (terminal));
+
+ if (terminal->popup_menu)
+ gtk_widget_destroy (terminal->popup_menu);
+
+ menu = ide_application_get_menu_by_id (IDE_APPLICATION_DEFAULT, "gb-terminal-view-popup-menu");
+ terminal->popup_menu = gtk_menu_new_from_model (G_MENU_MODEL (menu));
+
+ group = gtk_widget_get_action_group (GTK_WIDGET (terminal), "terminal");
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (group), "copy-clipboard");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), have_selection);
+ action = g_action_map_lookup_action (G_ACTION_MAP (group), "paste-clipboard");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), clipboard_contains_text);
+
+ gtk_style_context_add_class (gtk_widget_get_style_context (terminal->popup_menu),
GTK_STYLE_CLASS_CONTEXT_MENU);
+ gtk_menu_attach_to_widget (GTK_MENU (terminal->popup_menu), GTK_WIDGET (terminal), popup_menu_detach);
+
+ g_signal_emit (terminal, signals[POPULATE_POPUP], 0, terminal->popup_menu);
+
+ if (popup_info->device)
+ gtk_menu_popup_for_device (GTK_MENU (terminal->popup_menu),
+ popup_info->device, NULL, NULL, NULL, NULL, NULL,
+ popup_info->button, popup_info->time);
+ else
+ {
+ gtk_menu_popup (GTK_MENU (terminal->popup_menu), NULL, NULL,
+ NULL, terminal,
+ 0, gtk_get_current_event_time ());
+
+ gtk_menu_shell_select_first (GTK_MENU_SHELL (terminal->popup_menu), FALSE);
+ }
+ }
+
+ g_object_unref (terminal);
+ g_slice_free (PopupInfo, popup_info);
+}
+
+static void
+gb_terminal_do_popup (GbTerminal *terminal,
+ const GdkEvent *event)
+{
+ PopupInfo *popup_info = g_slice_new (PopupInfo);
+
+ popup_info->terminal = g_object_ref (terminal);
+
+ if (event != NULL)
+ {
+ gdk_event_get_button (event, &popup_info->button);
+ popup_info->time = gdk_event_get_time (event);
+ popup_info->device = gdk_event_get_device (event);
+ }
+ else
+ {
+ popup_info->button = 0;
+ popup_info->time = gtk_get_current_event_time ();
+ popup_info->device = NULL;
+ }
+
+ gtk_clipboard_request_contents (gtk_widget_get_clipboard (GTK_WIDGET (terminal), GDK_SELECTION_CLIPBOARD),
+ gdk_atom_intern_static_string ("TARGETS"),
+ popup_targets_received,
+ popup_info);
+}
+
+static gboolean
+gb_terminal_popup_menu (GtkWidget *widget)
+{
+ gb_terminal_do_popup (GB_TERMINAL (widget), NULL);
+ return TRUE;
+}
+
+static gboolean
+gb_terminal_button_press_event (GtkWidget *widget,
+ GdkEventButton *button)
+{
+ GbTerminal *self = (GbTerminal *)widget;
+
+ g_assert (GB_IS_TERMINAL (self));
+ g_assert (button != NULL);
+
+ if ((button->type == GDK_BUTTON_PRESS) && (button->button == GDK_BUTTON_SECONDARY))
+ {
+ if (!gtk_widget_has_focus (GTK_WIDGET (self)))
+ gtk_widget_grab_focus (GTK_WIDGET (self));
+
+ gb_terminal_do_popup (self, (GdkEvent *)button);
+ return GDK_EVENT_STOP;
+ }
+
+ return GTK_WIDGET_CLASS (gb_terminal_parent_class)->button_press_event (widget, button);
+}
+
+static void
+gb_terminal_real_select_all (GbTerminal *self,
+ gboolean all)
+{
+ g_assert (GB_IS_TERMINAL (self));
+
+ if (all)
+ vte_terminal_select_all (VTE_TERMINAL (self));
+ else
+ vte_terminal_unselect_all (VTE_TERMINAL (self));
+}
+
static void
gb_terminal_class_init (GbTerminalClass *klass)
{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkBindingSet *binding_set;
+ widget_class->button_press_event = gb_terminal_button_press_event;
+ widget_class->popup_menu = gb_terminal_popup_menu;
+
+ klass->select_all = gb_terminal_real_select_all;
+
+ signals [POPULATE_POPUP] =
+ g_signal_new ("populate-popup",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GbTerminalClass, populate_popup),
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 1,
+ GTK_TYPE_WIDGET);
+
+ signals [SELECT_ALL] =
+ g_signal_new ("select-all",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GbTerminalClass, select_all),
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_BOOLEAN);
+
binding_set = gtk_binding_set_by_class (klass);
gtk_binding_entry_add_signal (binding_set,
@@ -53,4 +239,5 @@ gb_terminal_class_init (GbTerminalClass *klass)
static void
gb_terminal_init (GbTerminal *self)
{
+ egg_widget_action_group_attach (self, "terminal");
}
diff --git a/plugins/terminal/gtk/menus.ui b/plugins/terminal/gtk/menus.ui
index b53270f..bd35ebf 100644
--- a/plugins/terminal/gtk/menus.ui
+++ b/plugins/terminal/gtk/menus.ui
@@ -9,4 +9,32 @@
</item>
</section>
</menu>
+ <menu id="gb-terminal-view-popup-menu">
+ <section id="gb-terminal-view-popup-menu-clipboard-section">
+ <item>
+ <attribute name="id">copy</attribute>
+ <attribute name="label" translatable="yes">_Copy</attribute>
+ <attribute name="action">terminal.copy-clipboard</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Paste</attribute>
+ <attribute name="action">terminal.paste-clipboard</attribute>
+ </item>
+ </section>
+ <section id="gb-terminal-view-popup-menu-selection-section">
+ <submenu id="gb-terminal-view-popup-menu-selection-submenu">
+ <attribute name="label" translatable="yes">Selection</attribute>
+ <item>
+ <attribute name="label" translatable="yes">Select _All</attribute>
+ <attribute name="action">terminal.select-all</attribute>
+ <attribute name="target" type="(b)">(true,)</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Select _None</attribute>
+ <attribute name="action">terminal.select-all</attribute>
+ <attribute name="target" type="(b)">(false,)</attribute>
+ </item>
+ </submenu>
+ </section>
+ </menu>
</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]