X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkentry.c;h=159120473c8a323d598478645894c51c5ee1e856;hb=6f1476edd3fbe31259e59ca3f03a01bf0f8ff67b;hp=40535d9f40e75404cd7ffcd2e126fdb56b50bdee;hpb=d38efb1713a5dc76c9f6d7019df044e32580dfcb;p=~andy%2Fgtk diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index 40535d9f4..159120473 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -66,6 +66,8 @@ #include "gtkwidgetprivate.h" #include "gtkstylecontextprivate.h" #include "gtktexthandleprivate.h" +#include "gtkbubblewindowprivate.h" +#include "gtktoolbar.h" #include "a11y/gtkentryaccessible.h" @@ -158,7 +160,10 @@ struct _GtkEntryPrivate gchar *placeholder_text; + GtkBubbleWindow *bubble_window; GtkTextHandle *text_handle; + GtkWidget *selection_bubble; + guint selection_bubble_timeout_id; gfloat xalign; @@ -218,6 +223,7 @@ struct _GtkEntryPrivate guint truncate_multiline : 1; guint cursor_handle_dragged : 1; guint selection_handle_dragged : 1; + guint populate_all : 1; }; struct _EntryIconInfo @@ -314,10 +320,12 @@ enum { PROP_COMPLETION, PROP_INPUT_PURPOSE, PROP_INPUT_HINTS, - PROP_ATTRIBUTES + PROP_ATTRIBUTES, + PROP_POPULATE_ALL }; static guint signals[LAST_SIGNAL] = { 0 }; +static gboolean test_touchscreen = FALSE; typedef enum { CURSOR_STANDARD, @@ -563,6 +571,11 @@ static void gtk_entry_get_text_area_size (GtkEntry *entry, gint *y, gint *width, gint *height); +static void gtk_entry_get_frame_size (GtkEntry *entry, + gint *x, + gint *y, + gint *width, + gint *height); static void get_text_area_size (GtkEntry *entry, gint *x, gint *y, @@ -586,6 +599,12 @@ static void gtk_entry_handle_dragged (GtkTextHandle *h gint x, gint y, GtkEntry *entry); +static void gtk_entry_handle_drag_finished (GtkTextHandle *handle, + GtkTextHandlePosition pos, + GtkEntry *entry); + +static void gtk_entry_selection_bubble_popup_set (GtkEntry *entry); +static void gtk_entry_selection_bubble_popup_unset (GtkEntry *entry); static void begin_change (GtkEntry *entry); static void end_change (GtkEntry *entry); @@ -704,6 +723,7 @@ gtk_entry_class_init (GtkEntryClass *class) class->toggle_overwrite = gtk_entry_toggle_overwrite; class->activate = gtk_entry_real_activate; class->get_text_area_size = gtk_entry_get_text_area_size; + class->get_frame_size = gtk_entry_get_frame_size; quark_inner_border = g_quark_from_static_string ("gtk-entry-inner-border"); quark_password_hint = g_quark_from_static_string ("gtk-entry-password-hint"); @@ -1405,6 +1425,21 @@ gtk_entry_class_init (GtkEntryClass *class) PANGO_TYPE_ATTR_LIST, GTK_PARAM_READWRITE)); + /** GtkEntry:populate-all: + * + * If ::populate-all is %TRUE, the #GtkEntry::populate-popup + * signal is also emitted for touch popups. + * + * Since: 3.8 + */ + g_object_class_install_property (gobject_class, + PROP_POPULATE_ALL, + g_param_spec_boolean ("populate-all", + P_("Populate all"), + P_("Whether to emit ::populate-popup for touch popups"), + FALSE, + GTK_PARAM_READWRITE)); + /** * GtkEntry:icon-prelight: * @@ -1463,13 +1498,20 @@ gtk_entry_class_init (GtkEntryClass *class) /** * GtkEntry::populate-popup: * @entry: The entry on which the signal is emitted - * @menu: the menu that is being populated + * @popup: the container that is being populated * - * The ::populate-popup signal gets emitted before showing the - * context menu of the entry. + * The ::populate-popup signal gets emitted before showing the + * context menu of the entry. * * If you need to add items to the context menu, connect - * to this signal and append your menuitems to the @menu. + * to this signal and append your items to the @widget, which + * will be a #GtkMenu in this case. + * + * If #GtkEntry::populate-all is %TRUE, this signal will + * also be emitted to populate touch popups. In this case, + * @widget will be a different container, e.g. a #GtkToolbar. + * The signal handler should not make assumptions about the + * type of @widget. */ signals[POPULATE_POPUP] = g_signal_new (I_("populate-popup"), @@ -1479,7 +1521,7 @@ gtk_entry_class_init (GtkEntryClass *class) NULL, NULL, _gtk_marshal_VOID__OBJECT, G_TYPE_NONE, 1, - GTK_TYPE_MENU); + GTK_TYPE_WIDGET); /* Action signals */ @@ -1938,6 +1980,7 @@ gtk_entry_class_init (GtkEntryClass *class) G_PARAM_DEPRECATED)); g_type_class_add_private (gobject_class, sizeof (GtkEntryPrivate)); + test_touchscreen = g_getenv ("GTK_TEST_TOUCHSCREEN") != NULL; gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ENTRY_ACCESSIBLE); } @@ -2220,6 +2263,10 @@ gtk_entry_set_property (GObject *object, gtk_entry_set_attributes (entry, g_value_get_boxed (value)); break; + case PROP_POPULATE_ALL: + entry->priv->populate_all = g_value_get_boolean (value); + break; + case PROP_SCROLL_OFFSET: case PROP_CURSOR_POSITION: default: @@ -2456,6 +2503,10 @@ gtk_entry_get_property (GObject *object, g_value_set_boxed (value, priv->attrs); break; + case PROP_POPULATE_ALL: + g_value_set_boolean (value, priv->populate_all); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2567,6 +2618,8 @@ gtk_entry_init (GtkEntry *entry) priv->text_handle = _gtk_text_handle_new (GTK_WIDGET (entry)); g_signal_connect (priv->text_handle, "handle-dragged", G_CALLBACK (gtk_entry_handle_dragged), entry); + g_signal_connect (priv->text_handle, "drag-finished", + G_CALLBACK (gtk_entry_handle_drag_finished), entry); } static void @@ -2803,6 +2856,9 @@ gtk_entry_finalize (GObject *object) if (priv->recompute_idle) g_source_remove (priv->recompute_idle); + if (priv->selection_bubble) + gtk_widget_destroy (priv->selection_bubble); + g_object_unref (priv->text_handle); g_free (priv->placeholder_text); g_free (priv->im_module); @@ -2965,7 +3021,7 @@ realize_icon_info (GtkWidget *widget, icon_info->window = gdk_window_new (gtk_widget_get_window (widget), &attributes, attributes_mask); - gdk_window_set_user_data (icon_info->window, widget); + gtk_widget_register_window (widget, icon_info->window); gtk_widget_queue_resize (widget); } @@ -3092,7 +3148,7 @@ gtk_entry_realize (GtkWidget *widget) &attributes, attributes_mask); - gdk_window_set_user_data (priv->text_area, entry); + gtk_widget_register_window (widget, priv->text_area); if (attributes_mask & GDK_WA_CURSOR) g_object_unref (attributes.cursor); @@ -3137,7 +3193,7 @@ gtk_entry_unrealize (GtkWidget *widget) if (priv->text_area) { - gdk_window_set_user_data (priv->text_area, NULL); + gtk_widget_unregister_window (widget, priv->text_area); gdk_window_destroy (priv->text_area); priv->text_area = NULL; } @@ -3156,6 +3212,7 @@ gtk_entry_unrealize (GtkWidget *widget) { if (icon_info->window != NULL) { + gtk_widget_unregister_window (widget, icon_info->window); gdk_window_destroy (icon_info->window); icon_info->window = NULL; } @@ -3208,19 +3265,14 @@ gtk_entry_get_preferred_width (GtkWidget *widget, PangoFontMetrics *metrics; GtkBorder borders; PangoContext *context; - GtkStyleContext *style_context; - GtkStateFlags state; gint icon_widths = 0; gint icon_width, i; gint width; context = gtk_widget_get_pango_context (widget); - style_context = gtk_widget_get_style_context (widget); - state = gtk_widget_get_state_flags (widget); - metrics = pango_context_get_metrics (context, - gtk_style_context_get_font (style_context, state), + pango_context_get_font_description (context), pango_context_get_language (context)); _gtk_entry_get_borders (entry, &borders); @@ -3261,28 +3313,25 @@ gtk_entry_get_preferred_height (GtkWidget *widget, GtkEntryPrivate *priv = entry->priv; PangoFontMetrics *metrics; GtkBorder borders; - GtkStyleContext *style_context; - GtkStateFlags state; PangoContext *context; gint height; + PangoLayout *layout; + layout = gtk_entry_ensure_layout (entry, TRUE); context = gtk_widget_get_pango_context (widget); - style_context = gtk_widget_get_style_context (widget); - state = gtk_widget_get_state_flags (widget); - metrics = pango_context_get_metrics (context, - gtk_style_context_get_font (style_context, state), + pango_context_get_font_description (context), pango_context_get_language (context)); priv->ascent = pango_font_metrics_get_ascent (metrics); priv->descent = pango_font_metrics_get_descent (metrics); + pango_font_metrics_unref (metrics); _gtk_entry_get_borders (entry, &borders); + pango_layout_get_pixel_size (layout, NULL, &height); - height = PANGO_PIXELS (priv->ascent + priv->descent) + borders.top + borders.bottom; - - pango_font_metrics_unref (metrics); + height += borders.top + borders.bottom; *minimum = height; *natural = height; @@ -3393,12 +3442,11 @@ get_text_area_size (GtkEntry *entry, static void -get_frame_size (GtkEntry *entry, - gboolean relative_to_window, - gint *x, - gint *y, - gint *width, - gint *height) +gtk_entry_get_frame_size (GtkEntry *entry, + gint *x, + gint *y, + gint *width, + gint *height) { GtkEntryPrivate *priv = entry->priv; GtkAllocation allocation; @@ -3413,7 +3461,7 @@ get_frame_size (GtkEntry *entry, gtk_widget_get_allocation (widget, &allocation); if (x) - *x = relative_to_window ? allocation.x : 0; + *x = allocation.x; if (y) { @@ -3422,8 +3470,7 @@ get_frame_size (GtkEntry *entry, else *y = (allocation.height - req_height) / 2; - if (relative_to_window) - *y += allocation.y; + *y += allocation.y; } if (width) @@ -3438,6 +3485,36 @@ get_frame_size (GtkEntry *entry, } } +static void +get_frame_size (GtkEntry *entry, + gboolean relative_to_window, + gint *x, + gint *y, + gint *width, + gint *height) +{ + GtkEntryClass *class; + GtkWidget *widget = GTK_WIDGET (entry); + + g_return_if_fail (GTK_IS_ENTRY (entry)); + + class = GTK_ENTRY_GET_CLASS (entry); + + if (class->get_frame_size) + class->get_frame_size (entry, x, y, width, height); + + if (!relative_to_window) + { + GtkAllocation allocation; + gtk_widget_get_allocation (widget, &allocation); + + if (x) + *x -= allocation.x; + if (y) + *y -= allocation.y; + } +} + static void gtk_entry_size_allocate (GtkWidget *widget, GtkAllocation *allocation) @@ -3715,36 +3792,40 @@ gtk_entry_draw (GtkWidget *widget, GtkEntryPrivate *priv = entry->priv; int i; - context = gtk_widget_get_style_context (widget); + if (gtk_cairo_should_draw_window (cr, + gtk_widget_get_window (widget))) + { + context = gtk_widget_get_style_context (widget); - /* Draw entry_bg, shadow, progress and focus */ - gtk_entry_draw_frame (widget, context, cr); + /* Draw entry_bg, shadow, progress and focus */ + gtk_entry_draw_frame (widget, context, cr); - /* Draw text and cursor */ - cairo_save (cr); + /* Draw text and cursor */ + cairo_save (cr); - gtk_cairo_transform_to_window (cr, widget, priv->text_area); + gtk_cairo_transform_to_window (cr, widget, priv->text_area); - if (priv->dnd_position != -1) - gtk_entry_draw_cursor (GTK_ENTRY (widget), cr, CURSOR_DND); - - gtk_entry_draw_text (GTK_ENTRY (widget), cr); + if (priv->dnd_position != -1) + gtk_entry_draw_cursor (GTK_ENTRY (widget), cr, CURSOR_DND); - /* When no text is being displayed at all, don't show the cursor */ - if (gtk_entry_get_display_mode (entry) != DISPLAY_BLANK && - gtk_widget_has_focus (widget) && - priv->selection_bound == priv->current_pos && priv->cursor_visible) - gtk_entry_draw_cursor (GTK_ENTRY (widget), cr, CURSOR_STANDARD); + gtk_entry_draw_text (GTK_ENTRY (widget), cr); - cairo_restore (cr); + /* When no text is being displayed at all, don't show the cursor */ + if (gtk_entry_get_display_mode (entry) != DISPLAY_BLANK && + gtk_widget_has_focus (widget) && + priv->selection_bound == priv->current_pos && priv->cursor_visible) + gtk_entry_draw_cursor (GTK_ENTRY (widget), cr, CURSOR_STANDARD); - /* Draw icons */ - for (i = 0; i < MAX_ICONS; i++) - { - EntryIconInfo *icon_info = priv->icons[i]; + cairo_restore (cr); - if (icon_info != NULL) - draw_icon (widget, cr, i); + /* Draw icons */ + for (i = 0; i < MAX_ICONS; i++) + { + EntryIconInfo *icon_info = priv->icons[i]; + + if (icon_info != NULL) + draw_icon (widget, cr, i); + } } return FALSE; @@ -3985,6 +4066,8 @@ gtk_entry_button_press (GtkWidget *widget, gint sel_start, sel_end; gint i; + gtk_entry_selection_bubble_popup_unset (entry); + for (i = 0; i < MAX_ICONS; i++) { icon_info = priv->icons[i]; @@ -4044,7 +4127,8 @@ gtk_entry_button_press (GtkWidget *widget, GdkDevice *source; source = gdk_event_get_source_device ((GdkEvent *) event); - is_touchscreen = gdk_device_get_source (source) == GDK_SOURCE_TOUCHSCREEN; + is_touchscreen = test_touchscreen || + gdk_device_get_source (source) == GDK_SOURCE_TOUCHSCREEN; priv->select_words = FALSE; priv->select_lines = FALSE; @@ -4188,6 +4272,8 @@ gtk_entry_button_release (GtkWidget *widget, GtkEntry *entry = GTK_ENTRY (widget); GtkEntryPrivate *priv = entry->priv; EntryIconInfo *icon_info = NULL; + gboolean is_touchscreen; + GdkDevice *source; gint i; for (i = 0; i < MAX_ICONS; i++) @@ -4220,20 +4306,23 @@ gtk_entry_button_release (GtkWidget *widget, if (event->window != priv->text_area || priv->button != event->button) return FALSE; + source = gdk_event_get_source_device ((GdkEvent *) event); + is_touchscreen = (test_touchscreen || + gdk_device_get_source (source) == GDK_SOURCE_TOUCHSCREEN); + if (priv->in_drag) { gint tmp_pos = gtk_entry_find_position (entry, priv->drag_start_x); - GdkDevice *source; gtk_editable_set_position (GTK_EDITABLE (entry), tmp_pos); - source = gdk_event_get_source_device ((GdkEvent *) event); - - if (gdk_device_get_source (source) == GDK_SOURCE_TOUCHSCREEN) + if (is_touchscreen) gtk_entry_update_handles (entry, GTK_TEXT_HANDLE_MODE_CURSOR); priv->in_drag = 0; } + else if (is_touchscreen) + gtk_entry_selection_bubble_popup_set (entry); priv->button = 0; priv->device = NULL; @@ -4411,7 +4500,7 @@ gtk_entry_motion_notify (GtkWidget *widget, gtk_entry_set_positions (entry, tmp_pos, -1); /* Update touch handles' position */ - if (input_source == GDK_SOURCE_TOUCHSCREEN) + if (test_touchscreen || input_source == GDK_SOURCE_TOUCHSCREEN) gtk_entry_update_handles (entry, (priv->current_pos == priv->selection_bound) ? GTK_TEXT_HANDLE_MODE_CURSOR : @@ -4457,8 +4546,12 @@ gtk_entry_key_press (GtkWidget *widget, gtk_entry_reset_blink_time (entry); gtk_entry_pend_cursor_blink (entry); - _gtk_text_handle_set_mode (priv->text_handle, - GTK_TEXT_HANDLE_MODE_NONE); + + gtk_entry_selection_bubble_popup_unset (entry); + + if (!event->send_event) + _gtk_text_handle_set_mode (priv->text_handle, + GTK_TEXT_HANDLE_MODE_NONE); if (priv->editable) { @@ -4553,6 +4646,7 @@ gtk_entry_focus_out (GtkWidget *widget, GtkEntryCompletion *completion; GdkKeymap *keymap; + gtk_entry_selection_bubble_popup_unset (entry); _gtk_text_handle_set_mode (priv->text_handle, GTK_TEXT_HANDLE_MODE_NONE); @@ -4835,8 +4929,6 @@ gtk_entry_style_updated (GtkWidget *widget) gtk_entry_update_cached_style_values (entry); - gtk_entry_recompute (entry); - icon_theme_changed (entry); } @@ -5464,6 +5556,8 @@ gtk_entry_cut_clipboard (GtkEntry *entry) { gtk_widget_error_bell (GTK_WIDGET (entry)); } + + gtk_entry_selection_bubble_popup_unset (entry); } static void @@ -5935,7 +6029,7 @@ get_layout_position (GtkEntry *entry, layout = gtk_entry_ensure_layout (entry, TRUE); - gtk_entry_get_text_area_size (entry, NULL, NULL, &area_width, &area_height); + get_text_area_size (entry, NULL, NULL, &area_width, &area_height); area_height = PANGO_SCALE * area_height; line = pango_layout_get_lines_readonly (layout)->data; @@ -6192,6 +6286,8 @@ gtk_entry_handle_dragged (GtkTextHandle *handle, GtkTextHandleMode mode; gint *min, *max; + gtk_entry_selection_bubble_popup_unset (entry); + cursor_pos = priv->current_pos; selection_bound_pos = priv->selection_bound; mode = _gtk_text_handle_get_mode (handle); @@ -6244,6 +6340,15 @@ gtk_entry_handle_dragged (GtkTextHandle *handle, } } +static void +gtk_entry_handle_drag_finished (GtkTextHandle *handle, + GtkTextHandlePosition pos, + GtkEntry *entry) +{ + gtk_entry_selection_bubble_popup_set (entry); +} + + /** * gtk_entry_reset_im_context: * @entry: a #GtkEntry @@ -6534,8 +6639,6 @@ gtk_entry_move_adjustments (GtkEntry *entry) GtkAdjustment *adjustment; PangoContext *context; PangoFontMetrics *metrics; - GtkStyleContext *style_context; - GtkStateFlags state; GtkBorder borders; gint x, layout_x; gint char_width; @@ -6554,11 +6657,9 @@ gtk_entry_move_adjustments (GtkEntry *entry) /* Approximate width of a char, so user can see what is ahead/behind */ context = gtk_widget_get_pango_context (widget); - style_context = gtk_widget_get_style_context (widget); - state = gtk_widget_get_state_flags (widget); metrics = pango_context_get_metrics (context, - gtk_style_context_get_font (style_context, state), + pango_context_get_font_description (context), pango_context_get_language (context)); char_width = pango_font_metrics_get_approximate_char_width (metrics) / PANGO_SCALE; @@ -8767,6 +8868,9 @@ gtk_entry_set_icon_tooltip_text (GtkEntry *entry, icon_info->tooltip = tooltip ? g_markup_escape_text (tooltip, -1) : NULL; ensure_has_tooltip (entry); + + g_object_notify (G_OBJECT (entry), + icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-tooltip-text" : "secondary-icon-tooltip-text"); } /** @@ -9185,6 +9289,151 @@ gtk_entry_popup_menu (GtkWidget *widget) return TRUE; } +static void +activate_bubble_cb (GtkWidget *item, + GtkEntry *entry) +{ + const gchar *signal = g_object_get_data (G_OBJECT (item), "gtk-signal"); + g_signal_emit_by_name (entry, signal); + _gtk_bubble_window_popdown (GTK_BUBBLE_WINDOW (entry->priv->selection_bubble)); +} + +static void +append_bubble_action (GtkEntry *entry, + GtkWidget *toolbar, + const gchar *stock_id, + const gchar *signal, + gboolean sensitive) +{ + GtkToolItem *item = gtk_tool_button_new_from_stock (stock_id); + g_object_set_data (G_OBJECT (item), I_("gtk-signal"), (char *)signal); + g_signal_connect (item, "clicked", G_CALLBACK (activate_bubble_cb), entry); + gtk_widget_set_sensitive (GTK_WIDGET (item), sensitive); + gtk_widget_show (GTK_WIDGET (item)); + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1); +} + +static void +bubble_targets_received (GtkClipboard *clipboard, + GtkSelectionData *data, + gpointer user_data) +{ + GtkEntry *entry = user_data; + GtkEntryPrivate *priv = entry->priv; + cairo_rectangle_int_t rect; + GtkAllocation allocation; + gint start_x, end_x; + gboolean has_selection; + gboolean has_clipboard; + DisplayMode mode; + GtkWidget *toolbar; + + has_selection = gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), + NULL, NULL); + if (!has_selection && !priv->editable) + { + priv->selection_bubble_timeout_id = 0; + return; + } + + if (priv->selection_bubble) + gtk_widget_destroy (priv->selection_bubble); + + priv->selection_bubble = _gtk_bubble_window_new (); + toolbar = GTK_WIDGET (gtk_toolbar_new ()); + gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_TEXT); + gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), FALSE); + gtk_widget_show (toolbar); + gtk_container_add (GTK_CONTAINER (priv->selection_bubble), toolbar); + + has_clipboard = gtk_selection_data_targets_include_text (data); + mode = gtk_entry_get_display_mode (entry); + + append_bubble_action (entry, toolbar, GTK_STOCK_CUT, "cut-clipboard", + priv->editable && has_selection && mode == DISPLAY_NORMAL); + + append_bubble_action (entry, toolbar, GTK_STOCK_COPY, "copy-clipboard", + has_selection && mode == DISPLAY_NORMAL); + + append_bubble_action (entry, toolbar, GTK_STOCK_PASTE, "paste-clipboard", + priv->editable && has_clipboard); + + if (priv->populate_all) + g_signal_emit (entry, signals[POPULATE_POPUP], 0, toolbar); + + gtk_widget_get_allocation (GTK_WIDGET (entry), &allocation); + + gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &start_x, NULL); + + start_x -= priv->scroll_offset; + start_x = CLAMP (start_x, 0, gdk_window_get_width (priv->text_area)); + + rect.y = 0; + rect.height = gdk_window_get_height (priv->text_area); + + if (has_selection) + { + end_x = gtk_entry_get_selection_bound_location (entry) - priv->scroll_offset; + end_x = CLAMP (end_x, 0, gdk_window_get_width (priv->text_area)); + + rect.x = MIN (start_x, end_x); + rect.width = MAX (start_x, end_x) - rect.x; + } + else + { + rect.x = start_x; + rect.width = 0; + } + + _gtk_bubble_window_popup (GTK_BUBBLE_WINDOW (priv->selection_bubble), + priv->text_area, &rect, GTK_POS_TOP); + + priv->selection_bubble_timeout_id = 0; +} + +static gboolean +gtk_entry_selection_bubble_popup_cb (gpointer user_data) +{ + GtkEntry *entry = user_data; + + gtk_clipboard_request_contents (gtk_widget_get_clipboard (GTK_WIDGET (entry), GDK_SELECTION_CLIPBOARD), + gdk_atom_intern_static_string ("TARGETS"), + bubble_targets_received, + entry); + return G_SOURCE_REMOVE; +} + +static void +gtk_entry_selection_bubble_popup_unset (GtkEntry *entry) +{ + GtkEntryPrivate *priv; + + priv = entry->priv; + + if (priv->selection_bubble) + _gtk_bubble_window_popdown (GTK_BUBBLE_WINDOW (priv->selection_bubble)); + + if (priv->selection_bubble_timeout_id) + { + g_source_remove (priv->selection_bubble_timeout_id); + priv->selection_bubble_timeout_id = 0; + } +} + +static void +gtk_entry_selection_bubble_popup_set (GtkEntry *entry) +{ + GtkEntryPrivate *priv; + + priv = entry->priv; + + if (priv->selection_bubble_timeout_id) + g_source_remove (priv->selection_bubble_timeout_id); + + priv->selection_bubble_timeout_id = + gdk_threads_add_timeout (1000, gtk_entry_selection_bubble_popup_cb, entry); +} + static void gtk_entry_drag_begin (GtkWidget *widget, GdkDragContext *context)