summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2001-10-22 20:47:01 +0000
committerOwen Taylor <otaylor@src.gnome.org>2001-10-22 20:47:01 +0000
commit92d2dc0ba639efbc360a3de34d4a2ae722afa098 (patch)
tree07727da269ec0f3ecac5f8e6973354999342fdcc
parent8fe966936c5b855b27aca8e9b2d07839d14662a4 (diff)
downloadgtk+-92d2dc0ba639efbc360a3de34d4a2ae722afa098.tar.gz
Fixing popup menus to have "Paste" sensitized correctly. Original patches
Mon Oct 22 16:25:12 2001 Owen Taylor <otaylor@redhat.com> Fixing popup menus to have "Paste" sensitized correctly. Original patches from Damian Ivereigh, much mangled. * gtk/gtkselection.c: Add functions gtk_selection_data_get_targets(), gtk_selection_data_targets_include_text(). (#60854) * gtk/gtkclipboard.c: Add a simple do-it-all non-async "check if the clipboard has text" function gtk_clipboard_wait_is_text_available. (#60854) * gtk/gtkentry.c: Only enable the paste item if the clipboard contains text. (#60973) * gtk/gtktextview.c: Only enable the paste item if the clipboard contains text. (#60975)
-rw-r--r--ChangeLog18
-rw-r--r--ChangeLog.pre-2-018
-rw-r--r--ChangeLog.pre-2-1018
-rw-r--r--ChangeLog.pre-2-218
-rw-r--r--ChangeLog.pre-2-418
-rw-r--r--ChangeLog.pre-2-618
-rw-r--r--ChangeLog.pre-2-818
-rw-r--r--gtk/gtkclipboard.c32
-rw-r--r--gtk/gtkclipboard.h28
-rw-r--r--gtk/gtkentry.c144
-rw-r--r--gtk/gtkselection.c78
-rw-r--r--gtk/gtkselection.h5
-rw-r--r--gtk/gtktextview.c149
13 files changed, 449 insertions, 113 deletions
diff --git a/ChangeLog b/ChangeLog
index 6db2b8fc4f..e0bc24e669 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+Mon Oct 22 16:25:12 2001 Owen Taylor <otaylor@redhat.com>
+
+ Fixing popup menus to have "Paste" sensitized correctly. Original
+ patches from Damian Ivereigh, much mangled.
+
+ * gtk/gtkselection.c: Add functions gtk_selection_data_get_targets(),
+ gtk_selection_data_targets_include_text(). (#60854)
+
+ * gtk/gtkclipboard.c: Add a simple do-it-all non-async "check if
+ the clipboard has text" function gtk_clipboard_wait_is_text_available.
+ (#60854)
+
+ * gtk/gtkentry.c: Only enable the paste item if the clipboard
+ contains text. (#60973)
+
+ * gtk/gtktextview.c: Only enable the paste item if the clipboard
+ contains text. (#60975)
+
2001-10-22 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c (gtk_text_view_class_init): rip out
diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0
index 6db2b8fc4f..e0bc24e669 100644
--- a/ChangeLog.pre-2-0
+++ b/ChangeLog.pre-2-0
@@ -1,3 +1,21 @@
+Mon Oct 22 16:25:12 2001 Owen Taylor <otaylor@redhat.com>
+
+ Fixing popup menus to have "Paste" sensitized correctly. Original
+ patches from Damian Ivereigh, much mangled.
+
+ * gtk/gtkselection.c: Add functions gtk_selection_data_get_targets(),
+ gtk_selection_data_targets_include_text(). (#60854)
+
+ * gtk/gtkclipboard.c: Add a simple do-it-all non-async "check if
+ the clipboard has text" function gtk_clipboard_wait_is_text_available.
+ (#60854)
+
+ * gtk/gtkentry.c: Only enable the paste item if the clipboard
+ contains text. (#60973)
+
+ * gtk/gtktextview.c: Only enable the paste item if the clipboard
+ contains text. (#60975)
+
2001-10-22 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c (gtk_text_view_class_init): rip out
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index 6db2b8fc4f..e0bc24e669 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -1,3 +1,21 @@
+Mon Oct 22 16:25:12 2001 Owen Taylor <otaylor@redhat.com>
+
+ Fixing popup menus to have "Paste" sensitized correctly. Original
+ patches from Damian Ivereigh, much mangled.
+
+ * gtk/gtkselection.c: Add functions gtk_selection_data_get_targets(),
+ gtk_selection_data_targets_include_text(). (#60854)
+
+ * gtk/gtkclipboard.c: Add a simple do-it-all non-async "check if
+ the clipboard has text" function gtk_clipboard_wait_is_text_available.
+ (#60854)
+
+ * gtk/gtkentry.c: Only enable the paste item if the clipboard
+ contains text. (#60973)
+
+ * gtk/gtktextview.c: Only enable the paste item if the clipboard
+ contains text. (#60975)
+
2001-10-22 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c (gtk_text_view_class_init): rip out
diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2
index 6db2b8fc4f..e0bc24e669 100644
--- a/ChangeLog.pre-2-2
+++ b/ChangeLog.pre-2-2
@@ -1,3 +1,21 @@
+Mon Oct 22 16:25:12 2001 Owen Taylor <otaylor@redhat.com>
+
+ Fixing popup menus to have "Paste" sensitized correctly. Original
+ patches from Damian Ivereigh, much mangled.
+
+ * gtk/gtkselection.c: Add functions gtk_selection_data_get_targets(),
+ gtk_selection_data_targets_include_text(). (#60854)
+
+ * gtk/gtkclipboard.c: Add a simple do-it-all non-async "check if
+ the clipboard has text" function gtk_clipboard_wait_is_text_available.
+ (#60854)
+
+ * gtk/gtkentry.c: Only enable the paste item if the clipboard
+ contains text. (#60973)
+
+ * gtk/gtktextview.c: Only enable the paste item if the clipboard
+ contains text. (#60975)
+
2001-10-22 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c (gtk_text_view_class_init): rip out
diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4
index 6db2b8fc4f..e0bc24e669 100644
--- a/ChangeLog.pre-2-4
+++ b/ChangeLog.pre-2-4
@@ -1,3 +1,21 @@
+Mon Oct 22 16:25:12 2001 Owen Taylor <otaylor@redhat.com>
+
+ Fixing popup menus to have "Paste" sensitized correctly. Original
+ patches from Damian Ivereigh, much mangled.
+
+ * gtk/gtkselection.c: Add functions gtk_selection_data_get_targets(),
+ gtk_selection_data_targets_include_text(). (#60854)
+
+ * gtk/gtkclipboard.c: Add a simple do-it-all non-async "check if
+ the clipboard has text" function gtk_clipboard_wait_is_text_available.
+ (#60854)
+
+ * gtk/gtkentry.c: Only enable the paste item if the clipboard
+ contains text. (#60973)
+
+ * gtk/gtktextview.c: Only enable the paste item if the clipboard
+ contains text. (#60975)
+
2001-10-22 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c (gtk_text_view_class_init): rip out
diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6
index 6db2b8fc4f..e0bc24e669 100644
--- a/ChangeLog.pre-2-6
+++ b/ChangeLog.pre-2-6
@@ -1,3 +1,21 @@
+Mon Oct 22 16:25:12 2001 Owen Taylor <otaylor@redhat.com>
+
+ Fixing popup menus to have "Paste" sensitized correctly. Original
+ patches from Damian Ivereigh, much mangled.
+
+ * gtk/gtkselection.c: Add functions gtk_selection_data_get_targets(),
+ gtk_selection_data_targets_include_text(). (#60854)
+
+ * gtk/gtkclipboard.c: Add a simple do-it-all non-async "check if
+ the clipboard has text" function gtk_clipboard_wait_is_text_available.
+ (#60854)
+
+ * gtk/gtkentry.c: Only enable the paste item if the clipboard
+ contains text. (#60973)
+
+ * gtk/gtktextview.c: Only enable the paste item if the clipboard
+ contains text. (#60975)
+
2001-10-22 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c (gtk_text_view_class_init): rip out
diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8
index 6db2b8fc4f..e0bc24e669 100644
--- a/ChangeLog.pre-2-8
+++ b/ChangeLog.pre-2-8
@@ -1,3 +1,21 @@
+Mon Oct 22 16:25:12 2001 Owen Taylor <otaylor@redhat.com>
+
+ Fixing popup menus to have "Paste" sensitized correctly. Original
+ patches from Damian Ivereigh, much mangled.
+
+ * gtk/gtkselection.c: Add functions gtk_selection_data_get_targets(),
+ gtk_selection_data_targets_include_text(). (#60854)
+
+ * gtk/gtkclipboard.c: Add a simple do-it-all non-async "check if
+ the clipboard has text" function gtk_clipboard_wait_is_text_available.
+ (#60854)
+
+ * gtk/gtkentry.c: Only enable the paste item if the clipboard
+ contains text. (#60973)
+
+ * gtk/gtktextview.c: Only enable the paste item if the clipboard
+ contains text. (#60975)
+
2001-10-22 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c (gtk_text_view_class_init): rip out
diff --git a/gtk/gtkclipboard.c b/gtk/gtkclipboard.c
index df2ef1d3d0..6556231733 100644
--- a/gtk/gtkclipboard.c
+++ b/gtk/gtkclipboard.c
@@ -820,3 +820,35 @@ gtk_clipboard_wait_for_text (GtkClipboard *clipboard)
return results.data;
}
+/**
+ * gtk_clipboard_wait_is_text_available:
+ * @clipboard: a #GtkClipboard
+ *
+ * Test to see if there is text available to be pasted
+ * This is done by requesting the TARGETS atom and checking
+ * if it contains any of the names: STRING, TEXT, COMPOUND_TEXT,
+ * UTF8_STRING. This function waits for the data to be received
+ * using the main loop, so events, timeouts, etc, may be dispatched
+ * during the wait.
+ *
+ * This function is a little faster than calling
+ * gtk_clipboard_wait_for_text() since it doesn't need to retrieve
+ * the actual text.
+ *
+ * Return value: %TRUE is there is text available, %FALSE otherwise.
+ **/
+gboolean
+gtk_clipboard_wait_is_text_available (GtkClipboard *clipboard)
+{
+ GtkSelectionData *data;
+ gboolean result = FALSE;
+
+ data = gtk_clipboard_wait_for_contents (clipboard, gdk_atom_intern ("TARGETS", FALSE));
+ if (data)
+ {
+ result = gtk_selection_data_targets_include_text (data);
+ gtk_selection_data_free (data);
+ }
+
+ return result;
+}
diff --git a/gtk/gtkclipboard.h b/gtk/gtkclipboard.h
index d7ed47c987..94a9bb0d5c 100644
--- a/gtk/gtkclipboard.h
+++ b/gtk/gtkclipboard.h
@@ -30,12 +30,12 @@ extern "C" {
typedef struct _GtkClipboard GtkClipboard;
-typedef void (* GtkClipboardReceivedFunc) (GtkClipboard *clipboard,
- GtkSelectionData *selection_data,
- gpointer data);
-typedef void (* GtkClipboardTextReceivedFunc) (GtkClipboard *clipboard,
- const gchar *text,
- gpointer data);
+typedef void (* GtkClipboardReceivedFunc) (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ gpointer data);
+typedef void (* GtkClipboardTextReceivedFunc) (GtkClipboard *clipboard,
+ const gchar *text,
+ gpointer data);
/* Should these functions have GtkClipboard *clipboard as the first argument?
* right now for ClearFunc, you may have trouble determining _which_ clipboard
@@ -68,18 +68,20 @@ void gtk_clipboard_set_text (GtkClipboard *clipboard,
const gchar *text,
gint len);
-void gtk_clipboard_request_contents (GtkClipboard *clipboard,
- GdkAtom target,
- GtkClipboardReceivedFunc callback,
- gpointer user_data);
-void gtk_clipboard_request_text (GtkClipboard *clipboard,
- GtkClipboardTextReceivedFunc callback,
- gpointer user_data);
+void gtk_clipboard_request_contents (GtkClipboard *clipboard,
+ GdkAtom target,
+ GtkClipboardReceivedFunc callback,
+ gpointer user_data);
+void gtk_clipboard_request_text (GtkClipboard *clipboard,
+ GtkClipboardTextReceivedFunc callback,
+ gpointer user_data);
GtkSelectionData *gtk_clipboard_wait_for_contents (GtkClipboard *clipboard,
GdkAtom target);
gchar * gtk_clipboard_wait_for_text (GtkClipboard *clipboard);
+gboolean gtk_clipboard_wait_is_text_available (GtkClipboard *clipboard);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index 503cd42b45..d993ad1d88 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -3721,7 +3721,7 @@ popup_position_func (GtkMenu *menu,
entry = GTK_ENTRY (user_data);
widget = GTK_WIDGET (entry);
-
+
g_return_if_fail (GTK_WIDGET_REALIZED (entry));
gdk_window_get_origin (widget->window, x, y);
@@ -3735,65 +3735,109 @@ popup_position_func (GtkMenu *menu,
*y = CLAMP (*y, 0, MAX (0, gdk_screen_height () - req.height));
}
-static void
-gtk_entry_do_popup (GtkEntry *entry,
- GdkEventButton *event)
+typedef struct
{
+ GtkEntry *entry;
+ gint button;
+ guint time;
+} PopupInfo;
- GtkWidget *menuitem;
- GtkWidget *submenu;
- gboolean have_selection;
-
- if (entry->popup_menu)
- gtk_widget_destroy (entry->popup_menu);
+static void
+popup_targets_received (GtkClipboard *clipboard,
+ GtkSelectionData *data,
+ gpointer user_data)
+{
+ PopupInfo *info = user_data;
+ GtkEntry *entry = info->entry;
- entry->popup_menu = gtk_menu_new ();
-
- gtk_menu_attach_to_widget (GTK_MENU (entry->popup_menu),
- GTK_WIDGET (entry),
- popup_menu_detach);
-
- have_selection = entry->current_pos != entry->selection_bound;
+ if (GTK_WIDGET_REALIZED (entry))
+ {
+ gboolean clipboard_contains_text = gtk_selection_data_targets_include_text (data);
+ GtkWidget *menuitem;
+ GtkWidget *submenu;
+
+ if (entry->popup_menu)
+ gtk_widget_destroy (entry->popup_menu);
+
+ entry->popup_menu = gtk_menu_new ();
+
+ gtk_menu_attach_to_widget (GTK_MENU (entry->popup_menu),
+ GTK_WIDGET (entry),
+ popup_menu_detach);
+
+ append_action_signal (entry, entry->popup_menu, _("Cut"), "cut_clipboard",
+ entry->editable && entry->current_pos != entry->selection_bound);
+ append_action_signal (entry, entry->popup_menu, _("Copy"), "copy_clipboard",
+ entry->current_pos != entry->selection_bound);
+ append_action_signal (entry, entry->popup_menu, _("Paste"), "paste_clipboard",
+ entry->editable && clipboard_contains_text);
+
+ menuitem = gtk_menu_item_new_with_label (_("Select All"));
+ gtk_signal_connect_object (GTK_OBJECT (menuitem), "activate",
+ GTK_SIGNAL_FUNC (gtk_entry_select_all), entry);
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (entry->popup_menu), menuitem);
+
+ menuitem = gtk_separator_menu_item_new ();
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (entry->popup_menu), menuitem);
+
+ menuitem = gtk_menu_item_new_with_label (_("Input Methods"));
+ gtk_widget_show (menuitem);
+ submenu = gtk_menu_new ();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (entry->popup_menu), menuitem);
+
+ gtk_im_multicontext_append_menuitems (GTK_IM_MULTICONTEXT (entry->im_context),
+ GTK_MENU_SHELL (submenu));
+
+ gtk_signal_emit (GTK_OBJECT (entry),
+ signals[POPULATE_POPUP],
+ entry->popup_menu);
- append_action_signal (entry, entry->popup_menu, _("Cut"), "cut_clipboard",
- have_selection);
- append_action_signal (entry, entry->popup_menu, _("Copy"), "copy_clipboard",
- have_selection);
- append_action_signal (entry, entry->popup_menu, _("Paste"), "paste_clipboard",
- TRUE);
-
- menuitem = gtk_menu_item_new_with_label (_("Select All"));
- gtk_signal_connect_object (GTK_OBJECT (menuitem), "activate",
- GTK_SIGNAL_FUNC (gtk_entry_select_all), entry);
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (entry->popup_menu), menuitem);
- menuitem = gtk_separator_menu_item_new ();
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (entry->popup_menu), menuitem);
-
- menuitem = gtk_menu_item_new_with_label (_("Input Methods"));
- gtk_widget_show (menuitem);
- submenu = gtk_menu_new ();
- gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
+ if (info->button)
+ gtk_menu_popup (GTK_MENU (entry->popup_menu), NULL, NULL,
+ NULL, NULL,
+ info->button, info->time);
+ else
+ gtk_menu_popup (GTK_MENU (entry->popup_menu), NULL, NULL,
+ popup_position_func, entry,
+ info->button, info->time);
+ }
- gtk_menu_shell_append (GTK_MENU_SHELL (entry->popup_menu), menuitem);
-
- gtk_im_multicontext_append_menuitems (GTK_IM_MULTICONTEXT (entry->im_context),
- GTK_MENU_SHELL (submenu));
+ g_object_unref (entry);
+ g_free (info);
+}
+
+static void
+gtk_entry_do_popup (GtkEntry *entry,
+ GdkEventButton *event)
+{
+ PopupInfo *info = g_new (PopupInfo, 1);
- gtk_signal_emit (GTK_OBJECT (entry),
- signals[POPULATE_POPUP],
- entry->popup_menu);
+ /* In order to know what entries we should make sensitive, we
+ * ask for the current targets of the clipboard, and when
+ * we get them, then we actually pop up the menu.
+ */
+ info->entry = g_object_ref (entry);
if (event)
- gtk_menu_popup (GTK_MENU (entry->popup_menu), NULL, NULL,
- NULL, NULL,
- event->button, event->time);
+ {
+ info->button = event->button;
+ info->time = event->time;
+ }
else
- gtk_menu_popup (GTK_MENU (entry->popup_menu), NULL, NULL,
- popup_position_func, entry,
- 0, gtk_get_current_event_time ());
+ {
+ info->button = 0;
+ info->time = gtk_get_current_event_time ();
+ }
+
+ gtk_clipboard_request_contents (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
+ gdk_atom_intern ("TARGETS", FALSE),
+ popup_targets_received,
+ info);
}
static void
diff --git a/gtk/gtkselection.c b/gtk/gtkselection.c
index 5b7d391607..21bcb510be 100644
--- a/gtk/gtkselection.c
+++ b/gtk/gtkselection.c
@@ -866,6 +866,84 @@ gtk_selection_data_get_text (GtkSelectionData *selection_data)
return result;
}
+/**
+ * gtk_selection_data_get_targets:
+ * @selection_data: a #GtkSelectionData object
+ * @targets: location to store an array of targets. The result
+ * stored here must be freed with g_free().
+ * @n_atoms: location to store number of items in @targets.
+ *
+ * Get the contents of @selection_data as an array of targets.
+ * This can be used to interpret the results of getting
+ * the standard TARGETS target that is always supplied for
+ * any selection.
+ *
+ * Return value: %TRUE if @selection_data contains a valid
+ * array of targets, otherwise %FALSE.
+ **/
+gboolean
+gtk_selection_data_get_targets (GtkSelectionData *selection_data,
+ GdkAtom **targets,
+ gint *n_atoms)
+{
+ if (selection_data->length >= 0 &&
+ selection_data->format == 32 &&
+ selection_data->type == GDK_SELECTION_TYPE_ATOM)
+ {
+ if (targets)
+ *targets = g_memdup (selection_data->data, selection_data->length);
+ if (n_atoms)
+ *n_atoms = selection_data->length / sizeof (GdkAtom);
+
+ return TRUE;
+ }
+ else
+ {
+ if (targets)
+ *targets = NULL;
+ if (n_atoms)
+ *n_atoms = -1;
+
+ return FALSE;
+ }
+}
+
+/**
+ * gtk_selection_data_targets_include_text:
+ * @selection_data: a #GtkSelectionData object
+ *
+ * Given a #GtkSelectionData object holding a list of targets,
+ * Determines if any of the targets in @targets can be used to
+ * provide text.
+ *
+ * Return value: %TRUE if @selection_data holds a list of targets,
+ * and a suitable target for text is included, otherwise %FALSE.
+ **/
+gboolean
+gtk_selection_data_targets_include_text (GtkSelectionData *selection_data)
+{
+ GdkAtom *targets;
+ gint n_targets;
+ gint i;
+ gboolean result = FALSE;
+
+ if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
+ {
+ for (i=0; i < n_targets; i++)
+ {
+ if (targets[i] == gdk_atom_intern ("STRING", FALSE) ||
+ targets[i] == gdk_atom_intern ("TEXT", FALSE) ||
+ targets[i] == gdk_atom_intern ("COMPOUND_TEXT", FALSE) ||
+ targets[i] == gdk_atom_intern ("UTF8_STRING", FALSE))
+ result = TRUE;
+ }
+
+ g_free (targets);
+ }
+
+ return result;
+}
+
/*************************************************************
* gtk_selection_init:
* Initialize local variables
diff --git a/gtk/gtkselection.h b/gtk/gtkselection.h
index 04a4ff3c56..cf6b887a87 100644
--- a/gtk/gtkselection.h
+++ b/gtk/gtkselection.h
@@ -129,6 +129,11 @@ gboolean gtk_selection_data_set_text (GtkSelectionData *selection_data,
const guchar *str);
guchar * gtk_selection_data_get_text (GtkSelectionData *selection_data);
+gboolean gtk_selection_data_get_targets (GtkSelectionData *selection_data,
+ GdkAtom **targets,
+ gint *n_atoms);
+gboolean gtk_selection_data_targets_include_text (GtkSelectionData *selection_data);
+
/* Called when a widget is destroyed */
void gtk_selection_remove_all (GtkWidget *widget);
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index 1f7a8e4f90..a62681ef6a 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -5396,67 +5396,116 @@ popup_position_func (GtkMenu *menu,
*y = CLAMP (*y, 0, MAX (0, gdk_screen_height () - req.height));
}
-static void
-gtk_text_view_do_popup (GtkTextView *text_view,
- GdkEventButton *event)
+typedef struct
{
- GtkWidget *menuitem;
- GtkWidget *submenu;
- gboolean have_selection;
- gboolean can_insert;
- GtkTextIter iter;
-
- if (text_view->popup_menu)
- gtk_widget_destroy (text_view->popup_menu);
-
- text_view->popup_menu = gtk_menu_new ();
-
- gtk_menu_attach_to_widget (GTK_MENU (text_view->popup_menu),
- GTK_WIDGET (text_view),
- popup_menu_detach);
-
- have_selection = gtk_text_buffer_get_selection_bounds (get_buffer (text_view),
- NULL, NULL);
+ GtkTextView *text_view;
+ gint button;
+ guint time;
+} PopupInfo;
- gtk_text_buffer_get_iter_at_mark (get_buffer (text_view),
- &iter,
- gtk_text_buffer_get_insert (get_buffer (text_view)));
-
- can_insert = gtk_text_iter_can_insert (&iter, text_view->editable);
+static void
+popup_targets_received (GtkClipboard *clipboard,
+ GtkSelectionData *data,
+ gpointer user_data)
+{
+ PopupInfo *info = user_data;
+ GtkTextView *text_view = info->text_view;
- append_action_signal (text_view, text_view->popup_menu, _("Cut"), "cut_clipboard",
- have_selection);
- append_action_signal (text_view, text_view->popup_menu, _("Copy"), "copy_clipboard",
- have_selection);
+ if (GTK_WIDGET_REALIZED (text_view))
+ {
+ /* We implicitely rely here on the fact that if we are pasting ourself, we'll
+ * have text targets as well as the private GTK_TEXT_BUFFER_CONTENTS target.
+ */
+ gboolean clipboard_contains_text = gtk_selection_data_targets_include_text (data);
+ GtkWidget *menuitem;
+ GtkWidget *submenu;
+ gboolean have_selection;
+ gboolean can_insert;
+ GtkTextIter iter;
- append_action_signal (text_view, text_view->popup_menu, _("Paste"), "paste_clipboard",
- can_insert);
+ if (text_view->popup_menu)
+ gtk_widget_destroy (text_view->popup_menu);
- menuitem = gtk_separator_menu_item_new ();
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (text_view->popup_menu), menuitem);
+ text_view->popup_menu = gtk_menu_new ();
- menuitem = gtk_menu_item_new_with_label (_("Input Methods"));
- gtk_widget_show (menuitem);
- submenu = gtk_menu_new ();
- gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
- gtk_menu_shell_append (GTK_MENU_SHELL (text_view->popup_menu), menuitem);
+ gtk_menu_attach_to_widget (GTK_MENU (text_view->popup_menu),
+ GTK_WIDGET (text_view),
+ popup_menu_detach);
+
+ have_selection = gtk_text_buffer_get_selection_bounds (get_buffer (text_view),
+ NULL, NULL);
+
+ gtk_text_buffer_get_iter_at_mark (get_buffer (text_view),
+ &iter,
+ gtk_text_buffer_get_insert (get_buffer (text_view)));
+
+ can_insert = gtk_text_iter_can_insert (&iter, text_view->editable);
+
+ append_action_signal (text_view, text_view->popup_menu, _("Cut"), "cut_clipboard",
+ have_selection);
+ append_action_signal (text_view, text_view->popup_menu, _("Copy"), "copy_clipboard",
+ have_selection);
+ append_action_signal (text_view, text_view->popup_menu, _("Paste"), "paste_clipboard",
+ can_insert && clipboard_contains_text);
+
+ menuitem = gtk_separator_menu_item_new ();
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (text_view->popup_menu), menuitem);
+
+ menuitem = gtk_menu_item_new_with_label (_("Input Methods"));
+ gtk_widget_show (menuitem);
+ submenu = gtk_menu_new ();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
+ gtk_menu_shell_append (GTK_MENU_SHELL (text_view->popup_menu), menuitem);
+
+ gtk_im_multicontext_append_menuitems (GTK_IM_MULTICONTEXT (text_view->im_context),
+ GTK_MENU_SHELL (submenu));
+
+ gtk_signal_emit (GTK_OBJECT (text_view),
+ signals[POPULATE_POPUP],
+ text_view->popup_menu);
+
+ if (info->button)
+ gtk_menu_popup (GTK_MENU (text_view->popup_menu), NULL, NULL,
+ NULL, NULL,
+ info->button, info->time);
+ else
+ gtk_menu_popup (GTK_MENU (text_view->popup_menu), NULL, NULL,
+ popup_position_func, text_view,
+ 0, gtk_get_current_event_time ());
+ }
+
+ g_object_unref (text_view);
+ g_free (info);
+}
- gtk_im_multicontext_append_menuitems (GTK_IM_MULTICONTEXT (text_view->im_context),
- GTK_MENU_SHELL (submenu));
+static void
+gtk_text_view_do_popup (GtkTextView *text_view,
+ GdkEventButton *event)
+{
+ PopupInfo *info = g_new (PopupInfo, 1);
- gtk_signal_emit (GTK_OBJECT (text_view),
- signals[POPULATE_POPUP],
- text_view->popup_menu);
+ /* In order to know what entries we should make sensitive, we
+ * ask for the current targets of the clipboard, and when
+ * we get them, then we actually pop up the menu.
+ */
+ info->text_view = g_object_ref (text_view);
if (event)
- gtk_menu_popup (GTK_MENU (text_view->popup_menu), NULL, NULL,
- NULL, NULL,
- event->button, event->time);
+ {
+ info->button = event->button;
+ info->time = event->time;
+ }
else
- gtk_menu_popup (GTK_MENU (text_view->popup_menu), NULL, NULL,
- popup_position_func, text_view,
- 0, gtk_get_current_event_time ());
+ {
+ info->button = 0;
+ info->time = gtk_get_current_event_time ();
+ }
+
+ gtk_clipboard_request_contents (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
+ gdk_atom_intern ("TARGETS", FALSE),
+ popup_targets_received,
+ info);
}
static void