diff options
author | Owen Taylor <otaylor@redhat.com> | 2001-10-22 20:47:01 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2001-10-22 20:47:01 +0000 |
commit | 92d2dc0ba639efbc360a3de34d4a2ae722afa098 (patch) | |
tree | 07727da269ec0f3ecac5f8e6973354999342fdcc | |
parent | 8fe966936c5b855b27aca8e9b2d07839d14662a4 (diff) | |
download | gtk+-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-- | ChangeLog | 18 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 18 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 18 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 18 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 18 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 18 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 18 | ||||
-rw-r--r-- | gtk/gtkclipboard.c | 32 | ||||
-rw-r--r-- | gtk/gtkclipboard.h | 28 | ||||
-rw-r--r-- | gtk/gtkentry.c | 144 | ||||
-rw-r--r-- | gtk/gtkselection.c | 78 | ||||
-rw-r--r-- | gtk/gtkselection.h | 5 | ||||
-rw-r--r-- | gtk/gtktextview.c | 149 |
13 files changed, 449 insertions, 113 deletions
@@ -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 |