Commit 92d2dc0b authored by Owen Taylor's avatar Owen Taylor Committed by Owen Taylor

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)
parent 8fe96693
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
......
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
......
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
......
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
......
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
......
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
......
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
......
......@@ -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;
}
......@@ -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 */
......
......@@ -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
......
......@@ -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
......
......@@ -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);
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment