1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* GTK - The GIMP Toolkit
3 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * Copyright (C) 2004-2006 Christian Hammond
5 * Copyright (C) 2008 Cody Russell
6 * Copyright (C) 2008 Red Hat, Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
23 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
24 * file for a list of people on the GTK+ Team. See the ChangeLog
25 * files for a list of changes. These files are distributed with
26 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
34 #include "gtkbindings.h"
35 #include "gtkcelleditable.h"
36 #include "gtkclipboard.h"
39 #include "gtkentrybuffer.h"
40 #include "gtkiconhelperprivate.h"
41 #include "gtkimagemenuitem.h"
42 #include "gtkimcontextsimple.h"
43 #include "gtkimmulticontext.h"
47 #include "gtkmarshalers.h"
49 #include "gtkmenuitem.h"
50 #include "gtkseparatormenuitem.h"
51 #include "gtkselection.h"
52 #include "gtksettings.h"
53 #include "gtkspinbutton.h"
55 #include "gtktextutil.h"
56 #include "gtkwindow.h"
57 #include "gtktreeview.h"
58 #include "gtktreeselection.h"
59 #include "gtktypebuiltins.h"
60 #include "gtkprivate.h"
61 #include "gtkentryprivate.h"
62 #include "gtkcelllayout.h"
63 #include "gtktooltip.h"
64 #include "gtkiconfactory.h"
65 #include "gtkicontheme.h"
66 #include "gtkwidgetprivate.h"
67 #include "gtkstylecontextprivate.h"
68 #include "gtktexthandleprivate.h"
69 #include "gtkbubblewindowprivate.h"
70 #include "gtktoolbar.h"
72 #include "a11y/gtkentryaccessible.h"
76 * @Short_description: A single line text entry field
78 * @See_also: #GtkTextView, #GtkEntryCompletion
80 * The #GtkEntry widget is a single line text entry
81 * widget. A fairly large set of key bindings are supported
82 * by default. If the entered text is longer than the allocation
83 * of the widget, the widget will scroll so that the cursor
84 * position is visible.
86 * When using an entry for passwords and other sensitive information,
87 * it can be put into "password mode" using gtk_entry_set_visibility().
88 * In this mode, entered text is displayed using a 'invisible' character.
89 * By default, GTK+ picks the best invisible character that is available
90 * in the current font, but it can be changed with
91 * gtk_entry_set_invisible_char(). Since 2.16, GTK+ displays a warning
92 * when Caps Lock or input methods might interfere with entering text in
93 * a password entry. The warning can be turned off with the
94 * #GtkEntry:caps-lock-warning property.
96 * Since 2.16, GtkEntry has the ability to display progress or activity
97 * information behind the text. To make an entry display such information,
98 * use gtk_entry_set_progress_fraction() or gtk_entry_set_progress_pulse_step().
100 * Additionally, GtkEntry can show icons at either side of the entry. These
101 * icons can be activatable by clicking, can be set up as drag source and
102 * can have tooltips. To add an icon, use gtk_entry_set_icon_from_gicon() or
103 * one of the various other functions that set an icon from a stock id, an
104 * icon name or a pixbuf. To trigger an action when the user clicks an icon,
105 * connect to the #GtkEntry::icon-press signal. To allow DND operations
106 * from an icon, use gtk_entry_set_icon_drag_source(). To set a tooltip on
107 * an icon, use gtk_entry_set_icon_tooltip_text() or the corresponding function
110 * Note that functionality or information that is only available by clicking
111 * on an icon in an entry may not be accessible at all to users which are not
112 * able to use a mouse or other pointing device. It is therefore recommended
113 * that any such functionality should also be available by other means, e.g.
114 * via the context menu of the entry.
118 #define GTK_ENTRY_COMPLETION_KEY "gtk-entry-completion-key"
120 #define MIN_ENTRY_WIDTH 150
121 #define DRAW_TIMEOUT 20
122 #define PASSWORD_HINT_MAX 8
126 #define IS_VALID_ICON_POSITION(pos) \
127 ((pos) == GTK_ENTRY_ICON_PRIMARY || \
128 (pos) == GTK_ENTRY_ICON_SECONDARY)
130 static const GtkBorder default_inner_border = { 2, 2, 2, 2 };
131 static GQuark quark_inner_border = 0;
132 static GQuark quark_password_hint = 0;
133 static GQuark quark_cursor_hadjustment = 0;
134 static GQuark quark_capslock_feedback = 0;
136 typedef struct _EntryIconInfo EntryIconInfo;
137 typedef struct _GtkEntryPasswordHint GtkEntryPasswordHint;
138 typedef struct _GtkEntryCapslockFeedback GtkEntryCapslockFeedback;
140 struct _GtkEntryPrivate
142 EntryIconInfo *icons[MAX_ICONS];
144 GtkEntryBuffer *buffer;
145 GtkIMContext *im_context;
146 GtkWidget *popup_menu;
150 GdkWindow *text_area;
152 PangoLayout *cached_layout;
153 PangoAttrList *attrs;
157 gdouble progress_fraction;
158 gdouble progress_pulse_fraction;
159 gdouble progress_pulse_current;
161 gchar *placeholder_text;
163 GtkBubbleWindow *bubble_window;
164 GtkTextHandle *text_handle;
165 GtkWidget *selection_bubble;
166 guint selection_bubble_timeout_id;
170 gint ascent; /* font ascent in pango units */
172 gint descent; /* font descent in pango units */
173 gint dnd_position; /* In chars, -1 == no DND cursor */
178 gint selection_bound;
184 gunichar invisible_char;
187 guint blink_time; /* time in msec the cursor has blinked since last user event */
189 guint recompute_idle;
191 guint16 x_text_size; /* allocated size, in bytes */
192 guint16 x_n_bytes; /* length in use, in bytes */
194 guint16 preedit_length; /* length of preedit string, in bytes */
195 guint16 preedit_cursor; /* offset of cursor within preedit string, in chars */
197 guint shadow_type : 4;
200 guint overwrite_mode : 1;
203 guint activates_default : 1;
204 guint cache_includes_preedit : 1;
205 guint caps_lock_warning : 1;
206 guint caps_lock_warning_shown : 1;
207 guint change_count : 8;
208 guint cursor_visible : 1;
209 guint editing_canceled : 1; /* Only used by GtkCellRendererText */
211 guint in_click : 1; /* Flag so we don't select all when clicking in entry to focus in */
212 guint is_cell_renderer : 1;
213 guint invisible_char_set : 1;
214 guint interior_focus : 1;
215 guint mouse_cursor_obscured : 1;
216 guint need_im_reset : 1;
217 guint progress_pulse_mode : 1;
218 guint progress_pulse_way_back : 1;
219 guint real_changed : 1;
220 guint resolved_dir : 4; /* PangoDirection */
221 guint select_words : 1;
222 guint select_lines : 1;
223 guint truncate_multiline : 1;
224 guint cursor_handle_dragged : 1;
225 guint selection_handle_dragged : 1;
226 guint populate_toolbar : 1;
229 struct _EntryIconInfo
233 guint insensitive : 1;
234 guint nonactivatable : 1;
239 GtkIconHelper *icon_helper;
241 GtkTargetList *target_list;
242 GdkDragAction actions;
245 struct _GtkEntryPasswordHint
247 gint position; /* Position (in text) of the last password hint */
248 guint source_id; /* Timeout source id */
251 struct _GtkEntryCapslockFeedback
278 PROP_CURSOR_POSITION,
279 PROP_SELECTION_BOUND,
286 PROP_ACTIVATES_DEFAULT,
291 PROP_TRUNCATE_MULTILINE,
295 PROP_INVISIBLE_CHAR_SET,
296 PROP_CAPS_LOCK_WARNING,
297 PROP_PROGRESS_FRACTION,
298 PROP_PROGRESS_PULSE_STEP,
300 PROP_PIXBUF_SECONDARY,
302 PROP_STOCK_SECONDARY,
303 PROP_ICON_NAME_PRIMARY,
304 PROP_ICON_NAME_SECONDARY,
306 PROP_GICON_SECONDARY,
307 PROP_STORAGE_TYPE_PRIMARY,
308 PROP_STORAGE_TYPE_SECONDARY,
309 PROP_ACTIVATABLE_PRIMARY,
310 PROP_ACTIVATABLE_SECONDARY,
311 PROP_SENSITIVE_PRIMARY,
312 PROP_SENSITIVE_SECONDARY,
313 PROP_TOOLTIP_TEXT_PRIMARY,
314 PROP_TOOLTIP_TEXT_SECONDARY,
315 PROP_TOOLTIP_MARKUP_PRIMARY,
316 PROP_TOOLTIP_MARKUP_SECONDARY,
318 PROP_EDITING_CANCELED,
319 PROP_PLACEHOLDER_TEXT,
324 PROP_POPULATE_TOOLBAR
327 static guint signals[LAST_SIGNAL] = { 0 };
328 static gboolean test_touchscreen = FALSE;
337 DISPLAY_NORMAL, /* The entry text is being shown */
338 DISPLAY_INVISIBLE, /* In invisible mode, text replaced by (eg) bullets */
339 DISPLAY_BLANK /* In invisible mode, nothing shown at all */
344 static void gtk_entry_editable_init (GtkEditableInterface *iface);
345 static void gtk_entry_cell_editable_init (GtkCellEditableIface *iface);
346 static void gtk_entry_set_property (GObject *object,
350 static void gtk_entry_get_property (GObject *object,
354 static void gtk_entry_finalize (GObject *object);
355 static void gtk_entry_dispose (GObject *object);
359 static void gtk_entry_destroy (GtkWidget *widget);
360 static void gtk_entry_realize (GtkWidget *widget);
361 static void gtk_entry_unrealize (GtkWidget *widget);
362 static void gtk_entry_map (GtkWidget *widget);
363 static void gtk_entry_unmap (GtkWidget *widget);
364 static void gtk_entry_get_preferred_width (GtkWidget *widget,
367 static void gtk_entry_get_preferred_height (GtkWidget *widget,
370 static void gtk_entry_size_allocate (GtkWidget *widget,
371 GtkAllocation *allocation);
372 static void gtk_entry_draw_frame (GtkWidget *widget,
373 GtkStyleContext *context,
375 static void gtk_entry_draw_progress (GtkWidget *widget,
376 GtkStyleContext *context,
378 static gint gtk_entry_draw (GtkWidget *widget,
380 static gint gtk_entry_button_press (GtkWidget *widget,
381 GdkEventButton *event);
382 static gint gtk_entry_button_release (GtkWidget *widget,
383 GdkEventButton *event);
384 static gint gtk_entry_enter_notify (GtkWidget *widget,
385 GdkEventCrossing *event);
386 static gint gtk_entry_leave_notify (GtkWidget *widget,
387 GdkEventCrossing *event);
388 static gint gtk_entry_motion_notify (GtkWidget *widget,
389 GdkEventMotion *event);
390 static gint gtk_entry_key_press (GtkWidget *widget,
392 static gint gtk_entry_key_release (GtkWidget *widget,
394 static gint gtk_entry_focus_in (GtkWidget *widget,
395 GdkEventFocus *event);
396 static gint gtk_entry_focus_out (GtkWidget *widget,
397 GdkEventFocus *event);
398 static void gtk_entry_grab_focus (GtkWidget *widget);
399 static void gtk_entry_style_updated (GtkWidget *widget);
400 static gboolean gtk_entry_query_tooltip (GtkWidget *widget,
403 gboolean keyboard_tip,
404 GtkTooltip *tooltip);
405 static void gtk_entry_direction_changed (GtkWidget *widget,
406 GtkTextDirection previous_dir);
407 static void gtk_entry_state_flags_changed (GtkWidget *widget,
408 GtkStateFlags previous_state);
409 static void gtk_entry_screen_changed (GtkWidget *widget,
410 GdkScreen *old_screen);
412 static gboolean gtk_entry_drag_drop (GtkWidget *widget,
413 GdkDragContext *context,
417 static gboolean gtk_entry_drag_motion (GtkWidget *widget,
418 GdkDragContext *context,
422 static void gtk_entry_drag_leave (GtkWidget *widget,
423 GdkDragContext *context,
425 static void gtk_entry_drag_data_received (GtkWidget *widget,
426 GdkDragContext *context,
429 GtkSelectionData *selection_data,
432 static void gtk_entry_drag_data_get (GtkWidget *widget,
433 GdkDragContext *context,
434 GtkSelectionData *selection_data,
437 static void gtk_entry_drag_data_delete (GtkWidget *widget,
438 GdkDragContext *context);
439 static void gtk_entry_drag_begin (GtkWidget *widget,
440 GdkDragContext *context);
441 static void gtk_entry_drag_end (GtkWidget *widget,
442 GdkDragContext *context);
445 /* GtkEditable method implementations
447 static void gtk_entry_insert_text (GtkEditable *editable,
448 const gchar *new_text,
449 gint new_text_length,
451 static void gtk_entry_delete_text (GtkEditable *editable,
454 static gchar * gtk_entry_get_chars (GtkEditable *editable,
457 static void gtk_entry_real_set_position (GtkEditable *editable,
459 static gint gtk_entry_get_position (GtkEditable *editable);
460 static void gtk_entry_set_selection_bounds (GtkEditable *editable,
463 static gboolean gtk_entry_get_selection_bounds (GtkEditable *editable,
467 /* GtkCellEditable method implementations
469 static void gtk_entry_start_editing (GtkCellEditable *cell_editable,
472 /* Default signal handlers
474 static void gtk_entry_real_insert_text (GtkEditable *editable,
475 const gchar *new_text,
476 gint new_text_length,
478 static void gtk_entry_real_delete_text (GtkEditable *editable,
481 static void gtk_entry_move_cursor (GtkEntry *entry,
482 GtkMovementStep step,
484 gboolean extend_selection);
485 static void gtk_entry_insert_at_cursor (GtkEntry *entry,
487 static void gtk_entry_delete_from_cursor (GtkEntry *entry,
490 static void gtk_entry_backspace (GtkEntry *entry);
491 static void gtk_entry_cut_clipboard (GtkEntry *entry);
492 static void gtk_entry_copy_clipboard (GtkEntry *entry);
493 static void gtk_entry_paste_clipboard (GtkEntry *entry);
494 static void gtk_entry_toggle_overwrite (GtkEntry *entry);
495 static void gtk_entry_select_all (GtkEntry *entry);
496 static void gtk_entry_real_activate (GtkEntry *entry);
497 static gboolean gtk_entry_popup_menu (GtkWidget *widget);
499 static void keymap_direction_changed (GdkKeymap *keymap,
501 static void keymap_state_changed (GdkKeymap *keymap,
503 static void remove_capslock_feedback (GtkEntry *entry);
505 /* IM Context Callbacks
507 static void gtk_entry_commit_cb (GtkIMContext *context,
510 static void gtk_entry_preedit_changed_cb (GtkIMContext *context,
512 static gboolean gtk_entry_retrieve_surrounding_cb (GtkIMContext *context,
514 static gboolean gtk_entry_delete_surrounding_cb (GtkIMContext *context,
521 static void gtk_entry_enter_text (GtkEntry *entry,
523 static void gtk_entry_set_positions (GtkEntry *entry,
525 gint selection_bound);
526 static void gtk_entry_draw_text (GtkEntry *entry,
528 static void gtk_entry_draw_cursor (GtkEntry *entry,
531 static PangoLayout *gtk_entry_ensure_layout (GtkEntry *entry,
532 gboolean include_preedit);
533 static void gtk_entry_reset_layout (GtkEntry *entry);
534 static void gtk_entry_recompute (GtkEntry *entry);
535 static gint gtk_entry_find_position (GtkEntry *entry,
537 static void gtk_entry_get_cursor_locations (GtkEntry *entry,
541 static void gtk_entry_adjust_scroll (GtkEntry *entry);
542 static gint gtk_entry_move_visually (GtkEntry *editable,
545 static gint gtk_entry_move_logically (GtkEntry *entry,
548 static gint gtk_entry_move_forward_word (GtkEntry *entry,
550 gboolean allow_whitespace);
551 static gint gtk_entry_move_backward_word (GtkEntry *entry,
553 gboolean allow_whitespace);
554 static void gtk_entry_delete_whitespace (GtkEntry *entry);
555 static void gtk_entry_select_word (GtkEntry *entry);
556 static void gtk_entry_select_line (GtkEntry *entry);
557 static void gtk_entry_paste (GtkEntry *entry,
559 static void gtk_entry_update_primary_selection (GtkEntry *entry);
560 static void gtk_entry_do_popup (GtkEntry *entry,
561 GdkEventButton *event);
562 static gboolean gtk_entry_mnemonic_activate (GtkWidget *widget,
563 gboolean group_cycling);
564 static void gtk_entry_grab_notify (GtkWidget *widget,
565 gboolean was_grabbed);
566 static void gtk_entry_check_cursor_blink (GtkEntry *entry);
567 static void gtk_entry_pend_cursor_blink (GtkEntry *entry);
568 static void gtk_entry_reset_blink_time (GtkEntry *entry);
569 static void gtk_entry_get_text_area_size (GtkEntry *entry,
574 static void gtk_entry_get_frame_size (GtkEntry *entry,
579 static void get_text_area_size (GtkEntry *entry,
584 static void get_frame_size (GtkEntry *entry,
585 gboolean relative_to_window,
590 static void gtk_entry_move_adjustments (GtkEntry *entry);
591 static GdkPixbuf * gtk_entry_ensure_pixbuf (GtkEntry *entry,
592 GtkEntryIconPosition icon_pos);
593 static void gtk_entry_update_cached_style_values(GtkEntry *entry);
594 static gboolean get_middle_click_paste (GtkEntry *entry);
596 /* GtkTextHandle handlers */
597 static void gtk_entry_handle_dragged (GtkTextHandle *handle,
598 GtkTextHandlePosition pos,
602 static void gtk_entry_handle_drag_finished (GtkTextHandle *handle,
603 GtkTextHandlePosition pos,
606 static void gtk_entry_selection_bubble_popup_set (GtkEntry *entry);
607 static void gtk_entry_selection_bubble_popup_unset (GtkEntry *entry);
609 static void begin_change (GtkEntry *entry);
610 static void end_change (GtkEntry *entry);
611 static void emit_changed (GtkEntry *entry);
613 static void buffer_inserted_text (GtkEntryBuffer *buffer,
618 static void buffer_deleted_text (GtkEntryBuffer *buffer,
622 static void buffer_notify_text (GtkEntryBuffer *buffer,
625 static void buffer_notify_length (GtkEntryBuffer *buffer,
628 static void buffer_notify_max_length (GtkEntryBuffer *buffer,
631 static void buffer_connect_signals (GtkEntry *entry);
632 static void buffer_disconnect_signals (GtkEntry *entry);
633 static GtkEntryBuffer *get_buffer (GtkEntry *entry);
635 G_DEFINE_TYPE_WITH_CODE (GtkEntry, gtk_entry, GTK_TYPE_WIDGET,
636 G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
637 gtk_entry_editable_init)
638 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_EDITABLE,
639 gtk_entry_cell_editable_init))
642 add_move_binding (GtkBindingSet *binding_set,
645 GtkMovementStep step,
648 g_return_if_fail ((modmask & GDK_SHIFT_MASK) == 0);
650 gtk_binding_entry_add_signal (binding_set, keyval, modmask,
654 G_TYPE_BOOLEAN, FALSE);
656 /* Selection-extending version */
657 gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
661 G_TYPE_BOOLEAN, TRUE);
665 gtk_entry_class_init (GtkEntryClass *class)
667 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
668 GtkWidgetClass *widget_class;
669 GtkBindingSet *binding_set;
671 widget_class = (GtkWidgetClass*) class;
673 gobject_class->dispose = gtk_entry_dispose;
674 gobject_class->finalize = gtk_entry_finalize;
675 gobject_class->set_property = gtk_entry_set_property;
676 gobject_class->get_property = gtk_entry_get_property;
678 widget_class->destroy = gtk_entry_destroy;
679 widget_class->map = gtk_entry_map;
680 widget_class->unmap = gtk_entry_unmap;
681 widget_class->realize = gtk_entry_realize;
682 widget_class->unrealize = gtk_entry_unrealize;
683 widget_class->get_preferred_width = gtk_entry_get_preferred_width;
684 widget_class->get_preferred_height = gtk_entry_get_preferred_height;
685 widget_class->size_allocate = gtk_entry_size_allocate;
686 widget_class->draw = gtk_entry_draw;
687 widget_class->enter_notify_event = gtk_entry_enter_notify;
688 widget_class->leave_notify_event = gtk_entry_leave_notify;
689 widget_class->button_press_event = gtk_entry_button_press;
690 widget_class->button_release_event = gtk_entry_button_release;
691 widget_class->motion_notify_event = gtk_entry_motion_notify;
692 widget_class->key_press_event = gtk_entry_key_press;
693 widget_class->key_release_event = gtk_entry_key_release;
694 widget_class->focus_in_event = gtk_entry_focus_in;
695 widget_class->focus_out_event = gtk_entry_focus_out;
696 widget_class->grab_focus = gtk_entry_grab_focus;
697 widget_class->style_updated = gtk_entry_style_updated;
698 widget_class->query_tooltip = gtk_entry_query_tooltip;
699 widget_class->drag_begin = gtk_entry_drag_begin;
700 widget_class->drag_end = gtk_entry_drag_end;
701 widget_class->direction_changed = gtk_entry_direction_changed;
702 widget_class->state_flags_changed = gtk_entry_state_flags_changed;
703 widget_class->screen_changed = gtk_entry_screen_changed;
704 widget_class->mnemonic_activate = gtk_entry_mnemonic_activate;
705 widget_class->grab_notify = gtk_entry_grab_notify;
707 widget_class->drag_drop = gtk_entry_drag_drop;
708 widget_class->drag_motion = gtk_entry_drag_motion;
709 widget_class->drag_leave = gtk_entry_drag_leave;
710 widget_class->drag_data_received = gtk_entry_drag_data_received;
711 widget_class->drag_data_get = gtk_entry_drag_data_get;
712 widget_class->drag_data_delete = gtk_entry_drag_data_delete;
714 widget_class->popup_menu = gtk_entry_popup_menu;
716 class->move_cursor = gtk_entry_move_cursor;
717 class->insert_at_cursor = gtk_entry_insert_at_cursor;
718 class->delete_from_cursor = gtk_entry_delete_from_cursor;
719 class->backspace = gtk_entry_backspace;
720 class->cut_clipboard = gtk_entry_cut_clipboard;
721 class->copy_clipboard = gtk_entry_copy_clipboard;
722 class->paste_clipboard = gtk_entry_paste_clipboard;
723 class->toggle_overwrite = gtk_entry_toggle_overwrite;
724 class->activate = gtk_entry_real_activate;
725 class->get_text_area_size = gtk_entry_get_text_area_size;
726 class->get_frame_size = gtk_entry_get_frame_size;
728 quark_inner_border = g_quark_from_static_string ("gtk-entry-inner-border");
729 quark_password_hint = g_quark_from_static_string ("gtk-entry-password-hint");
730 quark_cursor_hadjustment = g_quark_from_static_string ("gtk-hadjustment");
731 quark_capslock_feedback = g_quark_from_static_string ("gtk-entry-capslock-feedback");
733 g_object_class_override_property (gobject_class,
734 PROP_EDITING_CANCELED,
737 g_object_class_install_property (gobject_class,
739 g_param_spec_object ("buffer",
741 P_("Text buffer object which actually stores entry text"),
742 GTK_TYPE_ENTRY_BUFFER,
743 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
745 g_object_class_install_property (gobject_class,
746 PROP_CURSOR_POSITION,
747 g_param_spec_int ("cursor-position",
748 P_("Cursor Position"),
749 P_("The current position of the insertion cursor in chars"),
751 GTK_ENTRY_BUFFER_MAX_SIZE,
753 GTK_PARAM_READABLE));
755 g_object_class_install_property (gobject_class,
756 PROP_SELECTION_BOUND,
757 g_param_spec_int ("selection-bound",
758 P_("Selection Bound"),
759 P_("The position of the opposite end of the selection from the cursor in chars"),
761 GTK_ENTRY_BUFFER_MAX_SIZE,
763 GTK_PARAM_READABLE));
765 g_object_class_install_property (gobject_class,
767 g_param_spec_boolean ("editable",
769 P_("Whether the entry contents can be edited"),
771 GTK_PARAM_READWRITE));
773 g_object_class_install_property (gobject_class,
775 g_param_spec_int ("max-length",
776 P_("Maximum length"),
777 P_("Maximum number of characters for this entry. Zero if no maximum"),
779 GTK_ENTRY_BUFFER_MAX_SIZE,
781 GTK_PARAM_READWRITE));
782 g_object_class_install_property (gobject_class,
784 g_param_spec_boolean ("visibility",
786 P_("FALSE displays the \"invisible char\" instead of the actual text (password mode)"),
788 GTK_PARAM_READWRITE));
790 g_object_class_install_property (gobject_class,
792 g_param_spec_boolean ("has-frame",
794 P_("FALSE removes outside bevel from entry"),
796 GTK_PARAM_READWRITE));
799 * GtkEntry:inner-border:
801 * Sets the text area's border between the text and the frame.
803 * Deprecated: 3.4: Use the standard border and padding CSS properties
804 * (through objects like #GtkStyleContext and #GtkCssProvider); the value
805 * of this style property is ignored.
807 g_object_class_install_property (gobject_class,
809 g_param_spec_boxed ("inner-border",
811 P_("Border between text and frame. Overrides the inner-border style property"),
813 GTK_PARAM_READWRITE |
814 G_PARAM_DEPRECATED));
816 g_object_class_install_property (gobject_class,
818 g_param_spec_unichar ("invisible-char",
819 P_("Invisible character"),
820 P_("The character to use when masking entry contents (in \"password mode\")"),
822 GTK_PARAM_READWRITE));
824 g_object_class_install_property (gobject_class,
825 PROP_ACTIVATES_DEFAULT,
826 g_param_spec_boolean ("activates-default",
827 P_("Activates default"),
828 P_("Whether to activate the default widget (such as the default button in a dialog) when Enter is pressed"),
830 GTK_PARAM_READWRITE));
831 g_object_class_install_property (gobject_class,
833 g_param_spec_int ("width-chars",
834 P_("Width in chars"),
835 P_("Number of characters to leave space for in the entry"),
839 GTK_PARAM_READWRITE));
841 g_object_class_install_property (gobject_class,
843 g_param_spec_int ("scroll-offset",
845 P_("Number of pixels of the entry scrolled off the screen to the left"),
849 GTK_PARAM_READABLE));
851 g_object_class_install_property (gobject_class,
853 g_param_spec_string ("text",
855 P_("The contents of the entry"),
857 GTK_PARAM_READWRITE));
862 * The horizontal alignment, from 0 (left) to 1 (right).
863 * Reversed for RTL layouts.
867 g_object_class_install_property (gobject_class,
869 g_param_spec_float ("xalign",
871 P_("The horizontal alignment, from 0 (left) to 1 (right). Reversed for RTL layouts."),
875 GTK_PARAM_READWRITE));
878 * GtkEntry:truncate-multiline:
880 * When %TRUE, pasted multi-line text is truncated to the first line.
884 g_object_class_install_property (gobject_class,
885 PROP_TRUNCATE_MULTILINE,
886 g_param_spec_boolean ("truncate-multiline",
887 P_("Truncate multiline"),
888 P_("Whether to truncate multiline pastes to one line."),
890 GTK_PARAM_READWRITE));
893 * GtkEntry:shadow-type:
895 * Which kind of shadow to draw around the entry when
896 * #GtkEntry:has-frame is set to %TRUE.
900 g_object_class_install_property (gobject_class,
902 g_param_spec_enum ("shadow-type",
904 P_("Which kind of shadow to draw around the entry when has-frame is set"),
905 GTK_TYPE_SHADOW_TYPE,
907 GTK_PARAM_READWRITE));
910 * GtkEntry:overwrite-mode:
912 * If text is overwritten when typing in the #GtkEntry.
916 g_object_class_install_property (gobject_class,
918 g_param_spec_boolean ("overwrite-mode",
919 P_("Overwrite mode"),
920 P_("Whether new text overwrites existing text"),
922 GTK_PARAM_READWRITE));
925 * GtkEntry:text-length:
927 * The length of the text in the #GtkEntry.
931 g_object_class_install_property (gobject_class,
933 g_param_spec_uint ("text-length",
935 P_("Length of the text currently in the entry"),
939 GTK_PARAM_READABLE));
941 * GtkEntry:invisible-char-set:
943 * Whether the invisible char has been set for the #GtkEntry.
947 g_object_class_install_property (gobject_class,
948 PROP_INVISIBLE_CHAR_SET,
949 g_param_spec_boolean ("invisible-char-set",
950 P_("Invisible character set"),
951 P_("Whether the invisible character has been set"),
953 GTK_PARAM_READWRITE));
956 * GtkEntry:caps-lock-warning:
958 * Whether password entries will show a warning when Caps Lock is on.
960 * Note that the warning is shown using a secondary icon, and thus
961 * does not work if you are using the secondary icon position for some
966 g_object_class_install_property (gobject_class,
967 PROP_CAPS_LOCK_WARNING,
968 g_param_spec_boolean ("caps-lock-warning",
969 P_("Caps Lock warning"),
970 P_("Whether password entries will show a warning when Caps Lock is on"),
972 GTK_PARAM_READWRITE));
975 * GtkEntry:progress-fraction:
977 * The current fraction of the task that's been completed.
981 g_object_class_install_property (gobject_class,
982 PROP_PROGRESS_FRACTION,
983 g_param_spec_double ("progress-fraction",
984 P_("Progress Fraction"),
985 P_("The current fraction of the task that's been completed"),
989 GTK_PARAM_READWRITE));
992 * GtkEntry:progress-pulse-step:
994 * The fraction of total entry width to move the progress
995 * bouncing block for each call to gtk_entry_progress_pulse().
999 g_object_class_install_property (gobject_class,
1000 PROP_PROGRESS_PULSE_STEP,
1001 g_param_spec_double ("progress-pulse-step",
1002 P_("Progress Pulse Step"),
1003 P_("The fraction of total entry width to move the progress bouncing block for each call to gtk_entry_progress_pulse()"),
1007 GTK_PARAM_READWRITE));
1010 * GtkEntry:placeholder-text:
1012 * The text that will be displayed in the #GtkEntry when it is empty
1017 g_object_class_install_property (gobject_class,
1018 PROP_PLACEHOLDER_TEXT,
1019 g_param_spec_string ("placeholder-text",
1020 P_("Placeholder text"),
1021 P_("Show text in the entry when it's empty and unfocused"),
1023 GTK_PARAM_READWRITE));
1026 * GtkEntry:primary-icon-pixbuf:
1028 * A pixbuf to use as the primary icon for the entry.
1032 g_object_class_install_property (gobject_class,
1033 PROP_PIXBUF_PRIMARY,
1034 g_param_spec_object ("primary-icon-pixbuf",
1035 P_("Primary pixbuf"),
1036 P_("Primary pixbuf for the entry"),
1038 GTK_PARAM_READWRITE));
1041 * GtkEntry:secondary-icon-pixbuf:
1043 * An pixbuf to use as the secondary icon for the entry.
1047 g_object_class_install_property (gobject_class,
1048 PROP_PIXBUF_SECONDARY,
1049 g_param_spec_object ("secondary-icon-pixbuf",
1050 P_("Secondary pixbuf"),
1051 P_("Secondary pixbuf for the entry"),
1053 GTK_PARAM_READWRITE));
1056 * GtkEntry:primary-icon-stock:
1058 * The stock id to use for the primary icon for the entry.
1062 g_object_class_install_property (gobject_class,
1064 g_param_spec_string ("primary-icon-stock",
1065 P_("Primary stock ID"),
1066 P_("Stock ID for primary icon"),
1068 GTK_PARAM_READWRITE));
1071 * GtkEntry:secondary-icon-stock:
1073 * The stock id to use for the secondary icon for the entry.
1077 g_object_class_install_property (gobject_class,
1078 PROP_STOCK_SECONDARY,
1079 g_param_spec_string ("secondary-icon-stock",
1080 P_("Secondary stock ID"),
1081 P_("Stock ID for secondary icon"),
1083 GTK_PARAM_READWRITE));
1086 * GtkEntry:primary-icon-name:
1088 * The icon name to use for the primary icon for the entry.
1092 g_object_class_install_property (gobject_class,
1093 PROP_ICON_NAME_PRIMARY,
1094 g_param_spec_string ("primary-icon-name",
1095 P_("Primary icon name"),
1096 P_("Icon name for primary icon"),
1098 GTK_PARAM_READWRITE));
1101 * GtkEntry:secondary-icon-name:
1103 * The icon name to use for the secondary icon for the entry.
1107 g_object_class_install_property (gobject_class,
1108 PROP_ICON_NAME_SECONDARY,
1109 g_param_spec_string ("secondary-icon-name",
1110 P_("Secondary icon name"),
1111 P_("Icon name for secondary icon"),
1113 GTK_PARAM_READWRITE));
1116 * GtkEntry:primary-icon-gicon:
1118 * The #GIcon to use for the primary icon for the entry.
1122 g_object_class_install_property (gobject_class,
1124 g_param_spec_object ("primary-icon-gicon",
1125 P_("Primary GIcon"),
1126 P_("GIcon for primary icon"),
1128 GTK_PARAM_READWRITE));
1131 * GtkEntry:secondary-icon-gicon:
1133 * The #GIcon to use for the secondary icon for the entry.
1137 g_object_class_install_property (gobject_class,
1138 PROP_GICON_SECONDARY,
1139 g_param_spec_object ("secondary-icon-gicon",
1140 P_("Secondary GIcon"),
1141 P_("GIcon for secondary icon"),
1143 GTK_PARAM_READWRITE));
1146 * GtkEntry:primary-icon-storage-type:
1148 * The representation which is used for the primary icon of the entry.
1152 g_object_class_install_property (gobject_class,
1153 PROP_STORAGE_TYPE_PRIMARY,
1154 g_param_spec_enum ("primary-icon-storage-type",
1155 P_("Primary storage type"),
1156 P_("The representation being used for primary icon"),
1157 GTK_TYPE_IMAGE_TYPE,
1159 GTK_PARAM_READABLE));
1162 * GtkEntry:secondary-icon-storage-type:
1164 * The representation which is used for the secondary icon of the entry.
1168 g_object_class_install_property (gobject_class,
1169 PROP_STORAGE_TYPE_SECONDARY,
1170 g_param_spec_enum ("secondary-icon-storage-type",
1171 P_("Secondary storage type"),
1172 P_("The representation being used for secondary icon"),
1173 GTK_TYPE_IMAGE_TYPE,
1175 GTK_PARAM_READABLE));
1178 * GtkEntry:primary-icon-activatable:
1180 * Whether the primary icon is activatable.
1182 * GTK+ emits the #GtkEntry::icon-press and #GtkEntry::icon-release
1183 * signals only on sensitive, activatable icons.
1185 * Sensitive, but non-activatable icons can be used for purely
1186 * informational purposes.
1190 g_object_class_install_property (gobject_class,
1191 PROP_ACTIVATABLE_PRIMARY,
1192 g_param_spec_boolean ("primary-icon-activatable",
1193 P_("Primary icon activatable"),
1194 P_("Whether the primary icon is activatable"),
1196 GTK_PARAM_READWRITE));
1199 * GtkEntry:secondary-icon-activatable:
1201 * Whether the secondary icon is activatable.
1203 * GTK+ emits the #GtkEntry::icon-press and #GtkEntry::icon-release
1204 * signals only on sensitive, activatable icons.
1206 * Sensitive, but non-activatable icons can be used for purely
1207 * informational purposes.
1211 g_object_class_install_property (gobject_class,
1212 PROP_ACTIVATABLE_SECONDARY,
1213 g_param_spec_boolean ("secondary-icon-activatable",
1214 P_("Secondary icon activatable"),
1215 P_("Whether the secondary icon is activatable"),
1217 GTK_PARAM_READWRITE));
1221 * GtkEntry:primary-icon-sensitive:
1223 * Whether the primary icon is sensitive.
1225 * An insensitive icon appears grayed out. GTK+ does not emit the
1226 * #GtkEntry::icon-press and #GtkEntry::icon-release signals and
1227 * does not allow DND from insensitive icons.
1229 * An icon should be set insensitive if the action that would trigger
1230 * when clicked is currently not available.
1234 g_object_class_install_property (gobject_class,
1235 PROP_SENSITIVE_PRIMARY,
1236 g_param_spec_boolean ("primary-icon-sensitive",
1237 P_("Primary icon sensitive"),
1238 P_("Whether the primary icon is sensitive"),
1240 GTK_PARAM_READWRITE));
1243 * GtkEntry:secondary-icon-sensitive:
1245 * Whether the secondary icon is sensitive.
1247 * An insensitive icon appears grayed out. GTK+ does not emit the
1248 * #GtkEntry::icon-press and #GtkEntry::icon-release signals and
1249 * does not allow DND from insensitive icons.
1251 * An icon should be set insensitive if the action that would trigger
1252 * when clicked is currently not available.
1256 g_object_class_install_property (gobject_class,
1257 PROP_SENSITIVE_SECONDARY,
1258 g_param_spec_boolean ("secondary-icon-sensitive",
1259 P_("Secondary icon sensitive"),
1260 P_("Whether the secondary icon is sensitive"),
1262 GTK_PARAM_READWRITE));
1265 * GtkEntry:primary-icon-tooltip-text:
1267 * The contents of the tooltip on the primary icon.
1269 * Also see gtk_entry_set_icon_tooltip_text().
1273 g_object_class_install_property (gobject_class,
1274 PROP_TOOLTIP_TEXT_PRIMARY,
1275 g_param_spec_string ("primary-icon-tooltip-text",
1276 P_("Primary icon tooltip text"),
1277 P_("The contents of the tooltip on the primary icon"),
1279 GTK_PARAM_READWRITE));
1282 * GtkEntry:secondary-icon-tooltip-text:
1284 * The contents of the tooltip on the secondary icon.
1286 * Also see gtk_entry_set_icon_tooltip_text().
1290 g_object_class_install_property (gobject_class,
1291 PROP_TOOLTIP_TEXT_SECONDARY,
1292 g_param_spec_string ("secondary-icon-tooltip-text",
1293 P_("Secondary icon tooltip text"),
1294 P_("The contents of the tooltip on the secondary icon"),
1296 GTK_PARAM_READWRITE));
1299 * GtkEntry:primary-icon-tooltip-markup:
1301 * The contents of the tooltip on the primary icon, which is marked up
1302 * with the <link linkend="PangoMarkupFormat">Pango text markup
1305 * Also see gtk_entry_set_icon_tooltip_markup().
1309 g_object_class_install_property (gobject_class,
1310 PROP_TOOLTIP_MARKUP_PRIMARY,
1311 g_param_spec_string ("primary-icon-tooltip-markup",
1312 P_("Primary icon tooltip markup"),
1313 P_("The contents of the tooltip on the primary icon"),
1315 GTK_PARAM_READWRITE));
1318 * GtkEntry:secondary-icon-tooltip-markup:
1320 * The contents of the tooltip on the secondary icon, which is marked up
1321 * with the <link linkend="PangoMarkupFormat">Pango text markup
1324 * Also see gtk_entry_set_icon_tooltip_markup().
1328 g_object_class_install_property (gobject_class,
1329 PROP_TOOLTIP_MARKUP_SECONDARY,
1330 g_param_spec_string ("secondary-icon-tooltip-markup",
1331 P_("Secondary icon tooltip markup"),
1332 P_("The contents of the tooltip on the secondary icon"),
1334 GTK_PARAM_READWRITE));
1337 * GtkEntry:im-module:
1339 * Which IM (input method) module should be used for this entry.
1340 * See #GtkIMContext.
1342 * Setting this to a non-%NULL value overrides the
1343 * system-wide IM module setting. See the GtkSettings
1344 * #GtkSettings:gtk-im-module property.
1348 g_object_class_install_property (gobject_class,
1350 g_param_spec_string ("im-module",
1352 P_("Which IM module should be used"),
1354 GTK_PARAM_READWRITE));
1357 * GtkEntry:completion:
1359 * The auxiliary completion object to use with the entry.
1363 g_object_class_install_property (gobject_class,
1365 g_param_spec_object ("completion",
1367 P_("The auxiliary completion object"),
1368 GTK_TYPE_ENTRY_COMPLETION,
1369 GTK_PARAM_READWRITE));
1372 * GtkEntry:input-purpose:
1374 * The purpose of this text field.
1376 * This property can be used by on-screen keyboards and other input
1377 * methods to adjust their behaviour.
1379 * Note that setting the purpose to %GTK_INPUT_PURPOSE_PASSWORD or
1380 * %GTK_INPUT_PURPOSE_PIN is independent from setting
1381 * #GtkEntry:visibility.
1385 g_object_class_install_property (gobject_class,
1387 g_param_spec_enum ("input-purpose",
1389 P_("Purpose of the text field"),
1390 GTK_TYPE_INPUT_PURPOSE,
1391 GTK_INPUT_PURPOSE_FREE_FORM,
1392 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1395 * GtkEntry:input-hints:
1397 * Additional hints (beyond #GtkEntry:input-purpose) that
1398 * allow input methods to fine-tune their behaviour.
1402 g_object_class_install_property (gobject_class,
1404 g_param_spec_flags ("input-hints",
1406 P_("Hints for the text field behaviour"),
1407 GTK_TYPE_INPUT_HINTS,
1408 GTK_INPUT_HINT_NONE,
1409 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1412 * GtkEntry:attributes:
1414 * A list of Pango attributes to apply to the text of the entry.
1416 * This is mainly useful to change the size or weight of the text.
1420 g_object_class_install_property (gobject_class,
1422 g_param_spec_boxed ("attributes",
1424 P_("A list of style attributes to apply to the text of the label"),
1425 PANGO_TYPE_ATTR_LIST,
1426 GTK_PARAM_READWRITE));
1428 /** GtkEntry:populate-toolbar:
1430 * If ::populate-toolbar is %TRUE, the #GtkEntry::populate-popup
1431 * signal is also emitted for touch popups.
1435 g_object_class_install_property (gobject_class,
1436 PROP_POPULATE_TOOLBAR,
1437 g_param_spec_boolean ("populate-toolbar",
1438 P_("Populate toolbar"),
1439 P_("Whether to emit ::populate-popup for touch popups"),
1441 GTK_PARAM_READWRITE));
1444 * GtkEntry:icon-prelight:
1446 * The prelight style property determines whether activatable
1447 * icons prelight on mouseover.
1451 gtk_widget_class_install_style_property (widget_class,
1452 g_param_spec_boolean ("icon-prelight",
1453 P_("Icon Prelight"),
1454 P_("Whether activatable icons should prelight when hovered"),
1456 GTK_PARAM_READABLE));
1459 * GtkEntry:progress-border:
1461 * The border around the progress bar in the entry.
1465 * Deprecated: 3.4: Use the standard margin CSS property (through objects
1466 * like #GtkStyleContext and #GtkCssProvider); the value of this style
1467 * property is ignored.
1469 gtk_widget_class_install_style_property (widget_class,
1470 g_param_spec_boxed ("progress-border",
1471 P_("Progress Border"),
1472 P_("Border around the progress bar"),
1474 GTK_PARAM_READABLE |
1475 G_PARAM_DEPRECATED));
1478 * GtkEntry:invisible-char:
1480 * The invisible character is used when masking entry contents (in
1481 * \"password mode\")"). When it is not explicitly set with the
1482 * #GtkEntry:invisible-char property, GTK+ determines the character
1483 * to use from a list of possible candidates, depending on availability
1484 * in the current font.
1486 * This style property allows the theme to prepend a character
1487 * to the list of candidates.
1491 gtk_widget_class_install_style_property (widget_class,
1492 g_param_spec_unichar ("invisible-char",
1493 P_("Invisible character"),
1494 P_("The character to use when masking entry contents (in \"password mode\")"),
1496 GTK_PARAM_READABLE));
1499 * GtkEntry::populate-popup:
1500 * @entry: The entry on which the signal is emitted
1501 * @popup: the menu or toolbar that is being populated
1503 * The ::populate-popup signal gets emitted before showing the
1504 * context menu of the entry.
1506 * If you need to add items to the context menu, connect
1507 * to this signal and append your items to the @widget.
1509 * If #GtkEntry::populate-toolbar is %TRUE, this signal will
1510 * also be emitted to populate touch popups. In this case,
1511 * @widget will be a toolbar instead of a menu.
1513 signals[POPULATE_POPUP] =
1514 g_signal_new (I_("populate-popup"),
1515 G_OBJECT_CLASS_TYPE (gobject_class),
1517 G_STRUCT_OFFSET (GtkEntryClass, populate_popup),
1519 _gtk_marshal_VOID__OBJECT,
1523 /* Action signals */
1526 * GtkEntry::activate:
1527 * @entry: The entry on which the signal is emitted
1529 * The ::activate signal is emitted when the user hits
1532 * While this signal is used as a
1533 * <link linkend="keybinding-signals">keybinding signal</link>,
1534 * it is also commonly used by applications to intercept
1535 * activation of entries.
1537 * The default bindings for this signal are all forms of the Enter key.
1540 g_signal_new (I_("activate"),
1541 G_OBJECT_CLASS_TYPE (gobject_class),
1542 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1543 G_STRUCT_OFFSET (GtkEntryClass, activate),
1545 _gtk_marshal_VOID__VOID,
1547 widget_class->activate_signal = signals[ACTIVATE];
1550 * GtkEntry::move-cursor:
1551 * @entry: the object which received the signal
1552 * @step: the granularity of the move, as a #GtkMovementStep
1553 * @count: the number of @step units to move
1554 * @extend_selection: %TRUE if the move should extend the selection
1556 * The ::move-cursor signal is a
1557 * <link linkend="keybinding-signals">keybinding signal</link>
1558 * which gets emitted when the user initiates a cursor movement.
1559 * If the cursor is not visible in @entry, this signal causes
1560 * the viewport to be moved instead.
1562 * Applications should not connect to it, but may emit it with
1563 * g_signal_emit_by_name() if they need to control the cursor
1566 * The default bindings for this signal come in two variants,
1567 * the variant with the Shift modifier extends the selection,
1568 * the variant without the Shift modifer does not.
1569 * There are too many key combinations to list them all here.
1571 * <listitem>Arrow keys move by individual characters/lines</listitem>
1572 * <listitem>Ctrl-arrow key combinations move by words/paragraphs</listitem>
1573 * <listitem>Home/End keys move to the ends of the buffer</listitem>
1576 signals[MOVE_CURSOR] =
1577 g_signal_new (I_("move-cursor"),
1578 G_OBJECT_CLASS_TYPE (gobject_class),
1579 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1580 G_STRUCT_OFFSET (GtkEntryClass, move_cursor),
1582 _gtk_marshal_VOID__ENUM_INT_BOOLEAN,
1584 GTK_TYPE_MOVEMENT_STEP,
1589 * GtkEntry::insert-at-cursor:
1590 * @entry: the object which received the signal
1591 * @string: the string to insert
1593 * The ::insert-at-cursor signal is a
1594 * <link linkend="keybinding-signals">keybinding signal</link>
1595 * which gets emitted when the user initiates the insertion of a
1596 * fixed string at the cursor.
1598 * This signal has no default bindings.
1600 signals[INSERT_AT_CURSOR] =
1601 g_signal_new (I_("insert-at-cursor"),
1602 G_OBJECT_CLASS_TYPE (gobject_class),
1603 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1604 G_STRUCT_OFFSET (GtkEntryClass, insert_at_cursor),
1606 _gtk_marshal_VOID__STRING,
1611 * GtkEntry::delete-from-cursor:
1612 * @entry: the object which received the signal
1613 * @type: the granularity of the deletion, as a #GtkDeleteType
1614 * @count: the number of @type units to delete
1616 * The ::delete-from-cursor signal is a
1617 * <link linkend="keybinding-signals">keybinding signal</link>
1618 * which gets emitted when the user initiates a text deletion.
1620 * If the @type is %GTK_DELETE_CHARS, GTK+ deletes the selection
1621 * if there is one, otherwise it deletes the requested number
1624 * The default bindings for this signal are
1625 * Delete for deleting a character and Ctrl-Delete for
1628 signals[DELETE_FROM_CURSOR] =
1629 g_signal_new (I_("delete-from-cursor"),
1630 G_OBJECT_CLASS_TYPE (gobject_class),
1631 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1632 G_STRUCT_OFFSET (GtkEntryClass, delete_from_cursor),
1634 _gtk_marshal_VOID__ENUM_INT,
1636 GTK_TYPE_DELETE_TYPE,
1640 * GtkEntry::backspace:
1641 * @entry: the object which received the signal
1643 * The ::backspace signal is a
1644 * <link linkend="keybinding-signals">keybinding signal</link>
1645 * which gets emitted when the user asks for it.
1647 * The default bindings for this signal are
1648 * Backspace and Shift-Backspace.
1650 signals[BACKSPACE] =
1651 g_signal_new (I_("backspace"),
1652 G_OBJECT_CLASS_TYPE (gobject_class),
1653 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1654 G_STRUCT_OFFSET (GtkEntryClass, backspace),
1656 _gtk_marshal_VOID__VOID,
1660 * GtkEntry::cut-clipboard:
1661 * @entry: the object which received the signal
1663 * The ::cut-clipboard signal is a
1664 * <link linkend="keybinding-signals">keybinding signal</link>
1665 * which gets emitted to cut the selection to the clipboard.
1667 * The default bindings for this signal are
1668 * Ctrl-x and Shift-Delete.
1670 signals[CUT_CLIPBOARD] =
1671 g_signal_new (I_("cut-clipboard"),
1672 G_OBJECT_CLASS_TYPE (gobject_class),
1673 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1674 G_STRUCT_OFFSET (GtkEntryClass, cut_clipboard),
1676 _gtk_marshal_VOID__VOID,
1680 * GtkEntry::copy-clipboard:
1681 * @entry: the object which received the signal
1683 * The ::copy-clipboard signal is a
1684 * <link linkend="keybinding-signals">keybinding signal</link>
1685 * which gets emitted to copy the selection to the clipboard.
1687 * The default bindings for this signal are
1688 * Ctrl-c and Ctrl-Insert.
1690 signals[COPY_CLIPBOARD] =
1691 g_signal_new (I_("copy-clipboard"),
1692 G_OBJECT_CLASS_TYPE (gobject_class),
1693 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1694 G_STRUCT_OFFSET (GtkEntryClass, copy_clipboard),
1696 _gtk_marshal_VOID__VOID,
1700 * GtkEntry::paste-clipboard:
1701 * @entry: the object which received the signal
1703 * The ::paste-clipboard signal is a
1704 * <link linkend="keybinding-signals">keybinding signal</link>
1705 * which gets emitted to paste the contents of the clipboard
1706 * into the text view.
1708 * The default bindings for this signal are
1709 * Ctrl-v and Shift-Insert.
1711 signals[PASTE_CLIPBOARD] =
1712 g_signal_new (I_("paste-clipboard"),
1713 G_OBJECT_CLASS_TYPE (gobject_class),
1714 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1715 G_STRUCT_OFFSET (GtkEntryClass, paste_clipboard),
1717 _gtk_marshal_VOID__VOID,
1721 * GtkEntry::toggle-overwrite:
1722 * @entry: the object which received the signal
1724 * The ::toggle-overwrite signal is a
1725 * <link linkend="keybinding-signals">keybinding signal</link>
1726 * which gets emitted to toggle the overwrite mode of the entry.
1728 * The default bindings for this signal is Insert.
1730 signals[TOGGLE_OVERWRITE] =
1731 g_signal_new (I_("toggle-overwrite"),
1732 G_OBJECT_CLASS_TYPE (gobject_class),
1733 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1734 G_STRUCT_OFFSET (GtkEntryClass, toggle_overwrite),
1736 _gtk_marshal_VOID__VOID,
1740 * GtkEntry::icon-press:
1741 * @entry: The entry on which the signal is emitted
1742 * @icon_pos: The position of the clicked icon
1743 * @event: (type Gdk.EventButton): the button press event
1745 * The ::icon-press signal is emitted when an activatable icon
1750 signals[ICON_PRESS] =
1751 g_signal_new (I_("icon-press"),
1752 G_TYPE_FROM_CLASS (gobject_class),
1756 _gtk_marshal_VOID__ENUM_BOXED,
1758 GTK_TYPE_ENTRY_ICON_POSITION,
1759 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
1762 * GtkEntry::icon-release:
1763 * @entry: The entry on which the signal is emitted
1764 * @icon_pos: The position of the clicked icon
1765 * @event: (type Gdk.EventButton): the button release event
1767 * The ::icon-release signal is emitted on the button release from a
1768 * mouse click over an activatable icon.
1772 signals[ICON_RELEASE] =
1773 g_signal_new (I_("icon-release"),
1774 G_TYPE_FROM_CLASS (gobject_class),
1778 _gtk_marshal_VOID__ENUM_BOXED,
1780 GTK_TYPE_ENTRY_ICON_POSITION,
1781 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
1784 * GtkEntry::preedit-changed:
1785 * @entry: the object which received the signal
1786 * @preedit: the current preedit string
1788 * If an input method is used, the typed text will not immediately
1789 * be committed to the buffer. So if you are interested in the text,
1790 * connect to this signal.
1794 signals[PREEDIT_CHANGED] =
1795 g_signal_new_class_handler (I_("preedit-changed"),
1796 G_OBJECT_CLASS_TYPE (gobject_class),
1797 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1800 _gtk_marshal_VOID__STRING,
1809 binding_set = gtk_binding_set_by_class (class);
1811 /* Moving the insertion point */
1812 add_move_binding (binding_set, GDK_KEY_Right, 0,
1813 GTK_MOVEMENT_VISUAL_POSITIONS, 1);
1815 add_move_binding (binding_set, GDK_KEY_Left, 0,
1816 GTK_MOVEMENT_VISUAL_POSITIONS, -1);
1818 add_move_binding (binding_set, GDK_KEY_KP_Right, 0,
1819 GTK_MOVEMENT_VISUAL_POSITIONS, 1);
1821 add_move_binding (binding_set, GDK_KEY_KP_Left, 0,
1822 GTK_MOVEMENT_VISUAL_POSITIONS, -1);
1824 add_move_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK,
1825 GTK_MOVEMENT_WORDS, 1);
1827 add_move_binding (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK,
1828 GTK_MOVEMENT_WORDS, -1);
1830 add_move_binding (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
1831 GTK_MOVEMENT_WORDS, 1);
1833 add_move_binding (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
1834 GTK_MOVEMENT_WORDS, -1);
1836 add_move_binding (binding_set, GDK_KEY_Home, 0,
1837 GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
1839 add_move_binding (binding_set, GDK_KEY_End, 0,
1840 GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
1842 add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
1843 GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
1845 add_move_binding (binding_set, GDK_KEY_KP_End, 0,
1846 GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
1848 add_move_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK,
1849 GTK_MOVEMENT_BUFFER_ENDS, -1);
1851 add_move_binding (binding_set, GDK_KEY_End, GDK_CONTROL_MASK,
1852 GTK_MOVEMENT_BUFFER_ENDS, 1);
1854 add_move_binding (binding_set, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
1855 GTK_MOVEMENT_BUFFER_ENDS, -1);
1857 add_move_binding (binding_set, GDK_KEY_KP_End, GDK_CONTROL_MASK,
1858 GTK_MOVEMENT_BUFFER_ENDS, 1);
1862 gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
1864 GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
1866 G_TYPE_BOOLEAN, FALSE);
1867 gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
1869 GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
1871 G_TYPE_BOOLEAN, TRUE);
1873 gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
1875 GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
1877 G_TYPE_BOOLEAN, FALSE);
1878 gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
1880 GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
1882 G_TYPE_BOOLEAN, TRUE);
1885 gtk_binding_entry_add_signal (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK,
1887 GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_VISUAL_POSITIONS,
1889 G_TYPE_BOOLEAN, FALSE);
1890 gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
1892 GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_VISUAL_POSITIONS,
1894 G_TYPE_BOOLEAN, FALSE);
1898 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1900 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1902 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1906 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, 0,
1907 "delete-from-cursor", 2,
1908 G_TYPE_ENUM, GTK_DELETE_CHARS,
1911 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, 0,
1912 "delete-from-cursor", 2,
1913 G_TYPE_ENUM, GTK_DELETE_CHARS,
1916 gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, 0,
1919 /* Make this do the same as Backspace, to help with mis-typing */
1920 gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_SHIFT_MASK,
1923 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_CONTROL_MASK,
1924 "delete-from-cursor", 2,
1925 G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
1928 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_CONTROL_MASK,
1929 "delete-from-cursor", 2,
1930 G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
1933 gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_CONTROL_MASK,
1934 "delete-from-cursor", 2,
1935 G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
1938 /* Cut/copy/paste */
1940 gtk_binding_entry_add_signal (binding_set, GDK_KEY_x, GDK_CONTROL_MASK,
1941 "cut-clipboard", 0);
1942 gtk_binding_entry_add_signal (binding_set, GDK_KEY_c, GDK_CONTROL_MASK,
1943 "copy-clipboard", 0);
1944 gtk_binding_entry_add_signal (binding_set, GDK_KEY_v, GDK_CONTROL_MASK,
1945 "paste-clipboard", 0);
1947 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_SHIFT_MASK,
1948 "cut-clipboard", 0);
1949 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, GDK_CONTROL_MASK,
1950 "copy-clipboard", 0);
1951 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, GDK_SHIFT_MASK,
1952 "paste-clipboard", 0);
1955 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, 0,
1956 "toggle-overwrite", 0);
1957 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, 0,
1958 "toggle-overwrite", 0);
1961 * GtkEntry:inner-border:
1963 * Sets the text area's border between the text and the frame.
1967 * Deprecated: 3.4: Use the standard border and padding CSS properties
1968 * (through objects like #GtkStyleContext and #GtkCssProvider); the value
1969 * of this style property is ignored.
1971 gtk_widget_class_install_style_property (widget_class,
1972 g_param_spec_boxed ("inner-border",
1974 P_("Border between text and frame."),
1976 GTK_PARAM_READABLE |
1977 G_PARAM_DEPRECATED));
1979 g_type_class_add_private (gobject_class, sizeof (GtkEntryPrivate));
1980 test_touchscreen = g_getenv ("GTK_TEST_TOUCHSCREEN") != NULL;
1982 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ENTRY_ACCESSIBLE);
1986 gtk_entry_editable_init (GtkEditableInterface *iface)
1988 iface->do_insert_text = gtk_entry_insert_text;
1989 iface->do_delete_text = gtk_entry_delete_text;
1990 iface->insert_text = gtk_entry_real_insert_text;
1991 iface->delete_text = gtk_entry_real_delete_text;
1992 iface->get_chars = gtk_entry_get_chars;
1993 iface->set_selection_bounds = gtk_entry_set_selection_bounds;
1994 iface->get_selection_bounds = gtk_entry_get_selection_bounds;
1995 iface->set_position = gtk_entry_real_set_position;
1996 iface->get_position = gtk_entry_get_position;
2000 gtk_entry_cell_editable_init (GtkCellEditableIface *iface)
2002 iface->start_editing = gtk_entry_start_editing;
2005 /* for deprecated properties */
2007 gtk_entry_do_set_inner_border (GtkEntry *entry,
2008 const GtkBorder *border)
2011 g_object_set_qdata_full (G_OBJECT (entry), quark_inner_border,
2012 gtk_border_copy (border),
2013 (GDestroyNotify) gtk_border_free);
2015 g_object_set_qdata (G_OBJECT (entry), quark_inner_border, NULL);
2017 g_object_notify (G_OBJECT (entry), "inner-border");
2020 static const GtkBorder *
2021 gtk_entry_do_get_inner_border (GtkEntry *entry)
2023 return g_object_get_qdata (G_OBJECT (entry), quark_inner_border);
2027 gtk_entry_set_property (GObject *object,
2029 const GValue *value,
2032 GtkEntry *entry = GTK_ENTRY (object);
2033 GtkEntryPrivate *priv = entry->priv;
2038 gtk_entry_set_buffer (entry, g_value_get_object (value));
2043 gboolean new_value = g_value_get_boolean (value);
2045 if (new_value != priv->editable)
2047 GtkWidget *widget = GTK_WIDGET (entry);
2051 gtk_entry_reset_im_context (entry);
2052 if (gtk_widget_has_focus (widget))
2053 gtk_im_context_focus_out (priv->im_context);
2055 priv->preedit_length = 0;
2056 priv->preedit_cursor = 0;
2059 priv->editable = new_value;
2061 if (new_value && gtk_widget_has_focus (widget))
2062 gtk_im_context_focus_in (priv->im_context);
2064 gtk_widget_queue_draw (widget);
2069 case PROP_MAX_LENGTH:
2070 gtk_entry_set_max_length (entry, g_value_get_int (value));
2073 case PROP_VISIBILITY:
2074 gtk_entry_set_visibility (entry, g_value_get_boolean (value));
2077 case PROP_HAS_FRAME:
2078 gtk_entry_set_has_frame (entry, g_value_get_boolean (value));
2081 case PROP_INNER_BORDER:
2082 gtk_entry_do_set_inner_border (entry, g_value_get_boxed (value));
2085 case PROP_INVISIBLE_CHAR:
2086 gtk_entry_set_invisible_char (entry, g_value_get_uint (value));
2089 case PROP_ACTIVATES_DEFAULT:
2090 gtk_entry_set_activates_default (entry, g_value_get_boolean (value));
2093 case PROP_WIDTH_CHARS:
2094 gtk_entry_set_width_chars (entry, g_value_get_int (value));
2098 gtk_entry_set_text (entry, g_value_get_string (value));
2102 gtk_entry_set_alignment (entry, g_value_get_float (value));
2105 case PROP_TRUNCATE_MULTILINE:
2106 priv->truncate_multiline = g_value_get_boolean (value);
2109 case PROP_SHADOW_TYPE:
2110 priv->shadow_type = g_value_get_enum (value);
2113 case PROP_OVERWRITE_MODE:
2114 gtk_entry_set_overwrite_mode (entry, g_value_get_boolean (value));
2117 case PROP_INVISIBLE_CHAR_SET:
2118 if (g_value_get_boolean (value))
2119 priv->invisible_char_set = TRUE;
2121 gtk_entry_unset_invisible_char (entry);
2124 case PROP_CAPS_LOCK_WARNING:
2125 priv->caps_lock_warning = g_value_get_boolean (value);
2128 case PROP_PROGRESS_FRACTION:
2129 gtk_entry_set_progress_fraction (entry, g_value_get_double (value));
2132 case PROP_PROGRESS_PULSE_STEP:
2133 gtk_entry_set_progress_pulse_step (entry, g_value_get_double (value));
2136 case PROP_PLACEHOLDER_TEXT:
2137 gtk_entry_set_placeholder_text (entry, g_value_get_string (value));
2140 case PROP_PIXBUF_PRIMARY:
2141 gtk_entry_set_icon_from_pixbuf (entry,
2142 GTK_ENTRY_ICON_PRIMARY,
2143 g_value_get_object (value));
2146 case PROP_PIXBUF_SECONDARY:
2147 gtk_entry_set_icon_from_pixbuf (entry,
2148 GTK_ENTRY_ICON_SECONDARY,
2149 g_value_get_object (value));
2152 case PROP_STOCK_PRIMARY:
2153 gtk_entry_set_icon_from_stock (entry,
2154 GTK_ENTRY_ICON_PRIMARY,
2155 g_value_get_string (value));
2158 case PROP_STOCK_SECONDARY:
2159 gtk_entry_set_icon_from_stock (entry,
2160 GTK_ENTRY_ICON_SECONDARY,
2161 g_value_get_string (value));
2164 case PROP_ICON_NAME_PRIMARY:
2165 gtk_entry_set_icon_from_icon_name (entry,
2166 GTK_ENTRY_ICON_PRIMARY,
2167 g_value_get_string (value));
2170 case PROP_ICON_NAME_SECONDARY:
2171 gtk_entry_set_icon_from_icon_name (entry,
2172 GTK_ENTRY_ICON_SECONDARY,
2173 g_value_get_string (value));
2176 case PROP_GICON_PRIMARY:
2177 gtk_entry_set_icon_from_gicon (entry,
2178 GTK_ENTRY_ICON_PRIMARY,
2179 g_value_get_object (value));
2182 case PROP_GICON_SECONDARY:
2183 gtk_entry_set_icon_from_gicon (entry,
2184 GTK_ENTRY_ICON_SECONDARY,
2185 g_value_get_object (value));
2188 case PROP_ACTIVATABLE_PRIMARY:
2189 gtk_entry_set_icon_activatable (entry,
2190 GTK_ENTRY_ICON_PRIMARY,
2191 g_value_get_boolean (value));
2194 case PROP_ACTIVATABLE_SECONDARY:
2195 gtk_entry_set_icon_activatable (entry,
2196 GTK_ENTRY_ICON_SECONDARY,
2197 g_value_get_boolean (value));
2200 case PROP_SENSITIVE_PRIMARY:
2201 gtk_entry_set_icon_sensitive (entry,
2202 GTK_ENTRY_ICON_PRIMARY,
2203 g_value_get_boolean (value));
2206 case PROP_SENSITIVE_SECONDARY:
2207 gtk_entry_set_icon_sensitive (entry,
2208 GTK_ENTRY_ICON_SECONDARY,
2209 g_value_get_boolean (value));
2212 case PROP_TOOLTIP_TEXT_PRIMARY:
2213 gtk_entry_set_icon_tooltip_text (entry,
2214 GTK_ENTRY_ICON_PRIMARY,
2215 g_value_get_string (value));
2218 case PROP_TOOLTIP_TEXT_SECONDARY:
2219 gtk_entry_set_icon_tooltip_text (entry,
2220 GTK_ENTRY_ICON_SECONDARY,
2221 g_value_get_string (value));
2224 case PROP_TOOLTIP_MARKUP_PRIMARY:
2225 gtk_entry_set_icon_tooltip_markup (entry,
2226 GTK_ENTRY_ICON_PRIMARY,
2227 g_value_get_string (value));
2230 case PROP_TOOLTIP_MARKUP_SECONDARY:
2231 gtk_entry_set_icon_tooltip_markup (entry,
2232 GTK_ENTRY_ICON_SECONDARY,
2233 g_value_get_string (value));
2236 case PROP_IM_MODULE:
2237 g_free (priv->im_module);
2238 priv->im_module = g_value_dup_string (value);
2239 if (GTK_IS_IM_MULTICONTEXT (priv->im_context))
2240 gtk_im_multicontext_set_context_id (GTK_IM_MULTICONTEXT (priv->im_context), priv->im_module);
2243 case PROP_EDITING_CANCELED:
2244 priv->editing_canceled = g_value_get_boolean (value);
2247 case PROP_COMPLETION:
2248 gtk_entry_set_completion (entry, GTK_ENTRY_COMPLETION (g_value_get_object (value)));
2251 case PROP_INPUT_PURPOSE:
2252 gtk_entry_set_input_purpose (entry, g_value_get_enum (value));
2255 case PROP_INPUT_HINTS:
2256 gtk_entry_set_input_hints (entry, g_value_get_flags (value));
2259 case PROP_ATTRIBUTES:
2260 gtk_entry_set_attributes (entry, g_value_get_boxed (value));
2263 case PROP_POPULATE_TOOLBAR:
2264 entry->priv->populate_toolbar = g_value_get_boolean (value);
2267 case PROP_SCROLL_OFFSET:
2268 case PROP_CURSOR_POSITION:
2270 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2276 gtk_entry_get_property (GObject *object,
2281 GtkEntry *entry = GTK_ENTRY (object);
2282 GtkEntryPrivate *priv = entry->priv;
2287 g_value_set_object (value, gtk_entry_get_buffer (entry));
2290 case PROP_CURSOR_POSITION:
2291 g_value_set_int (value, priv->current_pos);
2294 case PROP_SELECTION_BOUND:
2295 g_value_set_int (value, priv->selection_bound);
2299 g_value_set_boolean (value, priv->editable);
2302 case PROP_MAX_LENGTH:
2303 g_value_set_int (value, gtk_entry_buffer_get_max_length (get_buffer (entry)));
2306 case PROP_VISIBILITY:
2307 g_value_set_boolean (value, priv->visible);
2310 case PROP_HAS_FRAME:
2311 g_value_set_boolean (value, priv->has_frame);
2314 case PROP_INNER_BORDER:
2315 g_value_set_boxed (value, gtk_entry_do_get_inner_border (entry));
2318 case PROP_INVISIBLE_CHAR:
2319 g_value_set_uint (value, priv->invisible_char);
2322 case PROP_ACTIVATES_DEFAULT:
2323 g_value_set_boolean (value, priv->activates_default);
2326 case PROP_WIDTH_CHARS:
2327 g_value_set_int (value, priv->width_chars);
2330 case PROP_SCROLL_OFFSET:
2331 g_value_set_int (value, priv->scroll_offset);
2335 g_value_set_string (value, gtk_entry_get_text (entry));
2339 g_value_set_float (value, gtk_entry_get_alignment (entry));
2342 case PROP_TRUNCATE_MULTILINE:
2343 g_value_set_boolean (value, priv->truncate_multiline);
2346 case PROP_SHADOW_TYPE:
2347 g_value_set_enum (value, priv->shadow_type);
2350 case PROP_OVERWRITE_MODE:
2351 g_value_set_boolean (value, priv->overwrite_mode);
2354 case PROP_TEXT_LENGTH:
2355 g_value_set_uint (value, gtk_entry_buffer_get_length (get_buffer (entry)));
2358 case PROP_INVISIBLE_CHAR_SET:
2359 g_value_set_boolean (value, priv->invisible_char_set);
2362 case PROP_IM_MODULE:
2363 g_value_set_string (value, priv->im_module);
2366 case PROP_CAPS_LOCK_WARNING:
2367 g_value_set_boolean (value, priv->caps_lock_warning);
2370 case PROP_PROGRESS_FRACTION:
2371 g_value_set_double (value, priv->progress_fraction);
2374 case PROP_PROGRESS_PULSE_STEP:
2375 g_value_set_double (value, priv->progress_pulse_fraction);
2378 case PROP_PLACEHOLDER_TEXT:
2379 g_value_set_string (value, gtk_entry_get_placeholder_text (entry));
2382 case PROP_PIXBUF_PRIMARY:
2383 g_value_set_object (value,
2384 gtk_entry_get_icon_pixbuf (entry,
2385 GTK_ENTRY_ICON_PRIMARY));
2388 case PROP_PIXBUF_SECONDARY:
2389 g_value_set_object (value,
2390 gtk_entry_get_icon_pixbuf (entry,
2391 GTK_ENTRY_ICON_SECONDARY));
2394 case PROP_STOCK_PRIMARY:
2395 g_value_set_string (value,
2396 gtk_entry_get_icon_stock (entry,
2397 GTK_ENTRY_ICON_PRIMARY));
2400 case PROP_STOCK_SECONDARY:
2401 g_value_set_string (value,
2402 gtk_entry_get_icon_stock (entry,
2403 GTK_ENTRY_ICON_SECONDARY));
2406 case PROP_ICON_NAME_PRIMARY:
2407 g_value_set_string (value,
2408 gtk_entry_get_icon_name (entry,
2409 GTK_ENTRY_ICON_PRIMARY));
2412 case PROP_ICON_NAME_SECONDARY:
2413 g_value_set_string (value,
2414 gtk_entry_get_icon_name (entry,
2415 GTK_ENTRY_ICON_SECONDARY));
2418 case PROP_GICON_PRIMARY:
2419 g_value_set_object (value,
2420 gtk_entry_get_icon_gicon (entry,
2421 GTK_ENTRY_ICON_PRIMARY));
2424 case PROP_GICON_SECONDARY:
2425 g_value_set_object (value,
2426 gtk_entry_get_icon_gicon (entry,
2427 GTK_ENTRY_ICON_SECONDARY));
2430 case PROP_STORAGE_TYPE_PRIMARY:
2431 g_value_set_enum (value,
2432 gtk_entry_get_icon_storage_type (entry,
2433 GTK_ENTRY_ICON_PRIMARY));
2436 case PROP_STORAGE_TYPE_SECONDARY:
2437 g_value_set_enum (value,
2438 gtk_entry_get_icon_storage_type (entry,
2439 GTK_ENTRY_ICON_SECONDARY));
2442 case PROP_ACTIVATABLE_PRIMARY:
2443 g_value_set_boolean (value,
2444 gtk_entry_get_icon_activatable (entry, GTK_ENTRY_ICON_PRIMARY));
2447 case PROP_ACTIVATABLE_SECONDARY:
2448 g_value_set_boolean (value,
2449 gtk_entry_get_icon_activatable (entry, GTK_ENTRY_ICON_SECONDARY));
2452 case PROP_SENSITIVE_PRIMARY:
2453 g_value_set_boolean (value,
2454 gtk_entry_get_icon_sensitive (entry, GTK_ENTRY_ICON_PRIMARY));
2457 case PROP_SENSITIVE_SECONDARY:
2458 g_value_set_boolean (value,
2459 gtk_entry_get_icon_sensitive (entry, GTK_ENTRY_ICON_SECONDARY));
2462 case PROP_TOOLTIP_TEXT_PRIMARY:
2463 g_value_take_string (value,
2464 gtk_entry_get_icon_tooltip_text (entry, GTK_ENTRY_ICON_PRIMARY));
2467 case PROP_TOOLTIP_TEXT_SECONDARY:
2468 g_value_take_string (value,
2469 gtk_entry_get_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY));
2472 case PROP_TOOLTIP_MARKUP_PRIMARY:
2473 g_value_take_string (value,
2474 gtk_entry_get_icon_tooltip_markup (entry, GTK_ENTRY_ICON_PRIMARY));
2477 case PROP_TOOLTIP_MARKUP_SECONDARY:
2478 g_value_take_string (value,
2479 gtk_entry_get_icon_tooltip_markup (entry, GTK_ENTRY_ICON_SECONDARY));
2482 case PROP_EDITING_CANCELED:
2483 g_value_set_boolean (value,
2484 priv->editing_canceled);
2487 case PROP_COMPLETION:
2488 g_value_set_object (value, G_OBJECT (gtk_entry_get_completion (entry)));
2491 case PROP_INPUT_PURPOSE:
2492 g_value_set_enum (value, gtk_entry_get_input_purpose (entry));
2495 case PROP_INPUT_HINTS:
2496 g_value_set_flags (value, gtk_entry_get_input_hints (entry));
2499 case PROP_ATTRIBUTES:
2500 g_value_set_boxed (value, priv->attrs);
2503 case PROP_POPULATE_TOOLBAR:
2504 g_value_set_boolean (value, priv->populate_toolbar);
2508 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2514 find_invisible_char (GtkWidget *widget)
2516 PangoLayout *layout;
2517 PangoAttrList *attr_list;
2519 gunichar invisible_chars [] = {
2521 0x25cf, /* BLACK CIRCLE */
2522 0x2022, /* BULLET */
2523 0x2731, /* HEAVY ASTERISK */
2524 0x273a /* SIXTEEN POINTED ASTERISK */
2527 gtk_widget_style_get (widget,
2528 "invisible-char", &invisible_chars[0],
2531 layout = gtk_widget_create_pango_layout (widget, NULL);
2533 attr_list = pango_attr_list_new ();
2534 pango_attr_list_insert (attr_list, pango_attr_fallback_new (FALSE));
2536 pango_layout_set_attributes (layout, attr_list);
2537 pango_attr_list_unref (attr_list);
2539 for (i = (invisible_chars[0] != 0 ? 0 : 1); i < G_N_ELEMENTS (invisible_chars); i++)
2541 gchar text[7] = { 0, };
2544 len = g_unichar_to_utf8 (invisible_chars[i], text);
2545 pango_layout_set_text (layout, text, len);
2547 count = pango_layout_get_unknown_glyphs_count (layout);
2551 g_object_unref (layout);
2552 return invisible_chars[i];
2556 g_object_unref (layout);
2562 gtk_entry_init (GtkEntry *entry)
2564 GtkStyleContext *context;
2565 GtkEntryPrivate *priv;
2567 entry->priv = G_TYPE_INSTANCE_GET_PRIVATE (entry,
2572 gtk_widget_set_can_focus (GTK_WIDGET (entry), TRUE);
2573 gtk_widget_set_has_window (GTK_WIDGET (entry), FALSE);
2575 priv->editable = TRUE;
2576 priv->visible = TRUE;
2577 priv->dnd_position = -1;
2578 priv->width_chars = -1;
2579 priv->is_cell_renderer = FALSE;
2580 priv->editing_canceled = FALSE;
2581 priv->has_frame = TRUE;
2582 priv->truncate_multiline = FALSE;
2583 priv->shadow_type = GTK_SHADOW_IN;
2585 priv->caps_lock_warning = TRUE;
2586 priv->caps_lock_warning_shown = FALSE;
2587 priv->progress_fraction = 0.0;
2588 priv->progress_pulse_fraction = 0.1;
2590 gtk_drag_dest_set (GTK_WIDGET (entry),
2591 GTK_DEST_DEFAULT_HIGHLIGHT,
2593 GDK_ACTION_COPY | GDK_ACTION_MOVE);
2594 gtk_drag_dest_add_text_targets (GTK_WIDGET (entry));
2596 /* This object is completely private. No external entity can gain a reference
2597 * to it; so we create it here and destroy it in finalize().
2599 priv->im_context = gtk_im_multicontext_new ();
2601 g_signal_connect (priv->im_context, "commit",
2602 G_CALLBACK (gtk_entry_commit_cb), entry);
2603 g_signal_connect (priv->im_context, "preedit-changed",
2604 G_CALLBACK (gtk_entry_preedit_changed_cb), entry);
2605 g_signal_connect (priv->im_context, "retrieve-surrounding",
2606 G_CALLBACK (gtk_entry_retrieve_surrounding_cb), entry);
2607 g_signal_connect (priv->im_context, "delete-surrounding",
2608 G_CALLBACK (gtk_entry_delete_surrounding_cb), entry);
2610 context = gtk_widget_get_style_context (GTK_WIDGET (entry));
2611 gtk_style_context_add_class (context, GTK_STYLE_CLASS_ENTRY);
2613 gtk_entry_update_cached_style_values (entry);
2615 priv->text_handle = _gtk_text_handle_new (GTK_WIDGET (entry));
2616 g_signal_connect (priv->text_handle, "handle-dragged",
2617 G_CALLBACK (gtk_entry_handle_dragged), entry);
2618 g_signal_connect (priv->text_handle, "drag-finished",
2619 G_CALLBACK (gtk_entry_handle_drag_finished), entry);
2623 gtk_entry_prepare_context_for_icon (GtkEntry *entry,
2624 GtkStyleContext *context,
2625 GtkEntryIconPosition icon_pos)
2627 GtkEntryPrivate *priv = entry->priv;
2628 EntryIconInfo *icon_info = priv->icons[icon_pos];
2630 GtkStateFlags state;
2632 widget = GTK_WIDGET (entry);
2633 state = gtk_widget_get_state_flags (widget);
2635 state &= ~(GTK_STATE_FLAG_PRELIGHT);
2637 if ((state & GTK_STATE_FLAG_INSENSITIVE) || icon_info->insensitive)
2638 state |= GTK_STATE_FLAG_INSENSITIVE;
2639 else if (icon_info->prelight)
2640 state |= GTK_STATE_FLAG_PRELIGHT;
2642 gtk_style_context_save (context);
2644 gtk_style_context_set_state (context, state);
2645 gtk_style_context_add_class (context, GTK_STYLE_CLASS_IMAGE);
2647 if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
2649 if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
2650 gtk_style_context_add_class (context, GTK_STYLE_CLASS_RIGHT);
2652 gtk_style_context_add_class (context, GTK_STYLE_CLASS_LEFT);
2656 if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
2657 gtk_style_context_add_class (context, GTK_STYLE_CLASS_LEFT);
2659 gtk_style_context_add_class (context, GTK_STYLE_CLASS_RIGHT);
2664 get_icon_width (GtkEntry *entry,
2665 GtkEntryIconPosition icon_pos)
2667 GtkEntryPrivate *priv = entry->priv;
2668 EntryIconInfo *icon_info = priv->icons[icon_pos];
2669 GtkStyleContext *context;
2676 context = gtk_widget_get_style_context (GTK_WIDGET (entry));
2677 gtk_entry_prepare_context_for_icon (entry, context, icon_pos);
2678 gtk_style_context_get_padding (context, 0, &padding);
2680 _gtk_icon_helper_get_size (icon_info->icon_helper, context,
2682 gtk_style_context_restore (context);
2685 width += padding.left + padding.right;
2691 get_icon_allocations (GtkEntry *entry,
2692 GtkAllocation *primary,
2693 GtkAllocation *secondary)
2696 GtkEntryPrivate *priv = entry->priv;
2697 gint x, y, width, height;
2699 get_text_area_size (entry, &x, &y, &width, &height);
2701 if (gtk_widget_has_focus (GTK_WIDGET (entry)) && !priv->interior_focus)
2702 y += priv->focus_width;
2705 primary->height = height;
2706 primary->width = get_icon_width (entry, GTK_ENTRY_ICON_PRIMARY);
2709 secondary->height = height;
2710 secondary->width = get_icon_width (entry, GTK_ENTRY_ICON_SECONDARY);
2712 if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
2714 primary->x = x + width - primary->width;
2720 secondary->x = x + width - secondary->width;
2726 begin_change (GtkEntry *entry)
2728 GtkEntryPrivate *priv = entry->priv;
2730 priv->change_count++;
2732 g_object_freeze_notify (G_OBJECT (entry));
2736 end_change (GtkEntry *entry)
2738 GtkEditable *editable = GTK_EDITABLE (entry);
2739 GtkEntryPrivate *priv = entry->priv;
2741 g_return_if_fail (priv->change_count > 0);
2743 g_object_thaw_notify (G_OBJECT (entry));
2745 priv->change_count--;
2747 if (priv->change_count == 0)
2749 if (priv->real_changed)
2751 g_signal_emit_by_name (editable, "changed");
2752 priv->real_changed = FALSE;
2758 emit_changed (GtkEntry *entry)
2760 GtkEditable *editable = GTK_EDITABLE (entry);
2761 GtkEntryPrivate *priv = entry->priv;
2763 if (priv->change_count == 0)
2764 g_signal_emit_by_name (editable, "changed");
2766 priv->real_changed = TRUE;
2770 gtk_entry_destroy (GtkWidget *widget)
2772 GtkEntry *entry = GTK_ENTRY (widget);
2773 GtkEntryPrivate *priv = entry->priv;
2775 priv->current_pos = priv->selection_bound = 0;
2776 gtk_entry_reset_im_context (entry);
2777 gtk_entry_reset_layout (entry);
2779 if (priv->blink_timeout)
2781 g_source_remove (priv->blink_timeout);
2782 priv->blink_timeout = 0;
2785 if (priv->recompute_idle)
2787 g_source_remove (priv->recompute_idle);
2788 priv->recompute_idle = 0;
2791 GTK_WIDGET_CLASS (gtk_entry_parent_class)->destroy (widget);
2795 gtk_entry_dispose (GObject *object)
2797 GtkEntry *entry = GTK_ENTRY (object);
2798 GtkEntryPrivate *priv = entry->priv;
2801 gtk_entry_set_icon_from_pixbuf (entry, GTK_ENTRY_ICON_PRIMARY, NULL);
2802 gtk_entry_set_icon_tooltip_markup (entry, GTK_ENTRY_ICON_PRIMARY, NULL);
2803 gtk_entry_set_icon_from_pixbuf (entry, GTK_ENTRY_ICON_SECONDARY, NULL);
2804 gtk_entry_set_icon_tooltip_markup (entry, GTK_ENTRY_ICON_SECONDARY, NULL);
2805 gtk_entry_set_completion (entry, NULL);
2809 buffer_disconnect_signals (entry);
2810 g_object_unref (priv->buffer);
2811 priv->buffer = NULL;
2814 keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (object)));
2815 g_signal_handlers_disconnect_by_func (keymap, keymap_state_changed, entry);
2816 g_signal_handlers_disconnect_by_func (keymap, keymap_direction_changed, entry);
2817 G_OBJECT_CLASS (gtk_entry_parent_class)->dispose (object);
2821 gtk_entry_finalize (GObject *object)
2823 GtkEntry *entry = GTK_ENTRY (object);
2824 GtkEntryPrivate *priv = entry->priv;
2825 EntryIconInfo *icon_info = NULL;
2828 for (i = 0; i < MAX_ICONS; i++)
2830 if ((icon_info = priv->icons[i]) != NULL)
2832 if (icon_info->target_list != NULL)
2834 gtk_target_list_unref (icon_info->target_list);
2835 icon_info->target_list = NULL;
2838 g_clear_object (&icon_info->icon_helper);
2840 g_slice_free (EntryIconInfo, icon_info);
2841 priv->icons[i] = NULL;
2845 if (priv->cached_layout)
2846 g_object_unref (priv->cached_layout);
2848 g_object_unref (priv->im_context);
2850 if (priv->blink_timeout)
2851 g_source_remove (priv->blink_timeout);
2853 if (priv->recompute_idle)
2854 g_source_remove (priv->recompute_idle);
2856 if (priv->selection_bubble)
2857 gtk_widget_destroy (priv->selection_bubble);
2859 g_object_unref (priv->text_handle);
2860 g_free (priv->placeholder_text);
2861 g_free (priv->im_module);
2863 G_OBJECT_CLASS (gtk_entry_parent_class)->finalize (object);
2867 gtk_entry_get_display_mode (GtkEntry *entry)
2869 GtkEntryPrivate *priv = entry->priv;
2872 return DISPLAY_NORMAL;
2874 if (priv->invisible_char == 0 && priv->invisible_char_set)
2875 return DISPLAY_BLANK;
2877 return DISPLAY_INVISIBLE;
2881 _gtk_entry_get_display_text (GtkEntry *entry,
2885 GtkEntryPasswordHint *password_hint;
2886 GtkEntryPrivate *priv;
2887 gunichar invisible_char;
2898 text = gtk_entry_buffer_get_text (get_buffer (entry));
2899 length = gtk_entry_buffer_get_length (get_buffer (entry));
2903 if (start_pos > length)
2906 if (end_pos <= start_pos)
2907 return g_strdup ("");
2908 else if (priv->visible)
2910 start = g_utf8_offset_to_pointer (text, start_pos);
2911 end = g_utf8_offset_to_pointer (start, end_pos - start_pos);
2912 return g_strndup (start, end - start);
2916 str = g_string_sized_new (length * 2);
2918 /* Figure out what our invisible char is and encode it */
2919 if (!priv->invisible_char)
2920 invisible_char = priv->invisible_char_set ? ' ' : '*';
2922 invisible_char = priv->invisible_char;
2923 char_len = g_unichar_to_utf8 (invisible_char, char_str);
2926 * Add hidden characters for each character in the text
2927 * buffer. If there is a password hint, then keep that
2928 * character visible.
2931 password_hint = g_object_get_qdata (G_OBJECT (entry), quark_password_hint);
2932 for (i = start_pos; i < end_pos; ++i)
2934 if (password_hint && i == password_hint->position)
2936 start = g_utf8_offset_to_pointer (text, i);
2937 g_string_append_len (str, start, g_utf8_next_char (start) - start);
2941 g_string_append_len (str, char_str, char_len);
2945 return g_string_free (str, FALSE);
2950 update_cursors (GtkWidget *widget)
2952 GtkEntry *entry = GTK_ENTRY (widget);
2953 GtkEntryPrivate *priv = entry->priv;
2954 EntryIconInfo *icon_info = NULL;
2955 GdkDisplay *display;
2959 for (i = 0; i < MAX_ICONS; i++)
2961 if ((icon_info = priv->icons[i]) != NULL)
2963 if (!_gtk_icon_helper_get_is_empty (icon_info->icon_helper) &&
2964 icon_info->window != NULL)
2965 gdk_window_show_unraised (icon_info->window);
2967 /* The icon windows are not children of the visible entry window,
2968 * thus we can't just inherit the xterm cursor. Slight complication
2969 * here is that for the entry, insensitive => arrow cursor, but for
2970 * an icon in a sensitive entry, insensitive => xterm cursor.
2972 if (gtk_widget_is_sensitive (widget) &&
2973 (icon_info->insensitive ||
2974 (icon_info->nonactivatable && icon_info->target_list == NULL)))
2976 display = gtk_widget_get_display (widget);
2977 cursor = gdk_cursor_new_for_display (display, GDK_XTERM);
2978 gdk_window_set_cursor (icon_info->window, cursor);
2979 g_object_unref (cursor);
2983 gdk_window_set_cursor (icon_info->window, NULL);
2990 realize_icon_info (GtkWidget *widget,
2991 GtkEntryIconPosition icon_pos)
2993 GtkEntry *entry = GTK_ENTRY (widget);
2994 GtkEntryPrivate *priv = entry->priv;
2995 EntryIconInfo *icon_info = priv->icons[icon_pos];
2996 GdkWindowAttr attributes;
2997 gint attributes_mask;
2999 g_return_if_fail (icon_info != NULL);
3003 attributes.width = 1;
3004 attributes.height = 1;
3005 attributes.window_type = GDK_WINDOW_CHILD;
3006 attributes.wclass = GDK_INPUT_ONLY;
3007 attributes.event_mask = gtk_widget_get_events (widget);
3008 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
3009 GDK_BUTTON_RELEASE_MASK |
3010 GDK_BUTTON1_MOTION_MASK |
3011 GDK_BUTTON3_MOTION_MASK |
3012 GDK_POINTER_MOTION_HINT_MASK |
3013 GDK_POINTER_MOTION_MASK |
3014 GDK_ENTER_NOTIFY_MASK |
3015 GDK_LEAVE_NOTIFY_MASK);
3016 attributes_mask = GDK_WA_X | GDK_WA_Y;
3018 icon_info->window = gdk_window_new (gtk_widget_get_window (widget),
3021 gtk_widget_register_window (widget, icon_info->window);
3023 gtk_widget_queue_resize (widget);
3026 static EntryIconInfo*
3027 construct_icon_info (GtkWidget *widget,
3028 GtkEntryIconPosition icon_pos)
3030 GtkEntry *entry = GTK_ENTRY (widget);
3031 GtkEntryPrivate *priv = entry->priv;
3032 EntryIconInfo *icon_info;
3034 g_return_val_if_fail (priv->icons[icon_pos] == NULL, NULL);
3036 icon_info = g_slice_new0 (EntryIconInfo);
3037 priv->icons[icon_pos] = icon_info;
3039 icon_info->icon_helper = _gtk_icon_helper_new ();
3040 _gtk_icon_helper_set_force_scale_pixbuf (icon_info->icon_helper, TRUE);
3042 if (gtk_widget_get_realized (widget))
3043 realize_icon_info (widget, icon_pos);
3049 gtk_entry_map (GtkWidget *widget)
3051 GtkEntry *entry = GTK_ENTRY (widget);
3052 GtkEntryPrivate *priv = entry->priv;
3053 EntryIconInfo *icon_info = NULL;
3056 GTK_WIDGET_CLASS (gtk_entry_parent_class)->map (widget);
3058 gdk_window_show (priv->text_area);
3060 for (i = 0; i < MAX_ICONS; i++)
3062 if ((icon_info = priv->icons[i]) != NULL)
3064 if (!_gtk_icon_helper_get_is_empty (icon_info->icon_helper) &&
3065 icon_info->window != NULL)
3066 gdk_window_show (icon_info->window);
3070 update_cursors (widget);
3074 gtk_entry_unmap (GtkWidget *widget)
3076 GtkEntry *entry = GTK_ENTRY (widget);
3077 GtkEntryPrivate *priv = entry->priv;
3078 EntryIconInfo *icon_info = NULL;
3081 _gtk_text_handle_set_mode (priv->text_handle,
3082 GTK_TEXT_HANDLE_MODE_NONE);
3084 for (i = 0; i < MAX_ICONS; i++)
3086 if ((icon_info = priv->icons[i]) != NULL)
3088 if (!_gtk_icon_helper_get_is_empty (icon_info->icon_helper) &&
3089 icon_info->window != NULL)
3090 gdk_window_hide (icon_info->window);
3094 gdk_window_hide (priv->text_area);
3096 GTK_WIDGET_CLASS (gtk_entry_parent_class)->unmap (widget);
3100 gtk_entry_realize (GtkWidget *widget)
3103 GtkEntryPrivate *priv;
3104 EntryIconInfo *icon_info;
3106 GdkWindowAttr attributes;
3107 gint attributes_mask;
3108 gint frame_x, frame_y;
3111 gtk_widget_set_realized (widget, TRUE);
3112 window = gtk_widget_get_parent_window (widget);
3113 gtk_widget_set_window (widget, window);
3114 g_object_ref (window);
3116 entry = GTK_ENTRY (widget);
3119 attributes.window_type = GDK_WINDOW_CHILD;
3120 attributes.wclass = GDK_INPUT_ONLY;
3121 attributes.event_mask = gtk_widget_get_events (widget);
3122 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
3123 GDK_BUTTON_RELEASE_MASK |
3124 GDK_BUTTON1_MOTION_MASK |
3125 GDK_BUTTON3_MOTION_MASK |
3126 GDK_POINTER_MOTION_HINT_MASK |
3127 GDK_POINTER_MOTION_MASK |
3128 GDK_ENTER_NOTIFY_MASK |
3129 GDK_LEAVE_NOTIFY_MASK);
3130 attributes_mask = GDK_WA_X | GDK_WA_Y;
3132 get_text_area_size (entry, &attributes.x, &attributes.y, &attributes.width, &attributes.height);
3134 get_frame_size (entry, TRUE, &frame_x, &frame_y, NULL, NULL);
3135 attributes.x += frame_x;
3136 attributes.y += frame_y;
3138 if (gtk_widget_is_sensitive (widget))
3140 attributes.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), GDK_XTERM);
3141 attributes_mask |= GDK_WA_CURSOR;
3144 priv->text_area = gdk_window_new (gtk_widget_get_window (widget),
3148 gtk_widget_register_window (widget, priv->text_area);
3150 if (attributes_mask & GDK_WA_CURSOR)
3151 g_object_unref (attributes.cursor);
3153 gtk_im_context_set_client_window (priv->im_context, priv->text_area);
3155 gtk_entry_adjust_scroll (entry);
3156 gtk_entry_update_primary_selection (entry);
3157 _gtk_text_handle_set_relative_to (priv->text_handle, priv->text_area);
3159 /* If the icon positions are already setup, create their windows.
3160 * Otherwise if they don't exist yet, then construct_icon_info()
3161 * will create the windows once the widget is already realized.
3163 for (i = 0; i < MAX_ICONS; i++)
3165 if ((icon_info = priv->icons[i]) != NULL)
3167 if (icon_info->window == NULL)
3168 realize_icon_info (widget, i);
3174 gtk_entry_unrealize (GtkWidget *widget)
3176 GtkEntry *entry = GTK_ENTRY (widget);
3177 GtkEntryPrivate *priv = entry->priv;
3178 GtkClipboard *clipboard;
3179 EntryIconInfo *icon_info;
3182 gtk_entry_reset_layout (entry);
3184 gtk_im_context_set_client_window (priv->im_context, NULL);
3185 _gtk_text_handle_set_relative_to (priv->text_handle, NULL);
3187 clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_PRIMARY);
3188 if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (entry))
3189 gtk_clipboard_clear (clipboard);
3191 if (priv->text_area)
3193 gtk_widget_unregister_window (widget, priv->text_area);
3194 gdk_window_destroy (priv->text_area);
3195 priv->text_area = NULL;
3198 if (priv->popup_menu)
3200 gtk_widget_destroy (priv->popup_menu);
3201 priv->popup_menu = NULL;
3204 GTK_WIDGET_CLASS (gtk_entry_parent_class)->unrealize (widget);
3206 for (i = 0; i < MAX_ICONS; i++)
3208 if ((icon_info = priv->icons[i]) != NULL)
3210 if (icon_info->window != NULL)
3212 gtk_widget_unregister_window (widget, icon_info->window);
3213 gdk_window_destroy (icon_info->window);
3214 icon_info->window = NULL;
3221 _gtk_entry_get_borders (GtkEntry *entry,
3222 GtkBorder *border_out)
3224 GtkEntryPrivate *priv = entry->priv;
3225 GtkWidget *widget = GTK_WIDGET (entry);
3226 GtkBorder tmp = { 0, 0, 0, 0 };
3227 GtkStyleContext *context;
3229 context = gtk_widget_get_style_context (widget);
3230 gtk_style_context_get_padding (context, 0, &tmp);
3232 if (priv->has_frame)
3236 gtk_style_context_get_border (context, 0, &border);
3237 tmp.top += border.top;
3238 tmp.right += border.right;
3239 tmp.bottom += border.bottom;
3240 tmp.left += border.left;
3243 if (!priv->interior_focus)
3245 tmp.top += priv->focus_width;
3246 tmp.right += priv->focus_width;
3247 tmp.bottom += priv->focus_width;
3248 tmp.left += priv->focus_width;
3251 if (border_out != NULL)
3256 gtk_entry_get_preferred_width (GtkWidget *widget,
3260 GtkEntry *entry = GTK_ENTRY (widget);
3261 GtkEntryPrivate *priv = entry->priv;
3262 PangoFontMetrics *metrics;
3264 PangoContext *context;
3265 gint icon_widths = 0;
3269 context = gtk_widget_get_pango_context (widget);
3271 metrics = pango_context_get_metrics (context,
3272 pango_context_get_font_description (context),
3273 pango_context_get_language (context));
3275 _gtk_entry_get_borders (entry, &borders);
3277 if (priv->width_chars < 0)
3278 width = MIN_ENTRY_WIDTH + borders.left + borders.right;
3281 gint char_width = pango_font_metrics_get_approximate_char_width (metrics);
3282 gint digit_width = pango_font_metrics_get_approximate_digit_width (metrics);
3283 gint char_pixels = (MAX (char_width, digit_width) + PANGO_SCALE - 1) / PANGO_SCALE;
3285 width = char_pixels * priv->width_chars + borders.left + borders.right;
3288 for (i = 0; i < MAX_ICONS; i++)
3290 icon_width = get_icon_width (entry, i);
3292 icon_widths += icon_width;
3295 if (icon_widths > width)
3296 width += icon_widths;
3298 pango_font_metrics_unref (metrics);
3305 gtk_entry_get_preferred_height (GtkWidget *widget,
3309 GtkEntry *entry = GTK_ENTRY (widget);
3310 GtkEntryPrivate *priv = entry->priv;
3311 PangoFontMetrics *metrics;
3313 PangoContext *context;
3315 PangoLayout *layout;
3317 layout = gtk_entry_ensure_layout (entry, TRUE);
3318 context = gtk_widget_get_pango_context (widget);
3320 metrics = pango_context_get_metrics (context,
3321 pango_context_get_font_description (context),
3322 pango_context_get_language (context));
3324 priv->ascent = pango_font_metrics_get_ascent (metrics);
3325 priv->descent = pango_font_metrics_get_descent (metrics);
3326 pango_font_metrics_unref (metrics);
3328 _gtk_entry_get_borders (entry, &borders);
3329 pango_layout_get_pixel_size (layout, NULL, &height);
3331 height += borders.top + borders.bottom;
3338 place_windows (GtkEntry *entry)
3340 GtkWidget *widget = GTK_WIDGET (entry);
3341 GtkEntryPrivate *priv = entry->priv;
3342 gint x, y, width, height;
3343 gint frame_x, frame_y;
3344 GtkAllocation primary;
3345 GtkAllocation secondary;
3346 EntryIconInfo *icon_info = NULL;
3348 get_frame_size (entry, TRUE, &frame_x, &frame_y, NULL, NULL);
3349 get_text_area_size (entry, &x, &y, &width, &height);
3350 get_icon_allocations (entry, &primary, &secondary);
3352 if (gtk_widget_has_focus (widget) && !priv->interior_focus)
3353 y += priv->focus_width;
3355 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
3356 x += secondary.width;
3359 width -= primary.width + secondary.width;
3363 primary.x += frame_x;
3364 primary.y += frame_y;
3365 secondary.x += frame_x;
3366 secondary.y += frame_y;
3368 if ((icon_info = priv->icons[GTK_ENTRY_ICON_PRIMARY]) != NULL)
3369 gdk_window_move_resize (icon_info->window,
3370 primary.x, primary.y,
3371 primary.width, primary.height);
3373 if ((icon_info = priv->icons[GTK_ENTRY_ICON_SECONDARY]) != NULL)
3374 gdk_window_move_resize (icon_info->window,
3375 secondary.x, secondary.y,
3376 secondary.width, secondary.height);
3378 gdk_window_move_resize (priv->text_area, x, y, width, height);
3382 gtk_entry_get_text_area_size (GtkEntry *entry,
3388 GtkEntryPrivate *priv = entry->priv;
3389 GtkWidget *widget = GTK_WIDGET (entry);
3390 GtkAllocation allocation;
3391 GtkRequisition requisition;
3396 gtk_widget_get_preferred_size (widget, &requisition, NULL);
3397 req_height = requisition.height - gtk_widget_get_margin_top (widget) - gtk_widget_get_margin_bottom (widget);
3399 gtk_widget_get_allocation (widget, &allocation);
3400 _gtk_entry_get_borders (entry, &borders);
3402 if (gtk_widget_get_realized (widget))
3403 get_frame_size (entry, TRUE, NULL, NULL, NULL, &frame_height);
3405 frame_height = req_height;
3407 if (gtk_widget_has_focus (widget) && !priv->interior_focus)
3408 frame_height -= 2 * priv->focus_width;
3414 *y = floor ((frame_height - req_height) / 2) + borders.top;
3417 *width = allocation.width - borders.left - borders.right;
3420 *height = req_height - borders.top - borders.bottom;
3424 get_text_area_size (GtkEntry *entry,
3430 GtkEntryClass *class;
3432 g_return_if_fail (GTK_IS_ENTRY (entry));
3434 class = GTK_ENTRY_GET_CLASS (entry);
3436 if (class->get_text_area_size)
3437 class->get_text_area_size (entry, x, y, width, height);
3442 gtk_entry_get_frame_size (GtkEntry *entry,
3448 GtkEntryPrivate *priv = entry->priv;
3449 GtkAllocation allocation;
3450 GtkRequisition requisition;
3451 GtkWidget *widget = GTK_WIDGET (entry);
3454 gtk_widget_get_preferred_size (widget, &requisition, NULL);
3456 req_height = requisition.height - gtk_widget_get_margin_top (widget) - gtk_widget_get_margin_bottom (widget);
3458 gtk_widget_get_allocation (widget, &allocation);
3465 if (priv->is_cell_renderer)
3468 *y = (allocation.height - req_height) / 2;
3474 *width = allocation.width;
3478 if (priv->is_cell_renderer)
3479 *height = allocation.height;
3481 *height = req_height;
3486 get_frame_size (GtkEntry *entry,
3487 gboolean relative_to_window,
3493 GtkEntryClass *class;
3494 GtkWidget *widget = GTK_WIDGET (entry);
3496 g_return_if_fail (GTK_IS_ENTRY (entry));
3498 class = GTK_ENTRY_GET_CLASS (entry);
3500 if (class->get_frame_size)
3501 class->get_frame_size (entry, x, y, width, height);
3503 if (!relative_to_window)
3505 GtkAllocation allocation;
3506 gtk_widget_get_allocation (widget, &allocation);
3516 gtk_entry_size_allocate (GtkWidget *widget,
3517 GtkAllocation *allocation)
3519 GtkEntry *entry = GTK_ENTRY (widget);
3521 gtk_widget_set_allocation (widget, allocation);
3523 if (gtk_widget_get_realized (widget))
3525 GtkEntryCompletion* completion;
3527 place_windows (entry);
3528 gtk_entry_recompute (entry);
3530 completion = gtk_entry_get_completion (entry);
3532 _gtk_entry_completion_resize_popup (completion);
3537 should_prelight (GtkEntry *entry,
3538 GtkEntryIconPosition icon_pos)
3540 GtkEntryPrivate *priv = entry->priv;
3541 EntryIconInfo *icon_info = priv->icons[icon_pos];
3547 if (icon_info->nonactivatable && icon_info->target_list == NULL)
3550 if (icon_info->pressed)
3553 gtk_widget_style_get (GTK_WIDGET (entry),
3554 "icon-prelight", &prelight,
3561 draw_icon (GtkWidget *widget,
3563 GtkEntryIconPosition icon_pos)
3565 GtkEntry *entry = GTK_ENTRY (widget);
3566 GtkEntryPrivate *priv = entry->priv;
3567 EntryIconInfo *icon_info = priv->icons[icon_pos];
3568 gint x, y, width, height, pix_width, pix_height;
3569 GtkStyleContext *context;
3575 width = gdk_window_get_width (icon_info->window);
3576 height = gdk_window_get_height (icon_info->window);
3578 /* size_allocate hasn't been called yet. These are the default values.
3580 if (width == 1 || height == 1)
3584 gtk_cairo_transform_to_window (cr, widget, icon_info->window);
3586 context = gtk_widget_get_style_context (widget);
3587 gtk_entry_prepare_context_for_icon (entry, context, icon_pos);
3588 _gtk_icon_helper_get_size (icon_info->icon_helper, context,
3589 &pix_width, &pix_height);
3590 gtk_style_context_get_padding (context, 0, &padding);
3592 x = MAX (0, padding.left);
3593 y = MAX (0, (height - pix_height) / 2);
3595 _gtk_icon_helper_draw (icon_info->icon_helper,
3599 gtk_style_context_restore (context);
3605 gtk_entry_draw_frame (GtkWidget *widget,
3606 GtkStyleContext *context,
3609 GtkEntry *entry = GTK_ENTRY (widget);
3610 GtkEntryPrivate *priv = entry->priv;
3611 gint x = 0, y = 0, width, height;
3612 gint frame_x, frame_y;
3616 get_frame_size (GTK_ENTRY (widget), FALSE, &frame_x, &frame_y, &width, &height);
3618 cairo_translate (cr, frame_x, frame_y);
3620 /* Fix a problem with some themes which assume that entry->text_area's
3621 * width equals widget->window's width
3622 * http://bugzilla.gnome.org/show_bug.cgi?id=466000 */
3623 if (GTK_IS_SPIN_BUTTON (widget))
3627 gtk_entry_get_text_area_size (GTK_ENTRY (widget), &x, NULL, &width, NULL);
3628 _gtk_entry_get_borders (GTK_ENTRY (widget), &borders);
3631 width += borders.left + borders.right;
3634 if (gtk_widget_has_focus (widget) && !priv->interior_focus)
3636 x += priv->focus_width;
3637 y += priv->focus_width;
3638 width -= 2 * priv->focus_width;
3639 height -= 2 * priv->focus_width;
3642 gtk_render_background (context, cr,
3643 x, y, width, height);
3645 if (priv->has_frame)
3646 gtk_render_frame (context, cr,
3647 x, y, width, height);
3649 gtk_entry_draw_progress (widget, context, cr);
3651 if (gtk_widget_has_visible_focus (widget) && !priv->interior_focus)
3653 x -= priv->focus_width;
3654 y -= priv->focus_width;
3655 width += 2 * priv->focus_width;
3656 height += 2 * priv->focus_width;
3658 gtk_render_focus (context, cr,
3659 0, 0, width, height);
3666 gtk_entry_prepare_context_for_progress (GtkEntry *entry,
3667 GtkStyleContext *context)
3669 GtkEntryPrivate *private = entry->priv;
3671 gtk_style_context_save (context);
3672 gtk_style_context_add_class (context, GTK_STYLE_CLASS_PROGRESSBAR);
3673 if (private->progress_pulse_mode)
3674 gtk_style_context_add_class (context, GTK_STYLE_CLASS_PULSE);
3678 get_progress_area (GtkWidget *widget,
3684 GtkEntry *entry = GTK_ENTRY (widget);
3685 GtkEntryPrivate *private = entry->priv;
3686 GtkStyleContext *context;
3687 GtkBorder margin, border, entry_borders;
3688 gint frame_width, text_area_width, text_area_height;
3690 context = gtk_widget_get_style_context (widget);
3691 _gtk_entry_get_borders (entry, &entry_borders);
3692 get_text_area_size (entry,
3694 &text_area_width, &text_area_height);
3695 get_frame_size (entry, FALSE,
3697 &frame_width, NULL);
3701 *width = text_area_width + entry_borders.left + entry_borders.right;
3702 *height = text_area_height + entry_borders.top + entry_borders.bottom;
3704 /* if the text area got resized by a subclass, subtract the left/right
3705 * border width, so that the progress bar won't extend over the resized
3708 if (frame_width > *width)
3710 gtk_style_context_get_border (context, 0, &border);
3711 if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
3713 *x = (frame_width - *width) + border.left;
3714 *width -= border.left;
3718 *width -= border.right;
3722 gtk_entry_prepare_context_for_progress (entry, context);
3723 gtk_style_context_get_margin (context, 0, &margin);
3725 gtk_style_context_restore (context);
3729 *width -= margin.left + margin.right;
3730 *height -= margin.top + margin.bottom;
3732 if (private->progress_pulse_mode)
3734 gdouble value = private->progress_pulse_current;
3736 *x += (gint) floor(value * (*width));
3737 *width = (gint) ceil(private->progress_pulse_fraction * (*width));
3739 else if (private->progress_fraction > 0)
3741 gdouble value = private->progress_fraction;
3743 if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
3747 bar_width = floor(value * (*width) + 0.5);
3748 *x += *width - bar_width;
3753 *width = (gint) floor(value * (*width) + 0.5);
3764 gtk_entry_draw_progress (GtkWidget *widget,
3765 GtkStyleContext *context,
3768 GtkEntry *entry = GTK_ENTRY (widget);
3769 gint x, y, width, height;
3771 get_progress_area (widget, &x, &y, &width, &height);
3773 if ((width <= 0) || (height <= 0))
3776 gtk_entry_prepare_context_for_progress (entry, context);
3777 gtk_render_activity (context, cr,
3778 x, y, width, height);
3780 gtk_style_context_restore (context);
3784 gtk_entry_draw (GtkWidget *widget,
3787 GtkEntry *entry = GTK_ENTRY (widget);
3788 GtkStyleContext *context;
3789 GtkEntryPrivate *priv = entry->priv;
3792 if (gtk_cairo_should_draw_window (cr,
3793 gtk_widget_get_window (widget)))
3795 context = gtk_widget_get_style_context (widget);
3797 /* Draw entry_bg, shadow, progress and focus */
3798 gtk_entry_draw_frame (widget, context, cr);
3800 /* Draw text and cursor */
3803 gtk_cairo_transform_to_window (cr, widget, priv->text_area);
3805 if (priv->dnd_position != -1)
3806 gtk_entry_draw_cursor (GTK_ENTRY (widget), cr, CURSOR_DND);
3808 gtk_entry_draw_text (GTK_ENTRY (widget), cr);
3810 /* When no text is being displayed at all, don't show the cursor */
3811 if (gtk_entry_get_display_mode (entry) != DISPLAY_BLANK &&
3812 gtk_widget_has_focus (widget) &&
3813 priv->selection_bound == priv->current_pos && priv->cursor_visible)
3814 gtk_entry_draw_cursor (GTK_ENTRY (widget), cr, CURSOR_STANDARD);
3819 for (i = 0; i < MAX_ICONS; i++)
3821 EntryIconInfo *icon_info = priv->icons[i];
3823 if (icon_info != NULL)
3824 draw_icon (widget, cr, i);
3832 gtk_entry_enter_notify (GtkWidget *widget,
3833 GdkEventCrossing *event)
3835 GtkEntry *entry = GTK_ENTRY (widget);
3836 GtkEntryPrivate *priv = entry->priv;
3839 for (i = 0; i < MAX_ICONS; i++)
3841 EntryIconInfo *icon_info = priv->icons[i];
3843 if (icon_info != NULL && event->window == icon_info->window)
3845 if (should_prelight (entry, i))
3847 icon_info->prelight = TRUE;
3848 gtk_widget_queue_draw (widget);
3859 gtk_entry_leave_notify (GtkWidget *widget,
3860 GdkEventCrossing *event)
3862 GtkEntry *entry = GTK_ENTRY (widget);
3863 GtkEntryPrivate *priv = entry->priv;
3866 for (i = 0; i < MAX_ICONS; i++)
3868 EntryIconInfo *icon_info = priv->icons[i];
3870 if (icon_info != NULL && event->window == icon_info->window)
3872 /* a grab means that we may never see the button release */
3873 if (event->mode == GDK_CROSSING_GRAB || event->mode == GDK_CROSSING_GTK_GRAB)
3874 icon_info->pressed = FALSE;
3876 if (should_prelight (entry, i))
3878 icon_info->prelight = FALSE;
3879 gtk_widget_queue_draw (widget);
3890 gtk_entry_get_pixel_ranges (GtkEntry *entry,
3894 gint start_char, end_char;
3896 if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_char, &end_char))
3898 PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
3899 PangoLayoutLine *line = pango_layout_get_lines_readonly (layout)->data;
3900 const char *text = pango_layout_get_text (layout);
3901 gint start_index = g_utf8_offset_to_pointer (text, start_char) - text;
3902 gint end_index = g_utf8_offset_to_pointer (text, end_char) - text;
3903 gint real_n_ranges, i;
3905 pango_layout_line_get_x_ranges (line, start_index, end_index, ranges, &real_n_ranges);
3911 for (i = 0; i < real_n_ranges; ++i)
3913 r[2 * i + 1] = (r[2 * i + 1] - r[2 * i]) / PANGO_SCALE;
3914 r[2 * i] = r[2 * i] / PANGO_SCALE;
3919 *n_ranges = real_n_ranges;
3931 in_selection (GtkEntry *entry,
3936 gint retval = FALSE;
3938 gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges);
3940 for (i = 0; i < n_ranges; ++i)
3942 if (x >= ranges[2 * i] && x < ranges[2 * i] + ranges[2 * i + 1])
3954 gtk_entry_move_handle (GtkEntry *entry,
3955 GtkTextHandlePosition pos,
3960 GtkEntryPrivate *priv = entry->priv;
3962 if (!_gtk_text_handle_get_is_dragged (priv->text_handle, pos) &&
3963 (x < 0 || x > gdk_window_get_width (priv->text_area)))
3965 /* Hide the handle if it's not being manipulated
3966 * and fell outside of the visible text area.
3968 _gtk_text_handle_set_visible (priv->text_handle, pos, FALSE);
3974 rect.x = CLAMP (x, 0, gdk_window_get_width (priv->text_area));
3977 rect.height = height;
3979 _gtk_text_handle_set_visible (priv->text_handle, pos, TRUE);
3980 _gtk_text_handle_set_position (priv->text_handle, pos, &rect);
3985 gtk_entry_get_selection_bound_location (GtkEntry *entry)
3987 GtkEntryPrivate *priv = entry->priv;
3988 PangoLayout *layout;
3994 layout = gtk_entry_ensure_layout (entry, FALSE);
3995 text = pango_layout_get_text (layout);
3996 index = g_utf8_offset_to_pointer (text, priv->selection_bound) - text;
3997 pango_layout_index_to_pos (layout, index, &pos);
3999 if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
4000 x = (pos.x + pos.width) / PANGO_SCALE;
4002 x = pos.x / PANGO_SCALE;
4008 gtk_entry_update_handles (GtkEntry *entry,
4009 GtkTextHandleMode mode)
4011 GtkEntryPrivate *priv = entry->priv;
4012 gint strong_x, height;
4015 _gtk_text_handle_set_mode (priv->text_handle, mode);
4017 /* Wait for recomputation before repositioning */
4018 if (priv->recompute_idle != 0)
4021 height = gdk_window_get_height (priv->text_area);
4023 gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &strong_x, NULL);
4024 cursor = strong_x - priv->scroll_offset;
4026 if (mode == GTK_TEXT_HANDLE_MODE_SELECTION)
4030 bound = gtk_entry_get_selection_bound_location (entry) - priv->scroll_offset;
4032 if (priv->selection_bound > priv->current_pos)
4043 /* Update start selection bound */
4044 gtk_entry_move_handle (entry, GTK_TEXT_HANDLE_POSITION_SELECTION_START,
4046 gtk_entry_move_handle (entry, GTK_TEXT_HANDLE_POSITION_SELECTION_END,
4050 gtk_entry_move_handle (entry, GTK_TEXT_HANDLE_POSITION_CURSOR,
4055 gtk_entry_button_press (GtkWidget *widget,
4056 GdkEventButton *event)
4058 GtkEntry *entry = GTK_ENTRY (widget);
4059 GtkEditable *editable = GTK_EDITABLE (widget);
4060 GtkEntryPrivate *priv = entry->priv;
4061 EntryIconInfo *icon_info = NULL;
4063 gint sel_start, sel_end;
4066 gtk_entry_selection_bubble_popup_unset (entry);
4068 for (i = 0; i < MAX_ICONS; i++)
4070 icon_info = priv->icons[i];
4072 if (!icon_info || icon_info->insensitive)
4075 if (event->window == icon_info->window)
4077 if (should_prelight (entry, i))
4079 icon_info->prelight = FALSE;
4080 gtk_widget_queue_draw (widget);
4083 priv->start_x = event->x;
4084 priv->start_y = event->y;
4085 icon_info->pressed = TRUE;
4087 if (!icon_info->nonactivatable)
4088 g_signal_emit (entry, signals[ICON_PRESS], 0, i, event);
4094 if (event->window != priv->text_area ||
4095 (priv->button && event->button != priv->button))
4098 gtk_entry_reset_blink_time (entry);
4100 priv->button = event->button;
4101 priv->device = gdk_event_get_device ((GdkEvent *) event);
4103 if (!gtk_widget_has_focus (widget))
4105 priv->in_click = TRUE;
4106 gtk_widget_grab_focus (widget);
4107 priv->in_click = FALSE;
4110 tmp_pos = gtk_entry_find_position (entry, event->x + priv->scroll_offset);
4112 if (gdk_event_triggers_context_menu ((GdkEvent *) event))
4114 gtk_entry_do_popup (entry, event);
4115 priv->button = 0; /* Don't wait for release, since the menu will gtk_grab_add */
4116 priv->device = NULL;
4120 else if (event->button == GDK_BUTTON_PRIMARY)
4122 gboolean have_selection = gtk_editable_get_selection_bounds (editable, &sel_start, &sel_end);
4123 gboolean is_touchscreen;
4126 source = gdk_event_get_source_device ((GdkEvent *) event);
4127 is_touchscreen = test_touchscreen ||
4128 gdk_device_get_source (source) == GDK_SOURCE_TOUCHSCREEN;
4130 priv->select_words = FALSE;
4131 priv->select_lines = FALSE;
4134 gtk_widget_get_modifier_mask (widget,
4135 GDK_MODIFIER_INTENT_EXTEND_SELECTION))
4137 gtk_entry_reset_im_context (entry);
4139 if (!have_selection) /* select from the current position to the clicked position */
4140 sel_start = sel_end = priv->current_pos;
4142 if (tmp_pos > sel_start && tmp_pos < sel_end)
4144 /* Truncate current selection, but keep it as big as possible */
4145 if (tmp_pos - sel_start > sel_end - tmp_pos)
4146 gtk_entry_set_positions (entry, sel_start, tmp_pos);
4148 gtk_entry_set_positions (entry, tmp_pos, sel_end);
4152 gboolean extend_to_left;
4155 /* Figure out what click selects and extend current selection */
4156 switch (event->type)
4158 case GDK_BUTTON_PRESS:
4159 gtk_entry_set_positions (entry, tmp_pos, tmp_pos);
4162 case GDK_2BUTTON_PRESS:
4163 priv->select_words = TRUE;
4164 gtk_entry_select_word (entry);
4167 case GDK_3BUTTON_PRESS:
4168 priv->select_lines = TRUE;
4169 gtk_entry_select_line (entry);
4176 start = MIN (priv->current_pos, priv->selection_bound);
4177 start = MIN (sel_start, start);
4179 end = MAX (priv->current_pos, priv->selection_bound);
4180 end = MAX (sel_end, end);
4182 if (tmp_pos == sel_start || tmp_pos == sel_end)
4183 extend_to_left = (tmp_pos == start);
4185 extend_to_left = (end == sel_end);
4188 gtk_entry_set_positions (entry, start, end);
4190 gtk_entry_set_positions (entry, end, start);
4193 else /* no shift key */
4194 switch (event->type)
4196 case GDK_BUTTON_PRESS:
4197 if (in_selection (entry, event->x + priv->scroll_offset))
4199 /* Click inside the selection - we'll either start a drag, or
4200 * clear the selection
4202 priv->in_drag = TRUE;
4203 priv->drag_start_x = event->x + priv->scroll_offset;
4204 priv->drag_start_y = event->y;
4208 gtk_editable_set_position (editable, tmp_pos);
4211 gtk_entry_update_handles (entry, GTK_TEXT_HANDLE_MODE_CURSOR);
4215 case GDK_2BUTTON_PRESS:
4216 /* We ALWAYS receive a GDK_BUTTON_PRESS immediately before
4217 * receiving a GDK_2BUTTON_PRESS so we need to reset
4218 * priv->in_drag which may have been set above
4220 priv->in_drag = FALSE;
4221 priv->select_words = TRUE;
4222 gtk_entry_select_word (entry);
4225 gtk_entry_update_handles (entry, GTK_TEXT_HANDLE_MODE_SELECTION);
4228 case GDK_3BUTTON_PRESS:
4229 /* We ALWAYS receive a GDK_BUTTON_PRESS immediately before
4230 * receiving a GDK_3BUTTON_PRESS so we need to reset
4231 * priv->in_drag which may have been set above
4233 priv->in_drag = FALSE;
4234 priv->select_lines = TRUE;
4235 gtk_entry_select_line (entry);
4237 gtk_entry_update_handles (entry, GTK_TEXT_HANDLE_MODE_SELECTION);
4246 else if (event->type == GDK_BUTTON_PRESS &&
4247 event->button == GDK_BUTTON_MIDDLE &&
4248 get_middle_click_paste (entry))
4252 priv->insert_pos = tmp_pos;
4253 gtk_entry_paste (entry, GDK_SELECTION_PRIMARY);
4258 gtk_widget_error_bell (widget);
4266 gtk_entry_button_release (GtkWidget *widget,
4267 GdkEventButton *event)
4269 GtkEntry *entry = GTK_ENTRY (widget);
4270 GtkEntryPrivate *priv = entry->priv;
4271 EntryIconInfo *icon_info = NULL;
4272 gboolean is_touchscreen;
4276 for (i = 0; i < MAX_ICONS; i++)
4278 icon_info = priv->icons[i];
4280 if (!icon_info || icon_info->insensitive)
4283 if (event->window == icon_info->window)
4285 icon_info->pressed = FALSE;
4287 if (should_prelight (entry, i) &&
4288 event->x >= 0 && event->y >= 0 &&
4289 event->x < gdk_window_get_width (icon_info->window) &&
4290 event->y < gdk_window_get_height (icon_info->window))
4292 icon_info->prelight = TRUE;
4293 gtk_widget_queue_draw (widget);
4296 if (!icon_info->nonactivatable)
4297 g_signal_emit (entry, signals[ICON_RELEASE], 0, i, event);
4303 if (event->window != priv->text_area || priv->button != event->button)
4306 source = gdk_event_get_source_device ((GdkEvent *) event);
4307 is_touchscreen = (test_touchscreen ||
4308 gdk_device_get_source (source) == GDK_SOURCE_TOUCHSCREEN);
4312 gint tmp_pos = gtk_entry_find_position (entry, priv->drag_start_x);
4314 gtk_editable_set_position (GTK_EDITABLE (entry), tmp_pos);
4317 gtk_entry_update_handles (entry, GTK_TEXT_HANDLE_MODE_CURSOR);
4321 else if (is_touchscreen)
4322 gtk_entry_selection_bubble_popup_set (entry);
4325 priv->device = NULL;
4327 gtk_entry_update_primary_selection (entry);
4333 _gtk_entry_get_selected_text (GtkEntry *entry)
4335 GtkEditable *editable = GTK_EDITABLE (entry);
4336 gint start_text, end_text;
4339 if (gtk_editable_get_selection_bounds (editable, &start_text, &end_text))
4340 text = gtk_editable_get_chars (editable, start_text, end_text);
4346 gtk_entry_motion_notify (GtkWidget *widget,
4347 GdkEventMotion *event)
4349 GtkEntry *entry = GTK_ENTRY (widget);
4350 GtkEntryPrivate *priv = entry->priv;
4351 EntryIconInfo *icon_info = NULL;
4355 for (i = 0; i < MAX_ICONS; i++)
4357 icon_info = priv->icons[i];
4359 if (!icon_info || icon_info->insensitive)
4362 if (event->window == icon_info->window)
4364 if (icon_info->pressed &&
4365 icon_info->target_list != NULL &&
4366 gtk_drag_check_threshold (widget,
4372 icon_info->in_drag = TRUE;
4373 icon_info->pressed = FALSE;
4374 gtk_drag_begin (widget,
4375 icon_info->target_list,
4385 if (priv->mouse_cursor_obscured)
4389 cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), GDK_XTERM);
4390 gdk_window_set_cursor (priv->text_area, cursor);
4391 g_object_unref (cursor);
4392 priv->mouse_cursor_obscured = FALSE;
4395 if (event->window != priv->text_area || priv->button != GDK_BUTTON_PRIMARY)
4398 if (priv->select_lines)
4401 gdk_event_request_motions (event);
4405 if (gtk_entry_get_display_mode (entry) == DISPLAY_NORMAL &&
4406 gtk_drag_check_threshold (widget,
4407 priv->drag_start_x, priv->drag_start_y,
4408 event->x + priv->scroll_offset, event->y))
4410 GdkDragContext *context;
4411 GtkTargetList *target_list = gtk_target_list_new (NULL, 0);
4412 guint actions = priv->editable ? GDK_ACTION_COPY | GDK_ACTION_MOVE : GDK_ACTION_COPY;
4414 cairo_surface_t *surface;
4416 gtk_target_list_add_text_targets (target_list, 0);
4418 text = _gtk_entry_get_selected_text (entry);
4419 surface = _gtk_text_util_create_drag_icon (widget, text, -1);
4421 context = gtk_drag_begin (widget, target_list, actions,
4422 priv->button, (GdkEvent *)event);
4425 gtk_drag_set_icon_surface (context, surface);
4427 gtk_drag_set_icon_default (context);
4430 cairo_surface_destroy (surface);
4433 priv->in_drag = FALSE;
4435 priv->device = NULL;
4437 gtk_target_list_unref (target_list);
4442 GdkInputSource input_source;
4446 length = gtk_entry_buffer_get_length (get_buffer (entry));
4450 else if (event->y >= gdk_window_get_height (priv->text_area))
4453 tmp_pos = gtk_entry_find_position (entry, event->x + priv->scroll_offset);
4455 source = gdk_event_get_source_device ((GdkEvent *) event);
4456 input_source = gdk_device_get_source (source);
4458 if (priv->select_words)
4461 gint old_min, old_max;
4464 min = gtk_entry_move_backward_word (entry, tmp_pos, TRUE);
4465 max = gtk_entry_move_forward_word (entry, tmp_pos, TRUE);
4467 pos = priv->current_pos;
4468 bound = priv->selection_bound;
4470 old_min = MIN(priv->current_pos, priv->selection_bound);
4471 old_max = MAX(priv->current_pos, priv->selection_bound);
4478 else if (old_max < max)
4483 else if (pos == old_min)
4485 if (priv->current_pos != min)
4490 if (priv->current_pos != max)
4494 gtk_entry_set_positions (entry, pos, bound);
4497 gtk_entry_set_positions (entry, tmp_pos, -1);
4499 /* Update touch handles' position */
4500 if (test_touchscreen || input_source == GDK_SOURCE_TOUCHSCREEN)
4501 gtk_entry_update_handles (entry,
4502 (priv->current_pos == priv->selection_bound) ?
4503 GTK_TEXT_HANDLE_MODE_CURSOR :
4504 GTK_TEXT_HANDLE_MODE_SELECTION);
4511 set_invisible_cursor (GdkWindow *window)
4513 GdkDisplay *display;
4516 display = gdk_window_get_display (window);
4517 cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR);
4519 gdk_window_set_cursor (window, cursor);
4521 g_object_unref (cursor);
4525 gtk_entry_obscure_mouse_cursor (GtkEntry *entry)
4527 GtkEntryPrivate *priv = entry->priv;
4529 if (priv->mouse_cursor_obscured)
4532 set_invisible_cursor (priv->text_area);
4534 priv->mouse_cursor_obscured = TRUE;
4538 gtk_entry_key_press (GtkWidget *widget,
4541 GtkEntry *entry = GTK_ENTRY (widget);
4542 GtkEntryPrivate *priv = entry->priv;
4544 gtk_entry_reset_blink_time (entry);
4545 gtk_entry_pend_cursor_blink (entry);
4547 gtk_entry_selection_bubble_popup_unset (entry);
4549 if (!event->send_event)
4550 _gtk_text_handle_set_mode (priv->text_handle,
4551 GTK_TEXT_HANDLE_MODE_NONE);
4555 if (gtk_im_context_filter_keypress (priv->im_context, event))
4557 gtk_entry_obscure_mouse_cursor (entry);
4558 priv->need_im_reset = TRUE;
4563 if (event->keyval == GDK_KEY_Return ||
4564 event->keyval == GDK_KEY_KP_Enter ||
4565 event->keyval == GDK_KEY_ISO_Enter ||
4566 event->keyval == GDK_KEY_Escape)
4567 gtk_entry_reset_im_context (entry);
4569 if (GTK_WIDGET_CLASS (gtk_entry_parent_class)->key_press_event (widget, event))
4570 /* Activate key bindings
4574 if (!priv->editable && event->length)
4575 gtk_widget_error_bell (widget);
4581 gtk_entry_key_release (GtkWidget *widget,
4584 GtkEntry *entry = GTK_ENTRY (widget);
4585 GtkEntryPrivate *priv = entry->priv;
4589 if (gtk_im_context_filter_keypress (priv->im_context, event))
4591 priv->need_im_reset = TRUE;
4596 return GTK_WIDGET_CLASS (gtk_entry_parent_class)->key_release_event (widget, event);
4600 gtk_entry_focus_in (GtkWidget *widget,
4601 GdkEventFocus *event)
4603 GtkEntry *entry = GTK_ENTRY (widget);
4604 GtkEntryPrivate *priv = entry->priv;
4607 gtk_widget_queue_draw (widget);
4609 keymap = gdk_keymap_get_for_display (gtk_widget_get_display (widget));
4613 priv->need_im_reset = TRUE;
4614 gtk_im_context_focus_in (priv->im_context);
4615 keymap_state_changed (keymap, entry);
4616 g_signal_connect (keymap, "state-changed",
4617 G_CALLBACK (keymap_state_changed), entry);
4620 g_signal_connect (keymap, "direction-changed",
4621 G_CALLBACK (keymap_direction_changed), entry);
4623 if (gtk_entry_buffer_get_bytes (get_buffer (entry)) == 0 &&
4624 priv->placeholder_text != NULL)
4626 gtk_entry_recompute (entry);
4630 gtk_entry_reset_blink_time (entry);
4631 gtk_entry_check_cursor_blink (entry);
4638 gtk_entry_focus_out (GtkWidget *widget,
4639 GdkEventFocus *event)
4641 GtkEntry *entry = GTK_ENTRY (widget);
4642 GtkEntryPrivate *priv = entry->priv;
4643 GtkEntryCompletion *completion;
4646 gtk_entry_selection_bubble_popup_unset (entry);
4647 _gtk_text_handle_set_mode (priv->text_handle,
4648 GTK_TEXT_HANDLE_MODE_NONE);
4650 gtk_widget_queue_draw (widget);
4652 keymap = gdk_keymap_get_for_display (gtk_widget_get_display (widget));
4656 priv->need_im_reset = TRUE;
4657 gtk_im_context_focus_out (priv->im_context);
4658 remove_capslock_feedback (entry);
4661 if (gtk_entry_buffer_get_bytes (get_buffer (entry)) == 0 &&
4662 priv->placeholder_text != NULL)
4664 gtk_entry_recompute (entry);
4668 gtk_entry_check_cursor_blink (entry);
4671 g_signal_handlers_disconnect_by_func (keymap, keymap_state_changed, entry);
4672 g_signal_handlers_disconnect_by_func (keymap, keymap_direction_changed, entry);
4674 completion = gtk_entry_get_completion (entry);
4676 _gtk_entry_completion_popdown (completion);
4682 gtk_entry_grab_focus (GtkWidget *widget)
4684 GtkEntry *entry = GTK_ENTRY (widget);
4685 GtkEntryPrivate *priv = entry->priv;
4686 gboolean select_on_focus;
4688 GTK_WIDGET_CLASS (gtk_entry_parent_class)->grab_focus (widget);
4690 if (priv->editable && !priv->in_click)
4692 g_object_get (gtk_widget_get_settings (widget),
4693 "gtk-entry-select-on-focus",
4697 if (select_on_focus)
4698 gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
4703 gtk_entry_direction_changed (GtkWidget *widget,
4704 GtkTextDirection previous_dir)
4706 GtkEntry *entry = GTK_ENTRY (widget);
4708 gtk_entry_recompute (entry);
4710 GTK_WIDGET_CLASS (gtk_entry_parent_class)->direction_changed (widget, previous_dir);
4714 gtk_entry_state_flags_changed (GtkWidget *widget,
4715 GtkStateFlags previous_state)
4717 GtkEntry *entry = GTK_ENTRY (widget);
4718 GtkEntryPrivate *priv = entry->priv;
4721 if (gtk_widget_get_realized (widget))
4723 if (gtk_widget_is_sensitive (widget))
4724 cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), GDK_XTERM);
4728 gdk_window_set_cursor (priv->text_area, cursor);
4731 g_object_unref (cursor);
4733 priv->mouse_cursor_obscured = FALSE;
4735 update_cursors (widget);
4738 if (!gtk_widget_is_sensitive (widget))
4740 /* Clear any selection */
4741 gtk_editable_select_region (GTK_EDITABLE (entry), priv->current_pos, priv->current_pos);
4744 gtk_entry_update_cached_style_values (entry);
4748 gtk_entry_screen_changed (GtkWidget *widget,
4749 GdkScreen *old_screen)
4751 gtk_entry_recompute (GTK_ENTRY (widget));
4754 /* GtkEditable method implementations
4757 gtk_entry_insert_text (GtkEditable *editable,
4758 const gchar *new_text,
4759 gint new_text_length,
4762 g_object_ref (editable);
4765 * The incoming text may a password or other secret. We make sure
4766 * not to copy it into temporary buffers.
4769 g_signal_emit_by_name (editable, "insert-text", new_text, new_text_length, position);
4771 g_object_unref (editable);
4775 gtk_entry_delete_text (GtkEditable *editable,
4779 g_object_ref (editable);
4781 g_signal_emit_by_name (editable, "delete-text", start_pos, end_pos);
4783 g_object_unref (editable);
4787 gtk_entry_get_chars (GtkEditable *editable,
4791 GtkEntry *entry = GTK_ENTRY (editable);
4794 gint start_index, end_index;
4796 text = gtk_entry_buffer_get_text (get_buffer (entry));
4797 text_length = gtk_entry_buffer_get_length (get_buffer (entry));
4800 end_pos = text_length;
4802 start_pos = MIN (text_length, start_pos);
4803 end_pos = MIN (text_length, end_pos);
4805 start_index = g_utf8_offset_to_pointer (text, start_pos) - text;
4806 end_index = g_utf8_offset_to_pointer (text, end_pos) - text;
4808 return g_strndup (text + start_index, end_index - start_index);
4812 gtk_entry_real_set_position (GtkEditable *editable,
4815 GtkEntry *entry = GTK_ENTRY (editable);
4816 GtkEntryPrivate *priv = entry->priv;
4820 length = gtk_entry_buffer_get_length (get_buffer (entry));
4821 if (position < 0 || position > length)
4824 if (position != priv->current_pos ||
4825 position != priv->selection_bound)
4827 gtk_entry_reset_im_context (entry);
4828 gtk_entry_set_positions (entry, position, position);
4833 gtk_entry_get_position (GtkEditable *editable)
4835 GtkEntry *entry = GTK_ENTRY (editable);
4836 GtkEntryPrivate *priv = entry->priv;
4838 return priv->current_pos;
4842 gtk_entry_set_selection_bounds (GtkEditable *editable,
4846 GtkEntry *entry = GTK_ENTRY (editable);
4849 length = gtk_entry_buffer_get_length (get_buffer (entry));
4855 gtk_entry_reset_im_context (entry);
4857 gtk_entry_set_positions (entry,
4859 MIN (start, length));
4861 gtk_entry_update_primary_selection (entry);
4865 gtk_entry_get_selection_bounds (GtkEditable *editable,
4869 GtkEntry *entry = GTK_ENTRY (editable);
4870 GtkEntryPrivate *priv = entry->priv;
4872 *start = priv->selection_bound;
4873 *end = priv->current_pos;
4875 return (priv->selection_bound != priv->current_pos);
4879 icon_theme_changed (GtkEntry *entry)
4881 GtkEntryPrivate *priv = entry->priv;
4884 for (i = 0; i < MAX_ICONS; i++)
4886 EntryIconInfo *icon_info = priv->icons[i];
4887 if (icon_info != NULL)
4888 _gtk_icon_helper_invalidate (icon_info->icon_helper);
4891 gtk_widget_queue_draw (GTK_WIDGET (entry));
4895 gtk_entry_update_cached_style_values (GtkEntry *entry)
4897 GtkEntryPrivate *priv = entry->priv;
4899 gboolean interior_focus;
4901 gtk_widget_style_get (GTK_WIDGET (entry),
4902 "focus-line-width", &focus_width,
4903 "interior-focus", &interior_focus,
4905 priv->focus_width = focus_width;
4906 priv->interior_focus = interior_focus;
4908 if (!priv->invisible_char_set)
4910 gunichar ch = find_invisible_char (GTK_WIDGET (entry));
4912 if (priv->invisible_char != ch)
4914 priv->invisible_char = ch;
4915 g_object_notify (G_OBJECT (entry), "invisible-char");
4921 gtk_entry_style_updated (GtkWidget *widget)
4923 GtkEntry *entry = GTK_ENTRY (widget);
4925 GTK_WIDGET_CLASS (gtk_entry_parent_class)->style_updated (widget);
4927 gtk_entry_update_cached_style_values (entry);
4929 icon_theme_changed (entry);
4932 /* GtkCellEditable method implementations
4935 gtk_cell_editable_entry_activated (GtkEntry *entry, gpointer data)
4937 gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (entry));
4938 gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (entry));
4942 gtk_cell_editable_key_press_event (GtkEntry *entry,
4943 GdkEventKey *key_event,
4946 GtkEntryPrivate *priv = entry->priv;
4948 if (key_event->keyval == GDK_KEY_Escape)
4950 priv->editing_canceled = TRUE;
4951 gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (entry));
4952 gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (entry));
4957 /* override focus */
4958 if (key_event->keyval == GDK_KEY_Up || key_event->keyval == GDK_KEY_Down)
4960 gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (entry));
4961 gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (entry));
4970 gtk_entry_start_editing (GtkCellEditable *cell_editable,
4973 GtkEntry *entry = GTK_ENTRY (cell_editable);
4974 GtkEntryPrivate *priv = entry->priv;
4976 priv->is_cell_renderer = TRUE;
4978 g_signal_connect (cell_editable, "activate",
4979 G_CALLBACK (gtk_cell_editable_entry_activated), NULL);
4980 g_signal_connect (cell_editable, "key-press-event",
4981 G_CALLBACK (gtk_cell_editable_key_press_event), NULL);
4985 gtk_entry_password_hint_free (GtkEntryPasswordHint *password_hint)
4987 if (password_hint->source_id)
4988 g_source_remove (password_hint->source_id);
4990 g_slice_free (GtkEntryPasswordHint, password_hint);
4995 gtk_entry_remove_password_hint (gpointer data)
4997 GtkEntryPasswordHint *password_hint = g_object_get_qdata (data, quark_password_hint);
4998 password_hint->position = -1;
5000 /* Force the string to be redrawn, but now without a visible character */
5001 gtk_entry_recompute (GTK_ENTRY (data));
5005 /* Default signal handlers
5008 gtk_entry_real_insert_text (GtkEditable *editable,
5009 const gchar *new_text,
5010 gint new_text_length,
5016 n_chars = g_utf8_strlen (new_text, new_text_length);
5019 * The actual insertion into the buffer. This will end up firing the
5020 * following signal handlers: buffer_inserted_text(), buffer_notify_display_text(),
5021 * buffer_notify_text(), buffer_notify_length()
5023 begin_change (GTK_ENTRY (editable));
5025 n_inserted = gtk_entry_buffer_insert_text (get_buffer (GTK_ENTRY (editable)), *position, new_text, n_chars);
5027 end_change (GTK_ENTRY (editable));
5029 if (n_inserted != n_chars)
5030 gtk_widget_error_bell (GTK_WIDGET (editable));
5032 *position += n_inserted;
5036 gtk_entry_real_delete_text (GtkEditable *editable,
5041 * The actual deletion from the buffer. This will end up firing the
5042 * following signal handlers: buffer_deleted_text(), buffer_notify_display_text(),
5043 * buffer_notify_text(), buffer_notify_length()
5046 begin_change (GTK_ENTRY (editable));
5048 gtk_entry_buffer_delete_text (get_buffer (GTK_ENTRY (editable)), start_pos, end_pos - start_pos);
5050 end_change (GTK_ENTRY (editable));
5053 /* GtkEntryBuffer signal handlers
5056 buffer_inserted_text (GtkEntryBuffer *buffer,
5062 GtkEntryPrivate *priv = entry->priv;
5063 guint password_hint_timeout;
5065 gint selection_bound;
5067 current_pos = priv->current_pos;
5068 if (current_pos > position)
5069 current_pos += n_chars;
5071 selection_bound = priv->selection_bound;
5072 if (selection_bound > position)
5073 selection_bound += n_chars;
5075 gtk_entry_set_positions (entry, current_pos, selection_bound);
5077 /* Calculate the password hint if it needs to be displayed. */
5078 if (n_chars == 1 && !priv->visible)
5080 g_object_get (gtk_widget_get_settings (GTK_WIDGET (entry)),
5081 "gtk-entry-password-hint-timeout", &password_hint_timeout,
5084 if (password_hint_timeout > 0)
5086 GtkEntryPasswordHint *password_hint = g_object_get_qdata (G_OBJECT (entry),
5087 quark_password_hint);
5090 password_hint = g_slice_new0 (GtkEntryPasswordHint);
5091 g_object_set_qdata_full (G_OBJECT (entry), quark_password_hint, password_hint,
5092 (GDestroyNotify)gtk_entry_password_hint_free);
5095 password_hint->position = position;
5096 if (password_hint->source_id)
5097 g_source_remove (password_hint->source_id);
5098 password_hint->source_id = gdk_threads_add_timeout (password_hint_timeout,
5099 (GSourceFunc)gtk_entry_remove_password_hint, entry);
5105 buffer_deleted_text (GtkEntryBuffer *buffer,
5110 GtkEntryPrivate *priv = entry->priv;
5111 guint end_pos = position + n_chars;
5112 gint selection_bound;
5115 current_pos = priv->current_pos;
5116 if (current_pos > position)
5117 current_pos -= MIN (current_pos, end_pos) - position;
5119 selection_bound = priv->selection_bound;
5120 if (selection_bound > position)
5121 selection_bound -= MIN (selection_bound, end_pos) - position;
5123 gtk_entry_set_positions (entry, current_pos, selection_bound);
5125 /* We might have deleted the selection */
5126 gtk_entry_update_primary_selection (entry);
5128 /* Disable the password hint if one exists. */
5131 GtkEntryPasswordHint *password_hint = g_object_get_qdata (G_OBJECT (entry),
5132 quark_password_hint);
5135 if (password_hint->source_id)
5136 g_source_remove (password_hint->source_id);
5137 password_hint->source_id = 0;
5138 password_hint->position = -1;
5144 buffer_notify_text (GtkEntryBuffer *buffer,
5148 gtk_entry_recompute (entry);
5149 emit_changed (entry);
5150 g_object_notify (G_OBJECT (entry), "text");
5154 buffer_notify_length (GtkEntryBuffer *buffer,
5158 g_object_notify (G_OBJECT (entry), "text-length");
5162 buffer_notify_max_length (GtkEntryBuffer *buffer,
5166 g_object_notify (G_OBJECT (entry), "max-length");
5170 buffer_connect_signals (GtkEntry *entry)
5172 g_signal_connect (get_buffer (entry), "inserted-text", G_CALLBACK (buffer_inserted_text), entry);
5173 g_signal_connect (get_buffer (entry), "deleted-text", G_CALLBACK (buffer_deleted_text), entry);
5174 g_signal_connect (get_buffer (entry), "notify::text", G_CALLBACK (buffer_notify_text), entry);
5175 g_signal_connect (get_buffer (entry), "notify::length", G_CALLBACK (buffer_notify_length), entry);
5176 g_signal_connect (get_buffer (entry), "notify::max-length", G_CALLBACK (buffer_notify_max_length), entry);
5180 buffer_disconnect_signals (GtkEntry *entry)
5182 g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_inserted_text, entry);
5183 g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_deleted_text, entry);
5184 g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_notify_text, entry);
5185 g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_notify_length, entry);
5186 g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_notify_max_length, entry);
5189 /* Compute the X position for an offset that corresponds to the "more important
5190 * cursor position for that offset. We use this when trying to guess to which
5191 * end of the selection we should go to when the user hits the left or
5195 get_better_cursor_x (GtkEntry *entry,
5198 GtkEntryPrivate *priv = entry->priv;
5199 GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (entry)));
5200 PangoDirection keymap_direction = gdk_keymap_get_direction (keymap);
5201 gboolean split_cursor;
5203 PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
5204 const gchar *text = pango_layout_get_text (layout);
5205 gint index = g_utf8_offset_to_pointer (text, offset) - text;
5207 PangoRectangle strong_pos, weak_pos;
5209 g_object_get (gtk_widget_get_settings (GTK_WIDGET (entry)),
5210 "gtk-split-cursor", &split_cursor,
5213 pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos);
5216 return strong_pos.x / PANGO_SCALE;
5218 return (keymap_direction == priv->resolved_dir) ? strong_pos.x / PANGO_SCALE : weak_pos.x / PANGO_SCALE;
5222 gtk_entry_move_cursor (GtkEntry *entry,
5223 GtkMovementStep step,
5225 gboolean extend_selection)
5227 GtkEntryPrivate *priv = entry->priv;
5228 gint new_pos = priv->current_pos;
5230 gtk_entry_reset_im_context (entry);
5232 if (priv->current_pos != priv->selection_bound && !extend_selection)
5234 /* If we have a current selection and aren't extending it, move to the
5235 * start/or end of the selection as appropriate
5239 case GTK_MOVEMENT_VISUAL_POSITIONS:
5241 gint current_x = get_better_cursor_x (entry, priv->current_pos);
5242 gint bound_x = get_better_cursor_x (entry, priv->selection_bound);
5245 new_pos = current_x < bound_x ? priv->current_pos : priv->selection_bound;
5247 new_pos = current_x > bound_x ? priv->current_pos : priv->selection_bound;
5250 case GTK_MOVEMENT_LOGICAL_POSITIONS:
5251 case GTK_MOVEMENT_WORDS:
5253 new_pos = MIN (priv->current_pos, priv->selection_bound);
5255 new_pos = MAX (priv->current_pos, priv->selection_bound);
5257 case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
5258 case GTK_MOVEMENT_PARAGRAPH_ENDS:
5259 case GTK_MOVEMENT_BUFFER_ENDS:
5260 new_pos = count < 0 ? 0 : gtk_entry_buffer_get_length (get_buffer (entry));
5262 case GTK_MOVEMENT_DISPLAY_LINES:
5263 case GTK_MOVEMENT_PARAGRAPHS:
5264 case GTK_MOVEMENT_PAGES:
5265 case GTK_MOVEMENT_HORIZONTAL_PAGES:
5273 case GTK_MOVEMENT_LOGICAL_POSITIONS:
5274 new_pos = gtk_entry_move_logically (entry, new_pos, count);
5276 case GTK_MOVEMENT_VISUAL_POSITIONS:
5277 new_pos = gtk_entry_move_visually (entry, new_pos, count);
5278 if (priv->current_pos == new_pos)
5280 if (!extend_selection)
5282 if (!gtk_widget_keynav_failed (GTK_WIDGET (entry),
5284 GTK_DIR_RIGHT : GTK_DIR_LEFT))
5286 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (entry));
5289 gtk_widget_child_focus (toplevel,
5291 GTK_DIR_RIGHT : GTK_DIR_LEFT);
5296 gtk_widget_error_bell (GTK_WIDGET (entry));
5300 case GTK_MOVEMENT_WORDS:
5303 new_pos = gtk_entry_move_forward_word (entry, new_pos, FALSE);
5308 new_pos = gtk_entry_move_backward_word (entry, new_pos, FALSE);
5311 if (priv->current_pos == new_pos)
5312 gtk_widget_error_bell (GTK_WIDGET (entry));
5314 case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
5315 case GTK_MOVEMENT_PARAGRAPH_ENDS:
5316 case GTK_MOVEMENT_BUFFER_ENDS:
5317 new_pos = count < 0 ? 0 : gtk_entry_buffer_get_length (get_buffer (entry));
5318 if (priv->current_pos == new_pos)
5319 gtk_widget_error_bell (GTK_WIDGET (entry));
5321 case GTK_MOVEMENT_DISPLAY_LINES:
5322 case GTK_MOVEMENT_PARAGRAPHS:
5323 case GTK_MOVEMENT_PAGES:
5324 case GTK_MOVEMENT_HORIZONTAL_PAGES:
5329 if (extend_selection)
5330 gtk_editable_select_region (GTK_EDITABLE (entry), priv->selection_bound, new_pos);
5332 gtk_editable_set_position (GTK_EDITABLE (entry), new_pos);
5334 gtk_entry_pend_cursor_blink (entry);
5338 gtk_entry_insert_at_cursor (GtkEntry *entry,
5341 GtkEntryPrivate *priv = entry->priv;
5342 GtkEditable *editable = GTK_EDITABLE (entry);
5343 gint pos = priv->current_pos;
5347 gtk_entry_reset_im_context (entry);
5348 gtk_editable_insert_text (editable, str, -1, &pos);
5349 gtk_editable_set_position (editable, pos);
5354 gtk_entry_delete_from_cursor (GtkEntry *entry,
5358 GtkEntryPrivate *priv = entry->priv;
5359 GtkEditable *editable = GTK_EDITABLE (entry);
5360 gint start_pos = priv->current_pos;
5361 gint end_pos = priv->current_pos;
5362 gint old_n_bytes = gtk_entry_buffer_get_bytes (get_buffer (entry));
5364 gtk_entry_reset_im_context (entry);
5366 if (!priv->editable)
5368 gtk_widget_error_bell (GTK_WIDGET (entry));
5372 if (priv->selection_bound != priv->current_pos)
5374 gtk_editable_delete_selection (editable);
5380 case GTK_DELETE_CHARS:
5381 end_pos = gtk_entry_move_logically (entry, priv->current_pos, count);
5382 gtk_editable_delete_text (editable, MIN (start_pos, end_pos), MAX (start_pos, end_pos));
5384 case GTK_DELETE_WORDS:
5387 /* Move to end of current word, or if not on a word, end of previous word */
5388 end_pos = gtk_entry_move_backward_word (entry, end_pos, FALSE);
5389 end_pos = gtk_entry_move_forward_word (entry, end_pos, FALSE);
5393 /* Move to beginning of current word, or if not on a word, begining of next word */
5394 start_pos = gtk_entry_move_forward_word (entry, start_pos, FALSE);
5395 start_pos = gtk_entry_move_backward_word (entry, start_pos, FALSE);
5399 case GTK_DELETE_WORD_ENDS:
5402 start_pos = gtk_entry_move_backward_word (entry, start_pos, FALSE);
5407 end_pos = gtk_entry_move_forward_word (entry, end_pos, FALSE);
5410 gtk_editable_delete_text (editable, start_pos, end_pos);
5412 case GTK_DELETE_DISPLAY_LINE_ENDS:
5413 case GTK_DELETE_PARAGRAPH_ENDS:
5415 gtk_editable_delete_text (editable, 0, priv->current_pos);
5417 gtk_editable_delete_text (editable, priv->current_pos, -1);
5419 case GTK_DELETE_DISPLAY_LINES:
5420 case GTK_DELETE_PARAGRAPHS:
5421 gtk_editable_delete_text (editable, 0, -1);
5423 case GTK_DELETE_WHITESPACE:
5424 gtk_entry_delete_whitespace (entry);
5428 if (gtk_entry_buffer_get_bytes (get_buffer (entry)) == old_n_bytes)
5429 gtk_widget_error_bell (GTK_WIDGET (entry));
5431 gtk_entry_pend_cursor_blink (entry);
5435 gtk_entry_backspace (GtkEntry *entry)
5437 GtkEntryPrivate *priv = entry->priv;
5438 GtkEditable *editable = GTK_EDITABLE (entry);
5441 gtk_entry_reset_im_context (entry);
5443 if (!priv->editable)
5445 gtk_widget_error_bell (GTK_WIDGET (entry));
5449 if (priv->selection_bound != priv->current_pos)
5451 gtk_editable_delete_selection (editable);
5455 prev_pos = gtk_entry_move_logically (entry, priv->current_pos, -1);
5457 if (prev_pos < priv->current_pos)
5459 PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
5460 PangoLogAttr *log_attrs;
5463 pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
5465 /* Deleting parts of characters */
5466 if (log_attrs[priv->current_pos].backspace_deletes_character)
5468 gchar *cluster_text;
5469 gchar *normalized_text;
5472 cluster_text = _gtk_entry_get_display_text (entry, prev_pos,
5474 normalized_text = g_utf8_normalize (cluster_text,
5475 strlen (cluster_text),
5477 len = g_utf8_strlen (normalized_text, -1);
5479 gtk_editable_delete_text (editable, prev_pos, priv->current_pos);
5482 gint pos = priv->current_pos;
5484 gtk_editable_insert_text (editable, normalized_text,
5485 g_utf8_offset_to_pointer (normalized_text, len - 1) - normalized_text,
5487 gtk_editable_set_position (editable, pos);
5490 g_free (normalized_text);
5491 g_free (cluster_text);
5495 gtk_editable_delete_text (editable, prev_pos, priv->current_pos);
5502 gtk_widget_error_bell (GTK_WIDGET (entry));
5505 gtk_entry_pend_cursor_blink (entry);
5509 gtk_entry_copy_clipboard (GtkEntry *entry)
5511 GtkEntryPrivate *priv = entry->priv;
5512 GtkEditable *editable = GTK_EDITABLE (entry);
5516 if (gtk_editable_get_selection_bounds (editable, &start, &end))
5520 gtk_widget_error_bell (GTK_WIDGET (entry));
5524 str = _gtk_entry_get_display_text (entry, start, end);
5525 gtk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (entry),
5526 GDK_SELECTION_CLIPBOARD),
5533 gtk_entry_cut_clipboard (GtkEntry *entry)
5535 GtkEntryPrivate *priv = entry->priv;
5536 GtkEditable *editable = GTK_EDITABLE (entry);
5541 gtk_widget_error_bell (GTK_WIDGET (entry));
5545 gtk_entry_copy_clipboard (entry);
5549 if (gtk_editable_get_selection_bounds (editable, &start, &end))
5550 gtk_editable_delete_text (editable, start, end);
5554 gtk_widget_error_bell (GTK_WIDGET (entry));
5557 gtk_entry_selection_bubble_popup_unset (entry);
5561 gtk_entry_paste_clipboard (GtkEntry *entry)
5563 GtkEntryPrivate *priv = entry->priv;
5566 gtk_entry_paste (entry, GDK_SELECTION_CLIPBOARD);
5568 gtk_widget_error_bell (GTK_WIDGET (entry));
5572 gtk_entry_delete_cb (GtkEntry *entry)
5574 GtkEntryPrivate *priv = entry->priv;
5575 GtkEditable *editable = GTK_EDITABLE (entry);
5580 if (gtk_editable_get_selection_bounds (editable, &start, &end))
5581 gtk_editable_delete_text (editable, start, end);
5586 gtk_entry_toggle_overwrite (GtkEntry *entry)
5588 GtkEntryPrivate *priv = entry->priv;
5590 priv->overwrite_mode = !priv->overwrite_mode;
5591 gtk_entry_pend_cursor_blink (entry);
5592 gtk_widget_queue_draw (GTK_WIDGET (entry));
5596 gtk_entry_select_all (GtkEntry *entry)
5598 gtk_entry_select_line (entry);
5602 gtk_entry_real_activate (GtkEntry *entry)
5604 GtkEntryPrivate *priv = entry->priv;
5606 GtkWidget *default_widget, *focus_widget;
5607 GtkWidget *toplevel;
5610 widget = GTK_WIDGET (entry);
5612 if (priv->activates_default)
5614 toplevel = gtk_widget_get_toplevel (widget);
5615 if (GTK_IS_WINDOW (toplevel))
5617 window = GTK_WINDOW (toplevel);
5621 default_widget = gtk_window_get_default_widget (window);
5622 focus_widget = gtk_window_get_focus (window);
5623 if (widget != default_widget &&
5624 !(widget == focus_widget && (!default_widget || !gtk_widget_get_sensitive (default_widget))))
5625 gtk_window_activate_default (window);
5632 keymap_direction_changed (GdkKeymap *keymap,
5635 gtk_entry_recompute (entry);
5638 /* IM Context Callbacks
5642 gtk_entry_commit_cb (GtkIMContext *context,
5646 GtkEntryPrivate *priv = entry->priv;
5649 gtk_entry_enter_text (entry, str);
5653 gtk_entry_preedit_changed_cb (GtkIMContext *context,
5656 GtkEntryPrivate *priv = entry->priv;
5660 gchar *preedit_string;
5663 gtk_im_context_get_preedit_string (priv->im_context,
5664 &preedit_string, NULL,
5666 g_signal_emit (entry, signals[PREEDIT_CHANGED], 0, preedit_string);
5667 priv->preedit_length = strlen (preedit_string);
5668 cursor_pos = CLAMP (cursor_pos, 0, g_utf8_strlen (preedit_string, -1));
5669 priv->preedit_cursor = cursor_pos;
5670 g_free (preedit_string);
5672 gtk_entry_recompute (entry);
5677 gtk_entry_retrieve_surrounding_cb (GtkIMContext *context,
5680 GtkEntryPrivate *priv = entry->priv;
5683 /* XXXX ??? does this even make sense when text is not visible? Should we return FALSE? */
5684 text = _gtk_entry_get_display_text (entry, 0, -1);
5685 gtk_im_context_set_surrounding (context, text, strlen (text), /* Length in bytes */
5686 g_utf8_offset_to_pointer (text, priv->current_pos) - text);
5693 gtk_entry_delete_surrounding_cb (GtkIMContext *slave,
5698 GtkEntryPrivate *priv = entry->priv;
5701 gtk_editable_delete_text (GTK_EDITABLE (entry),
5702 priv->current_pos + offset,
5703 priv->current_pos + offset + n_chars);
5708 /* Internal functions
5711 /* Used for im_commit_cb and inserting Unicode chars */
5713 gtk_entry_enter_text (GtkEntry *entry,
5716 GtkEntryPrivate *priv = entry->priv;
5717 GtkEditable *editable = GTK_EDITABLE (entry);
5719 gboolean old_need_im_reset;
5721 old_need_im_reset = priv->need_im_reset;
5722 priv->need_im_reset = FALSE;
5724 if (gtk_editable_get_selection_bounds (editable, NULL, NULL))
5725 gtk_editable_delete_selection (editable);
5728 if (priv->overwrite_mode)
5729 gtk_entry_delete_from_cursor (entry, GTK_DELETE_CHARS, 1);
5732 tmp_pos = priv->current_pos;
5733 gtk_editable_insert_text (editable, str, strlen (str), &tmp_pos);
5734 gtk_editable_set_position (editable, tmp_pos);
5736 priv->need_im_reset = old_need_im_reset;
5739 /* All changes to priv->current_pos and priv->selection_bound
5740 * should go through this function.
5743 gtk_entry_set_positions (GtkEntry *entry,
5745 gint selection_bound)
5747 GtkEntryPrivate *priv = entry->priv;
5748 gboolean changed = FALSE;
5750 g_object_freeze_notify (G_OBJECT (entry));
5752 if (current_pos != -1 &&
5753 priv->current_pos != current_pos)
5755 priv->current_pos = current_pos;
5758 g_object_notify (G_OBJECT (entry), "cursor-position");
5761 if (selection_bound != -1 &&
5762 priv->selection_bound != selection_bound)
5764 priv->selection_bound = selection_bound;
5767 g_object_notify (G_OBJECT (entry), "selection-bound");
5770 g_object_thaw_notify (G_OBJECT (entry));
5774 gtk_entry_move_adjustments (entry);
5775 gtk_entry_recompute (entry);
5780 gtk_entry_reset_layout (GtkEntry *entry)
5782 GtkEntryPrivate *priv = entry->priv;
5784 if (priv->cached_layout)
5786 g_object_unref (priv->cached_layout);
5787 priv->cached_layout = NULL;
5792 update_im_cursor_location (GtkEntry *entry)
5794 GtkEntryPrivate *priv = entry->priv;
5797 gint strong_xoffset;
5798 gint area_width, area_height;
5800 gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &strong_x, NULL);
5801 gtk_entry_get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
5803 strong_xoffset = strong_x - priv->scroll_offset;
5804 if (strong_xoffset < 0)
5808 else if (strong_xoffset > area_width)
5810 strong_xoffset = area_width;
5812 area.x = strong_xoffset;
5815 area.height = area_height;
5817 gtk_im_context_set_cursor_location (priv->im_context, &area);
5821 recompute_idle_func (gpointer data)
5823 GtkEntry *entry = GTK_ENTRY (data);
5824 GtkEntryPrivate *priv = entry->priv;
5826 priv->recompute_idle = 0;
5828 if (gtk_widget_has_screen (GTK_WIDGET (entry)))
5830 GtkTextHandleMode handle_mode;
5832 gtk_entry_adjust_scroll (entry);
5833 gtk_widget_queue_draw (GTK_WIDGET (entry));
5835 update_im_cursor_location (entry);
5837 handle_mode = _gtk_text_handle_get_mode (priv->text_handle);
5839 if (handle_mode != GTK_TEXT_HANDLE_MODE_NONE)
5840 gtk_entry_update_handles (entry, handle_mode);
5847 gtk_entry_recompute (GtkEntry *entry)
5849 GtkEntryPrivate *priv = entry->priv;
5851 gtk_entry_reset_layout (entry);
5852 gtk_entry_check_cursor_blink (entry);
5854 if (!priv->recompute_idle)
5856 priv->recompute_idle = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 15, /* between resize and redraw */
5857 recompute_idle_func, entry, NULL);
5862 gtk_entry_get_placeholder_text_color (GtkEntry *entry,
5865 GtkWidget *widget = GTK_WIDGET (entry);
5866 GtkStyleContext *context;
5867 GdkRGBA fg = { 0.5, 0.5, 0.5 };
5869 context = gtk_widget_get_style_context (widget);
5870 gtk_style_context_lookup_color (context, "placeholder_text_color", &fg);
5872 color->red = CLAMP (fg.red * 65535. + 0.5, 0, 65535);
5873 color->green = CLAMP (fg.green * 65535. + 0.5, 0, 65535);
5874 color->blue = CLAMP (fg.blue * 65535. + 0.5, 0, 65535);
5877 static inline gboolean
5878 show_placeholder_text (GtkEntry *entry)
5880 GtkEntryPrivate *priv = entry->priv;
5882 if (!gtk_widget_has_focus (GTK_WIDGET (entry)) &&
5883 gtk_entry_buffer_get_bytes (get_buffer (entry)) == 0 &&
5884 priv->placeholder_text != NULL)
5890 static PangoLayout *
5891 gtk_entry_create_layout (GtkEntry *entry,
5892 gboolean include_preedit)
5894 GtkEntryPrivate *priv = entry->priv;
5895 GtkWidget *widget = GTK_WIDGET (entry);
5896 PangoLayout *layout;
5897 PangoAttrList *tmp_attrs;
5898 gboolean placeholder_layout;
5900 gchar *preedit_string = NULL;
5901 gint preedit_length = 0;
5902 PangoAttrList *preedit_attrs = NULL;
5907 layout = gtk_widget_create_pango_layout (widget, NULL);
5908 pango_layout_set_single_paragraph_mode (layout, TRUE);
5910 tmp_attrs = priv->attrs ? pango_attr_list_ref (priv->attrs)
5911 : pango_attr_list_new ();
5913 placeholder_layout = show_placeholder_text (entry);
5914 display = placeholder_layout ? g_strdup (priv->placeholder_text) : _gtk_entry_get_display_text (entry, 0, -1);
5915 n_bytes = strlen (display);
5917 if (!placeholder_layout && include_preedit)
5919 gtk_im_context_get_preedit_string (priv->im_context,
5920 &preedit_string, &preedit_attrs, NULL);
5921 preedit_length = priv->preedit_length;
5923 else if (placeholder_layout)
5926 PangoAttribute *attr;
5928 gtk_entry_get_placeholder_text_color (entry, &color);
5929 attr = pango_attr_foreground_new (color.red, color.green, color.blue);
5930 attr->start_index = 0;
5931 attr->end_index = G_MAXINT;
5932 pango_attr_list_insert (tmp_attrs, attr);
5937 GString *tmp_string = g_string_new (display);
5938 gint cursor_index = g_utf8_offset_to_pointer (display, priv->current_pos) - display;
5940 g_string_insert (tmp_string, cursor_index, preedit_string);
5941 pango_layout_set_text (layout, tmp_string->str, tmp_string->len);
5942 pango_attr_list_splice (tmp_attrs, preedit_attrs,
5943 cursor_index, preedit_length);
5944 g_string_free (tmp_string, TRUE);
5948 PangoDirection pango_dir;
5950 if (gtk_entry_get_display_mode (entry) == DISPLAY_NORMAL)
5951 pango_dir = pango_find_base_dir (display, n_bytes);
5953 pango_dir = PANGO_DIRECTION_NEUTRAL;
5955 if (pango_dir == PANGO_DIRECTION_NEUTRAL)
5957 if (gtk_widget_has_focus (widget))
5959 GdkDisplay *display = gtk_widget_get_display (widget);
5960 GdkKeymap *keymap = gdk_keymap_get_for_display (display);
5961 if (gdk_keymap_get_direction (keymap) == PANGO_DIRECTION_RTL)
5962 pango_dir = PANGO_DIRECTION_RTL;
5964 pango_dir = PANGO_DIRECTION_LTR;
5968 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
5969 pango_dir = PANGO_DIRECTION_RTL;
5971 pango_dir = PANGO_DIRECTION_LTR;
5975 pango_context_set_base_dir (gtk_widget_get_pango_context (widget),
5978 priv->resolved_dir = pango_dir;
5980 pango_layout_set_text (layout, display, n_bytes);
5983 pango_layout_set_attributes (layout, tmp_attrs);
5985 g_free (preedit_string);
5989 pango_attr_list_unref (preedit_attrs);
5991 pango_attr_list_unref (tmp_attrs);
5996 static PangoLayout *
5997 gtk_entry_ensure_layout (GtkEntry *entry,
5998 gboolean include_preedit)
6000 GtkEntryPrivate *priv = entry->priv;
6002 if (priv->preedit_length > 0 &&
6003 !include_preedit != !priv->cache_includes_preedit)
6004 gtk_entry_reset_layout (entry);
6006 if (!priv->cached_layout)
6008 priv->cached_layout = gtk_entry_create_layout (entry, include_preedit);
6009 priv->cache_includes_preedit = include_preedit;
6012 return priv->cached_layout;
6016 get_layout_position (GtkEntry *entry,
6020 GtkEntryPrivate *priv = entry->priv;
6021 PangoLayout *layout;
6022 PangoRectangle logical_rect;
6023 gint area_width, area_height;
6025 PangoLayoutLine *line;
6027 layout = gtk_entry_ensure_layout (entry, TRUE);
6029 get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
6030 area_height = PANGO_SCALE * area_height;
6032 line = pango_layout_get_lines_readonly (layout)->data;
6033 pango_layout_line_get_extents (line, NULL, &logical_rect);
6035 /* Align primarily for locale's ascent/descent */
6036 y_pos = ((area_height - priv->ascent - priv->descent) / 2 +
6037 priv->ascent + logical_rect.y);
6039 /* Now see if we need to adjust to fit in actual drawn string */
6040 if (logical_rect.height > area_height)
6041 y_pos = (area_height - logical_rect.height) / 2;
6044 else if (y_pos + logical_rect.height > area_height)
6045 y_pos = area_height - logical_rect.height;
6047 y_pos = y_pos / PANGO_SCALE;
6050 *x = - priv->scroll_offset;
6057 draw_text_with_color (GtkEntry *entry,
6059 GdkRGBA *default_color)
6061 GtkEntryPrivate *priv = entry->priv;
6062 PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
6065 gint start_pos, end_pos;
6067 widget = GTK_WIDGET (entry);
6071 get_layout_position (entry, &x, &y);
6073 cairo_move_to (cr, x, y);
6074 gdk_cairo_set_source_rgba (cr, default_color);
6075 pango_cairo_show_layout (cr, layout);
6077 if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos))
6081 PangoRectangle logical_rect;
6082 GdkRGBA selection_color, text_color;
6083 GtkStyleContext *context;
6084 GtkStateFlags state;
6086 context = gtk_widget_get_style_context (widget);
6087 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
6088 gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges);
6090 state = gtk_widget_get_state_flags (widget);
6091 state |= GTK_STATE_FLAG_SELECTED;
6093 gtk_style_context_get_background_color (context, state, &selection_color);
6094 gtk_style_context_get_color (context, state, &text_color);
6096 for (i = 0; i < n_ranges; ++i)
6097 cairo_rectangle (cr,
6098 - priv->scroll_offset + ranges[2 * i],
6101 logical_rect.height);
6105 gdk_cairo_set_source_rgba (cr, &selection_color);
6108 cairo_move_to (cr, x, y);
6109 gdk_cairo_set_source_rgba (cr, &text_color);
6110 pango_cairo_show_layout (cr, layout);
6118 gtk_entry_draw_text (GtkEntry *entry,
6121 GtkEntryPrivate *priv = entry->priv;
6122 GtkWidget *widget = GTK_WIDGET (entry);
6123 GtkStateFlags state = 0;
6124 GdkRGBA text_color, bar_text_color;
6125 GtkStyleContext *context;
6127 gint progress_x, progress_y, progress_width, progress_height;
6128 gint clip_width, clip_height;
6130 /* Nothing to display at all */
6131 if (gtk_entry_get_display_mode (entry) == DISPLAY_BLANK)
6134 state = gtk_widget_get_state_flags (widget);
6135 context = gtk_widget_get_style_context (widget);
6137 gtk_style_context_get_color (context, state, &text_color);
6139 /* Get foreground color for progressbars */
6140 gtk_entry_prepare_context_for_progress (entry, context);
6141 gtk_style_context_get_color (context, state, &bar_text_color);
6142 gtk_style_context_restore (context);
6144 get_progress_area (widget,
6145 &progress_x, &progress_y,
6146 &progress_width, &progress_height);
6150 clip_width = gdk_window_get_width (priv->text_area);
6151 clip_height = gdk_window_get_height (priv->text_area);
6152 cairo_rectangle (cr, 0, 0, clip_width, clip_height);
6155 /* If the color is the same, or the progress area has a zero
6156 * size, then we only need to draw once. */
6157 if (gdk_rgba_equal (&text_color, &bar_text_color) ||
6158 ((progress_width == 0) || (progress_height == 0)))
6160 draw_text_with_color (entry, cr, &text_color);
6164 int frame_x, frame_y, area_x, area_y;
6166 width = gdk_window_get_width (priv->text_area);
6167 height = gdk_window_get_height (priv->text_area);
6171 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
6172 cairo_rectangle (cr, 0, 0, width, height);
6174 /* progres area is frame-relative, we need it text-area window
6176 get_frame_size (entry, TRUE, &frame_x, &frame_y, NULL, NULL);
6177 gdk_window_get_position (priv->text_area, &area_x, &area_y);
6178 progress_x += frame_x - area_x;
6179 progress_y += frame_y - area_y;
6181 cairo_rectangle (cr, progress_x, progress_y,
6182 progress_width, progress_height);
6184 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
6186 draw_text_with_color (entry, cr, &text_color);
6191 cairo_rectangle (cr, progress_x, progress_y,
6192 progress_width, progress_height);
6195 draw_text_with_color (entry, cr, &bar_text_color);
6204 gtk_entry_draw_cursor (GtkEntry *entry,
6208 GtkEntryPrivate *priv = entry->priv;
6209 GtkWidget *widget = GTK_WIDGET (entry);
6210 GtkStyleContext *context;
6211 PangoRectangle cursor_rect;
6214 gboolean block_at_line_end;
6215 PangoLayout *layout;
6219 context = gtk_widget_get_style_context (widget);
6221 layout = gtk_entry_ensure_layout (entry, TRUE);
6222 text = pango_layout_get_text (layout);
6223 cursor_index = g_utf8_offset_to_pointer (text, priv->current_pos + priv->preedit_cursor) - text;
6224 get_layout_position (entry, &x, &y);
6226 if (!priv->overwrite_mode)
6229 block = _gtk_text_util_get_block_cursor_location (layout,
6230 cursor_index, &cursor_rect, &block_at_line_end);
6234 gtk_render_insertion_cursor (context, cr,
6236 layout, cursor_index, priv->resolved_dir);
6238 else /* overwrite_mode */
6240 GdkRGBA cursor_color;
6245 rect.x = PANGO_PIXELS (cursor_rect.x) + x;
6246 rect.y = PANGO_PIXELS (cursor_rect.y) + y;
6247 rect.width = PANGO_PIXELS (cursor_rect.width);
6248 rect.height = PANGO_PIXELS (cursor_rect.height);
6250 _gtk_style_context_get_cursor_color (context, &cursor_color, NULL);
6251 gdk_cairo_set_source_rgba (cr, &cursor_color);
6252 gdk_cairo_rectangle (cr, &rect);
6255 if (!block_at_line_end)
6257 GtkStateFlags state;
6260 state = gtk_widget_get_state_flags (widget);
6261 gtk_style_context_get_background_color (context, state, &color);
6263 gdk_cairo_rectangle (cr, &rect);
6265 cairo_move_to (cr, x, y);
6266 gdk_cairo_set_source_rgba (cr, &color);
6267 pango_cairo_show_layout (cr, layout);
6275 gtk_entry_handle_dragged (GtkTextHandle *handle,
6276 GtkTextHandlePosition pos,
6281 gint cursor_pos, selection_bound_pos, tmp_pos;
6282 GtkEntryPrivate *priv = entry->priv;
6283 GtkTextHandleMode mode;
6286 gtk_entry_selection_bubble_popup_unset (entry);
6288 cursor_pos = priv->current_pos;
6289 selection_bound_pos = priv->selection_bound;
6290 mode = _gtk_text_handle_get_mode (handle);
6291 tmp_pos = gtk_entry_find_position (entry, x + priv->scroll_offset);
6293 if (mode == GTK_TEXT_HANDLE_MODE_CURSOR ||
6294 cursor_pos >= selection_bound_pos)
6297 min = &selection_bound_pos;
6301 max = &selection_bound_pos;
6305 if (pos == GTK_TEXT_HANDLE_POSITION_SELECTION_END)
6307 if (mode == GTK_TEXT_HANDLE_MODE_SELECTION)
6311 min_pos = MAX (*min + 1, 0);
6312 tmp_pos = MAX (tmp_pos, min_pos);
6319 if (mode == GTK_TEXT_HANDLE_MODE_SELECTION)
6324 *min = MIN (tmp_pos, max_pos);
6328 if (cursor_pos != priv->current_pos ||
6329 selection_bound_pos != priv->selection_bound)
6331 if (mode == GTK_TEXT_HANDLE_MODE_CURSOR)
6332 gtk_entry_set_positions (entry, cursor_pos, cursor_pos);
6334 gtk_entry_set_positions (entry, cursor_pos, selection_bound_pos);
6336 gtk_entry_update_handles (entry, mode);
6341 gtk_entry_handle_drag_finished (GtkTextHandle *handle,
6342 GtkTextHandlePosition pos,
6345 gtk_entry_selection_bubble_popup_set (entry);
6350 * gtk_entry_reset_im_context:
6351 * @entry: a #GtkEntry
6353 * Reset the input method context of the entry if needed.
6355 * This can be necessary in the case where modifying the buffer
6356 * would confuse on-going input method behavior.
6361 gtk_entry_reset_im_context (GtkEntry *entry)
6363 GtkEntryPrivate *priv = entry->priv;
6365 g_return_if_fail (GTK_IS_ENTRY (entry));
6367 if (priv->need_im_reset)
6369 priv->need_im_reset = FALSE;
6370 gtk_im_context_reset (priv->im_context);
6375 * gtk_entry_im_context_filter_keypress:
6376 * @entry: a #GtkEntry
6377 * @event: (type Gdk.EventKey): the key event
6379 * Allow the #GtkEntry input method to internally handle key press
6380 * and release events. If this function returns %TRUE, then no further
6381 * processing should be done for this key event. See
6382 * gtk_im_context_filter_keypress().
6384 * Note that you are expected to call this function from your handler
6385 * when overriding key event handling. This is needed in the case when
6386 * you need to insert your own key handling between the input method
6387 * and the default key event handling of the #GtkEntry.
6388 * See gtk_text_view_reset_im_context() for an example of use.
6390 * Return value: %TRUE if the input method handled the key event.
6395 gtk_entry_im_context_filter_keypress (GtkEntry *entry,
6398 GtkEntryPrivate *priv;
6400 g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
6404 return gtk_im_context_filter_keypress (priv->im_context, event);
6408 _gtk_entry_get_im_context (GtkEntry *entry)
6410 return entry->priv->im_context;
6414 gtk_entry_find_position (GtkEntry *entry,
6417 GtkEntryPrivate *priv = entry->priv;
6418 PangoLayout *layout;
6419 PangoLayoutLine *line;
6426 layout = gtk_entry_ensure_layout (entry, TRUE);
6427 text = pango_layout_get_text (layout);
6428 cursor_index = g_utf8_offset_to_pointer (text, priv->current_pos) - text;
6430 line = pango_layout_get_lines_readonly (layout)->data;
6431 pango_layout_line_x_to_index (line, x * PANGO_SCALE, &index, &trailing);
6433 if (index >= cursor_index && priv->preedit_length)
6435 if (index >= cursor_index + priv->preedit_length)
6436 index -= priv->preedit_length;
6439 index = cursor_index;
6444 pos = g_utf8_pointer_to_offset (text, text + index);
6451 gtk_entry_get_cursor_locations (GtkEntry *entry,
6456 GtkEntryPrivate *priv = entry->priv;
6457 DisplayMode mode = gtk_entry_get_display_mode (entry);
6459 /* Nothing to display at all, so no cursor is relevant */
6460 if (mode == DISPLAY_BLANK)
6470 PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
6471 const gchar *text = pango_layout_get_text (layout);
6472 PangoRectangle strong_pos, weak_pos;
6475 if (type == CURSOR_STANDARD)
6477 index = g_utf8_offset_to_pointer (text, priv->current_pos + priv->preedit_cursor) - text;
6479 else /* type == CURSOR_DND */
6481 index = g_utf8_offset_to_pointer (text, priv->dnd_position) - text;
6483 if (priv->dnd_position > priv->current_pos)
6485 if (mode == DISPLAY_NORMAL)
6486 index += priv->preedit_length;
6489 gint preedit_len_chars = g_utf8_strlen (text, -1) - gtk_entry_buffer_get_length (get_buffer (entry));
6490 index += preedit_len_chars * g_unichar_to_utf8 (priv->invisible_char, NULL);
6495 pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos);
6498 *strong_x = strong_pos.x / PANGO_SCALE;
6501 *weak_x = weak_pos.x / PANGO_SCALE;
6506 gtk_entry_get_is_selection_handle_dragged (GtkEntry *entry)
6508 GtkEntryPrivate *priv = entry->priv;
6509 GtkTextHandlePosition pos;
6511 if (_gtk_text_handle_get_mode (priv->text_handle) != GTK_TEXT_HANDLE_MODE_SELECTION)
6514 if (priv->current_pos >= priv->selection_bound)
6515 pos = GTK_TEXT_HANDLE_POSITION_SELECTION_START;
6517 pos = GTK_TEXT_HANDLE_POSITION_SELECTION_END;
6519 return _gtk_text_handle_get_is_dragged (priv->text_handle, pos);
6523 gtk_entry_adjust_scroll (GtkEntry *entry)
6525 GtkEntryPrivate *priv = entry->priv;
6526 gint min_offset, max_offset;
6527 gint text_area_width, text_width;
6528 gint strong_x, weak_x;
6529 gint strong_xoffset, weak_xoffset;
6531 PangoLayout *layout;
6532 PangoLayoutLine *line;
6533 PangoRectangle logical_rect;
6534 GtkTextHandleMode handle_mode;
6536 if (!gtk_widget_get_realized (GTK_WIDGET (entry)))
6539 text_area_width = gdk_window_get_width (priv->text_area);
6541 if (text_area_width < 0)
6542 text_area_width = 0;
6544 layout = gtk_entry_ensure_layout (entry, TRUE);
6545 line = pango_layout_get_lines_readonly (layout)->data;
6547 pango_layout_line_get_extents (line, NULL, &logical_rect);
6549 /* Display as much text as we can */
6551 if (priv->resolved_dir == PANGO_DIRECTION_LTR)
6552 xalign = priv->xalign;
6554 xalign = 1.0 - priv->xalign;
6556 text_width = PANGO_PIXELS(logical_rect.width);
6558 if (text_width > text_area_width)
6561 max_offset = text_width - text_area_width;
6565 min_offset = (text_width - text_area_width) * xalign;
6566 max_offset = min_offset;
6569 priv->scroll_offset = CLAMP (priv->scroll_offset, min_offset, max_offset);
6571 if (gtk_entry_get_is_selection_handle_dragged (entry))
6573 /* The text handle corresponding to the selection bound is
6574 * being dragged, ensure it stays onscreen even if we scroll
6575 * cursors away, this is so both handles can cause content
6578 strong_x = weak_x = gtk_entry_get_selection_bound_location (entry);
6582 /* And make sure cursors are on screen. Note that the cursor is
6583 * actually drawn one pixel into the INNER_BORDER space on
6584 * the right, when the scroll is at the utmost right. This
6585 * looks better to to me than confining the cursor inside the
6586 * border entirely, though it means that the cursor gets one
6587 * pixel closer to the edge of the widget on the right than
6588 * on the left. This might need changing if one changed
6589 * INNER_BORDER from 2 to 1, as one would do on a
6590 * small-screen-real-estate display.
6592 * We always make sure that the strong cursor is on screen, and
6593 * put the weak cursor on screen if possible.
6595 gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &strong_x, &weak_x);
6598 strong_xoffset = strong_x - priv->scroll_offset;
6600 if (strong_xoffset < 0)
6602 priv->scroll_offset += strong_xoffset;
6605 else if (strong_xoffset > text_area_width)
6607 priv->scroll_offset += strong_xoffset - text_area_width;
6608 strong_xoffset = text_area_width;
6611 weak_xoffset = weak_x - priv->scroll_offset;
6613 if (weak_xoffset < 0 && strong_xoffset - weak_xoffset <= text_area_width)
6615 priv->scroll_offset += weak_xoffset;
6617 else if (weak_xoffset > text_area_width &&
6618 strong_xoffset - (weak_xoffset - text_area_width) >= 0)
6620 priv->scroll_offset += weak_xoffset - text_area_width;
6623 g_object_notify (G_OBJECT (entry), "scroll-offset");
6625 handle_mode = _gtk_text_handle_get_mode (priv->text_handle);
6627 if (handle_mode != GTK_TEXT_HANDLE_MODE_NONE)
6628 gtk_entry_update_handles (entry, handle_mode);
6632 gtk_entry_move_adjustments (GtkEntry *entry)
6634 GtkWidget *widget = GTK_WIDGET (entry);
6635 GtkAllocation allocation;
6636 GtkAdjustment *adjustment;
6637 PangoContext *context;
6638 PangoFontMetrics *metrics;
6643 adjustment = g_object_get_qdata (G_OBJECT (entry), quark_cursor_hadjustment);
6647 gtk_widget_get_allocation (widget, &allocation);
6649 /* Cursor/char position, layout offset, border width, and widget allocation */
6650 gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &x, NULL);
6651 get_layout_position (entry, &layout_x, NULL);
6652 _gtk_entry_get_borders (entry, &borders);
6653 x += allocation.x + layout_x + borders.left;
6655 /* Approximate width of a char, so user can see what is ahead/behind */
6656 context = gtk_widget_get_pango_context (widget);
6658 metrics = pango_context_get_metrics (context,
6659 pango_context_get_font_description (context),
6660 pango_context_get_language (context));
6661 char_width = pango_font_metrics_get_approximate_char_width (metrics) / PANGO_SCALE;
6664 gtk_adjustment_clamp_page (adjustment,
6665 x - (char_width + 1), /* one char + one pixel before */
6666 x + (char_width + 2)); /* one char + cursor + one pixel after */
6670 gtk_entry_move_visually (GtkEntry *entry,
6674 GtkEntryPrivate *priv = entry->priv;
6676 PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
6679 text = pango_layout_get_text (layout);
6681 index = g_utf8_offset_to_pointer (text, start) - text;
6685 int new_index, new_trailing;
6686 gboolean split_cursor;
6689 g_object_get (gtk_widget_get_settings (GTK_WIDGET (entry)),
6690 "gtk-split-cursor", &split_cursor,
6697 GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (entry)));
6698 PangoDirection keymap_direction = gdk_keymap_get_direction (keymap);
6700 strong = keymap_direction == priv->resolved_dir;
6705 pango_layout_move_cursor_visually (layout, strong, index, 0, 1, &new_index, &new_trailing);
6710 pango_layout_move_cursor_visually (layout, strong, index, 0, -1, &new_index, &new_trailing);
6716 else if (new_index != G_MAXINT)
6719 while (new_trailing--)
6720 index = g_utf8_next_char (text + index) - text;
6723 return g_utf8_pointer_to_offset (text, text + index);
6727 gtk_entry_move_logically (GtkEntry *entry,
6731 gint new_pos = start;
6734 length = gtk_entry_buffer_get_length (get_buffer (entry));
6736 /* Prevent any leak of information */
6737 if (gtk_entry_get_display_mode (entry) != DISPLAY_NORMAL)
6739 new_pos = CLAMP (start + count, 0, length);
6743 PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
6744 PangoLogAttr *log_attrs;
6747 pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
6749 while (count > 0 && new_pos < length)
6753 while (new_pos < length && !log_attrs[new_pos].is_cursor_position);
6757 while (count < 0 && new_pos > 0)
6761 while (new_pos > 0 && !log_attrs[new_pos].is_cursor_position);
6773 gtk_entry_move_forward_word (GtkEntry *entry,
6775 gboolean allow_whitespace)
6777 gint new_pos = start;
6780 length = gtk_entry_buffer_get_length (get_buffer (entry));
6782 /* Prevent any leak of information */
6783 if (gtk_entry_get_display_mode (entry) != DISPLAY_NORMAL)
6787 else if (new_pos < length)
6789 PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
6790 PangoLogAttr *log_attrs;
6793 pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
6795 /* Find the next word boundary */
6797 while (new_pos < n_attrs - 1 && !(log_attrs[new_pos].is_word_end ||
6798 (log_attrs[new_pos].is_word_start && allow_whitespace)))
6809 gtk_entry_move_backward_word (GtkEntry *entry,
6811 gboolean allow_whitespace)
6813 gint new_pos = start;
6815 /* Prevent any leak of information */
6816 if (gtk_entry_get_display_mode (entry) != DISPLAY_NORMAL)
6822 PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
6823 PangoLogAttr *log_attrs;
6826 pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
6828 new_pos = start - 1;
6830 /* Find the previous word boundary */
6831 while (new_pos > 0 && !(log_attrs[new_pos].is_word_start ||
6832 (log_attrs[new_pos].is_word_end && allow_whitespace)))
6842 gtk_entry_delete_whitespace (GtkEntry *entry)
6844 GtkEntryPrivate *priv = entry->priv;
6845 PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
6846 PangoLogAttr *log_attrs;
6850 pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
6852 start = end = priv->current_pos;
6854 while (start > 0 && log_attrs[start-1].is_white)
6857 while (end < n_attrs && log_attrs[end].is_white)
6863 gtk_editable_delete_text (GTK_EDITABLE (entry), start, end);
6868 gtk_entry_select_word (GtkEntry *entry)
6870 GtkEntryPrivate *priv = entry->priv;
6871 gint start_pos = gtk_entry_move_backward_word (entry, priv->current_pos, TRUE);
6872 gint end_pos = gtk_entry_move_forward_word (entry, priv->current_pos, TRUE);
6874 gtk_editable_select_region (GTK_EDITABLE (entry), start_pos, end_pos);
6878 gtk_entry_select_line (GtkEntry *entry)
6880 gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
6884 truncate_multiline (const gchar *text)
6889 text[length] && text[length] != '\n' && text[length] != '\r';
6896 paste_received (GtkClipboard *clipboard,
6900 GtkEntry *entry = GTK_ENTRY (data);
6901 GtkEditable *editable = GTK_EDITABLE (entry);
6902 GtkEntryPrivate *priv = entry->priv;
6904 if (priv->button == GDK_BUTTON_MIDDLE)
6906 gint pos, start, end;
6907 pos = priv->insert_pos;
6908 gtk_editable_get_selection_bounds (editable, &start, &end);
6909 if (!((start <= pos && pos <= end) || (end <= pos && pos <= start)))
6910 gtk_editable_select_region (editable, pos, pos);
6915 gint pos, start, end;
6917 gboolean popup_completion;
6918 GtkEntryCompletion *completion;
6920 completion = gtk_entry_get_completion (entry);
6922 if (priv->truncate_multiline)
6923 length = truncate_multiline (text);
6925 /* only complete if the selection is at the end */
6926 popup_completion = (gtk_entry_buffer_get_length (get_buffer (entry)) ==
6927 MAX (priv->current_pos, priv->selection_bound));
6931 if (gtk_widget_get_mapped (completion->priv->popup_window))
6932 _gtk_entry_completion_popdown (completion);
6934 if (!popup_completion && completion->priv->changed_id > 0)
6935 g_signal_handler_block (entry, completion->priv->changed_id);
6938 begin_change (entry);
6939 if (gtk_editable_get_selection_bounds (editable, &start, &end))
6940 gtk_editable_delete_text (editable, start, end);
6942 pos = priv->current_pos;
6943 gtk_editable_insert_text (editable, text, length, &pos);
6944 gtk_editable_set_position (editable, pos);
6948 !popup_completion && completion->priv->changed_id > 0)
6949 g_signal_handler_unblock (entry, completion->priv->changed_id);
6952 g_object_unref (entry);
6956 gtk_entry_paste (GtkEntry *entry,
6959 g_object_ref (entry);
6960 gtk_clipboard_request_text (gtk_widget_get_clipboard (GTK_WIDGET (entry), selection),
6961 paste_received, entry);
6965 primary_get_cb (GtkClipboard *clipboard,
6966 GtkSelectionData *selection_data,
6970 GtkEntry *entry = GTK_ENTRY (data);
6973 if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start, &end))
6975 gchar *str = _gtk_entry_get_display_text (entry, start, end);
6976 gtk_selection_data_set_text (selection_data, str, -1);
6982 primary_clear_cb (GtkClipboard *clipboard,
6985 GtkEntry *entry = GTK_ENTRY (data);
6986 GtkEntryPrivate *priv = entry->priv;
6988 gtk_editable_select_region (GTK_EDITABLE (entry), priv->current_pos, priv->current_pos);
6992 gtk_entry_update_primary_selection (GtkEntry *entry)
6994 GtkTargetList *list;
6995 GtkTargetEntry *targets;
6996 GtkClipboard *clipboard;
7000 if (!gtk_widget_get_realized (GTK_WIDGET (entry)))
7003 list = gtk_target_list_new (NULL, 0);
7004 gtk_target_list_add_text_targets (list, 0);
7006 targets = gtk_target_table_new_from_list (list, &n_targets);
7008 clipboard = gtk_widget_get_clipboard (GTK_WIDGET (entry), GDK_SELECTION_PRIMARY);
7010 if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start, &end))
7012 if (!gtk_clipboard_set_with_owner (clipboard, targets, n_targets,
7013 primary_get_cb, primary_clear_cb, G_OBJECT (entry)))
7014 primary_clear_cb (clipboard, entry);
7018 if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (entry))
7019 gtk_clipboard_clear (clipboard);
7022 gtk_target_table_free (targets, n_targets);
7023 gtk_target_list_unref (list);
7027 gtk_entry_clear (GtkEntry *entry,
7028 GtkEntryIconPosition icon_pos)
7030 GtkEntryPrivate *priv = entry->priv;
7031 EntryIconInfo *icon_info = priv->icons[icon_pos];
7032 GtkImageType storage_type;
7034 if (icon_info && _gtk_icon_helper_get_is_empty (icon_info->icon_helper))
7037 g_object_freeze_notify (G_OBJECT (entry));
7039 /* Explicitly check, as the pointer may become invalidated
7040 * during destruction.
7042 if (GDK_IS_WINDOW (icon_info->window))
7043 gdk_window_hide (icon_info->window);
7045 storage_type = _gtk_icon_helper_get_storage_type (icon_info->icon_helper);
7047 switch (storage_type)
7049 case GTK_IMAGE_PIXBUF:
7050 g_object_notify (G_OBJECT (entry),
7051 icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-pixbuf" : "secondary-icon-pixbuf");
7054 case GTK_IMAGE_STOCK:
7055 g_object_notify (G_OBJECT (entry),
7056 icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-stock" : "secondary-icon-stock");
7059 case GTK_IMAGE_ICON_NAME:
7060 g_object_notify (G_OBJECT (entry),
7061 icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-name" : "secondary-icon-name");
7064 case GTK_IMAGE_GICON:
7065 g_object_notify (G_OBJECT (entry),
7066 icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-gicon" : "secondary-icon-gicon");
7070 g_assert_not_reached ();
7074 _gtk_icon_helper_clear (icon_info->icon_helper);
7076 g_object_notify (G_OBJECT (entry),
7077 icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-storage-type" : "secondary-icon-storage-type");
7079 g_object_thaw_notify (G_OBJECT (entry));
7083 gtk_entry_ensure_pixbuf (GtkEntry *entry,
7084 GtkEntryIconPosition icon_pos)
7086 GtkEntryPrivate *priv = entry->priv;
7087 EntryIconInfo *icon_info = priv->icons[icon_pos];
7088 GtkStyleContext *context;
7091 context = gtk_widget_get_style_context (GTK_WIDGET (entry));
7092 gtk_entry_prepare_context_for_icon (entry, context, icon_pos);
7094 pix = _gtk_icon_helper_ensure_pixbuf (icon_info->icon_helper,
7097 gtk_style_context_restore (context);
7108 * Creates a new entry.
7110 * Return value: a new #GtkEntry.
7113 gtk_entry_new (void)
7115 return g_object_new (GTK_TYPE_ENTRY, NULL);
7119 * gtk_entry_new_with_buffer:
7120 * @buffer: The buffer to use for the new #GtkEntry.
7122 * Creates a new entry with the specified text buffer.
7124 * Return value: a new #GtkEntry
7129 gtk_entry_new_with_buffer (GtkEntryBuffer *buffer)
7131 g_return_val_if_fail (GTK_IS_ENTRY_BUFFER (buffer), NULL);
7132 return g_object_new (GTK_TYPE_ENTRY, "buffer", buffer, NULL);
7135 static GtkEntryBuffer*
7136 get_buffer (GtkEntry *entry)
7138 GtkEntryPrivate *priv = entry->priv;
7140 if (priv->buffer == NULL)
7142 GtkEntryBuffer *buffer;
7143 buffer = gtk_entry_buffer_new (NULL, 0);
7144 gtk_entry_set_buffer (entry, buffer);
7145 g_object_unref (buffer);
7148 return priv->buffer;
7152 * gtk_entry_get_buffer:
7153 * @entry: a #GtkEntry
7155 * Get the #GtkEntryBuffer object which holds the text for
7160 * Returns: (transfer none): A #GtkEntryBuffer object.
7163 gtk_entry_get_buffer (GtkEntry *entry)
7165 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
7167 return get_buffer (entry);
7171 * gtk_entry_set_buffer:
7172 * @entry: a #GtkEntry
7173 * @buffer: a #GtkEntryBuffer
7175 * Set the #GtkEntryBuffer object which holds the text for
7181 gtk_entry_set_buffer (GtkEntry *entry,
7182 GtkEntryBuffer *buffer)
7184 GtkEntryPrivate *priv;
7187 g_return_if_fail (GTK_IS_ENTRY (entry));
7193 g_return_if_fail (GTK_IS_ENTRY_BUFFER (buffer));
7194 g_object_ref (buffer);
7199 buffer_disconnect_signals (entry);
7200 g_object_unref (priv->buffer);
7203 priv->buffer = buffer;
7206 buffer_connect_signals (entry);
7208 obj = G_OBJECT (entry);
7209 g_object_freeze_notify (obj);
7210 g_object_notify (obj, "buffer");
7211 g_object_notify (obj, "text");
7212 g_object_notify (obj, "text-length");
7213 g_object_notify (obj, "max-length");
7214 g_object_notify (obj, "visibility");
7215 g_object_notify (obj, "invisible-char");
7216 g_object_notify (obj, "invisible-char-set");
7217 g_object_thaw_notify (obj);
7219 gtk_editable_set_position (GTK_EDITABLE (entry), 0);
7220 gtk_entry_recompute (entry);
7224 * gtk_entry_get_text_area:
7225 * @entry: a #GtkEntry
7226 * @text_area: (out): Return location for the text area.
7228 * Gets the area where the entry's text is drawn. This function is
7229 * useful when drawing something to the entry in a draw callback.
7231 * If the entry is not realized, @text_area is filled with zeros.
7233 * See also gtk_entry_get_icon_area().
7238 gtk_entry_get_text_area (GtkEntry *entry,
7239 GdkRectangle *text_area)
7241 GtkEntryPrivate *priv;
7243 g_return_if_fail (GTK_IS_ENTRY (entry));
7244 g_return_if_fail (text_area != NULL);
7248 if (priv->text_area)
7250 GtkAllocation allocation;
7253 gtk_widget_get_allocation (GTK_WIDGET (entry), &allocation);
7254 gdk_window_get_position (priv->text_area, &x, &y);
7256 text_area->x = x - allocation.x;
7257 text_area->y = y - allocation.y;
7258 text_area->width = gdk_window_get_width (priv->text_area);
7259 text_area->height = gdk_window_get_height (priv->text_area);
7265 text_area->width = 0;
7266 text_area->height = 0;
7271 * gtk_entry_set_text:
7272 * @entry: a #GtkEntry
7273 * @text: the new text
7275 * Sets the text in the widget to the given
7276 * value, replacing the current contents.
7278 * See gtk_entry_buffer_set_text().
7281 gtk_entry_set_text (GtkEntry *entry,
7285 GtkEntryCompletion *completion;
7287 g_return_if_fail (GTK_IS_ENTRY (entry));
7288 g_return_if_fail (text != NULL);
7290 /* Actually setting the text will affect the cursor and selection;
7291 * if the contents don't actually change, this will look odd to the user.
7293 if (strcmp (gtk_entry_buffer_get_text (get_buffer (entry)), text) == 0)
7296 completion = gtk_entry_get_completion (entry);
7297 if (completion && completion->priv->changed_id > 0)
7298 g_signal_handler_block (entry, completion->priv->changed_id);
7300 begin_change (entry);
7301 gtk_editable_delete_text (GTK_EDITABLE (entry), 0, -1);
7303 gtk_editable_insert_text (GTK_EDITABLE (entry), text, strlen (text), &tmp_pos);
7306 if (completion && completion->priv->changed_id > 0)
7307 g_signal_handler_unblock (entry, completion->priv->changed_id);
7311 * gtk_entry_set_visibility:
7312 * @entry: a #GtkEntry
7313 * @visible: %TRUE if the contents of the entry are displayed
7316 * Sets whether the contents of the entry are visible or not.
7317 * When visibility is set to %FALSE, characters are displayed
7318 * as the invisible char, and will also appear that way when
7319 * the text in the entry widget is copied elsewhere.
7321 * By default, GTK+ picks the best invisible character available
7322 * in the current font, but it can be changed with
7323 * gtk_entry_set_invisible_char().
7325 * Note that you probably want to set #GtkEntry:input-purpose
7326 * to %GTK_INPUT_PURPOSE_PASSWORD or %GTK_INPUT_PURPOSE_PIN to
7327 * inform input methods about the purpose of this entry,
7328 * in addition to setting visibility to %FALSE.
7331 gtk_entry_set_visibility (GtkEntry *entry,
7334 GtkEntryPrivate *priv;
7336 g_return_if_fail (GTK_IS_ENTRY (entry));
7340 visible = visible != FALSE;
7342 if (priv->visible != visible)
7344 priv->visible = visible;
7346 g_object_notify (G_OBJECT (entry), "visibility");
7347 gtk_entry_recompute (entry);
7352 * gtk_entry_get_visibility:
7353 * @entry: a #GtkEntry
7355 * Retrieves whether the text in @entry is visible. See
7356 * gtk_entry_set_visibility().
7358 * Return value: %TRUE if the text is currently visible
7361 gtk_entry_get_visibility (GtkEntry *entry)
7363 g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
7365 return entry->priv->visible;
7369 * gtk_entry_set_invisible_char:
7370 * @entry: a #GtkEntry
7371 * @ch: a Unicode character
7373 * Sets the character to use in place of the actual text when
7374 * gtk_entry_set_visibility() has been called to set text visibility
7375 * to %FALSE. i.e. this is the character used in "password mode" to
7376 * show the user how many characters have been typed. By default, GTK+
7377 * picks the best invisible char available in the current font. If you
7378 * set the invisible char to 0, then the user will get no feedback
7379 * at all; there will be no text on the screen as they type.
7382 gtk_entry_set_invisible_char (GtkEntry *entry,
7385 GtkEntryPrivate *priv;
7387 g_return_if_fail (GTK_IS_ENTRY (entry));
7391 if (!priv->invisible_char_set)
7393 priv->invisible_char_set = TRUE;
7394 g_object_notify (G_OBJECT (entry), "invisible-char-set");
7397 if (ch == priv->invisible_char)
7400 priv->invisible_char = ch;
7401 g_object_notify (G_OBJECT (entry), "invisible-char");
7402 gtk_entry_recompute (entry);
7406 * gtk_entry_get_invisible_char:
7407 * @entry: a #GtkEntry
7409 * Retrieves the character displayed in place of the real characters
7410 * for entries with visibility set to false. See gtk_entry_set_invisible_char().
7412 * Return value: the current invisible char, or 0, if the entry does not
7413 * show invisible text at all.
7416 gtk_entry_get_invisible_char (GtkEntry *entry)
7418 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
7420 return entry->priv->invisible_char;
7424 * gtk_entry_unset_invisible_char:
7425 * @entry: a #GtkEntry
7427 * Unsets the invisible char previously set with
7428 * gtk_entry_set_invisible_char(). So that the
7429 * default invisible char is used again.
7434 gtk_entry_unset_invisible_char (GtkEntry *entry)
7436 GtkEntryPrivate *priv;
7439 g_return_if_fail (GTK_IS_ENTRY (entry));
7443 if (!priv->invisible_char_set)
7446 priv->invisible_char_set = FALSE;
7447 ch = find_invisible_char (GTK_WIDGET (entry));
7449 if (priv->invisible_char != ch)
7451 priv->invisible_char = ch;
7452 g_object_notify (G_OBJECT (entry), "invisible-char");
7455 g_object_notify (G_OBJECT (entry), "invisible-char-set");
7456 gtk_entry_recompute (entry);
7460 * gtk_entry_set_overwrite_mode:
7461 * @entry: a #GtkEntry
7462 * @overwrite: new value
7464 * Sets whether the text is overwritten when typing in the #GtkEntry.
7469 gtk_entry_set_overwrite_mode (GtkEntry *entry,
7472 GtkEntryPrivate *priv = entry->priv;
7474 g_return_if_fail (GTK_IS_ENTRY (entry));
7476 if (priv->overwrite_mode == overwrite)
7479 gtk_entry_toggle_overwrite (entry);
7481 g_object_notify (G_OBJECT (entry), "overwrite-mode");
7485 * gtk_entry_get_overwrite_mode:
7486 * @entry: a #GtkEntry
7488 * Gets the value set by gtk_entry_set_overwrite_mode().
7490 * Return value: whether the text is overwritten when typing.
7495 gtk_entry_get_overwrite_mode (GtkEntry *entry)
7497 g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
7499 return entry->priv->overwrite_mode;
7503 * gtk_entry_get_text:
7504 * @entry: a #GtkEntry
7506 * Retrieves the contents of the entry widget.
7507 * See also gtk_editable_get_chars().
7509 * This is equivalent to:
7511 * <informalexample><programlisting>
7512 * gtk_entry_buffer_get_text (gtk_entry_get_buffer (entry));
7513 * </programlisting></informalexample>
7515 * Return value: a pointer to the contents of the widget as a
7516 * string. This string points to internally allocated
7517 * storage in the widget and must not be freed, modified or
7521 gtk_entry_get_text (GtkEntry *entry)
7523 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
7525 return gtk_entry_buffer_get_text (get_buffer (entry));
7529 * gtk_entry_set_max_length:
7530 * @entry: a #GtkEntry
7531 * @max: the maximum length of the entry, or 0 for no maximum.
7532 * (other than the maximum length of entries.) The value passed in will
7533 * be clamped to the range 0-65536.
7535 * Sets the maximum allowed length of the contents of the widget. If
7536 * the current contents are longer than the given length, then they
7537 * will be truncated to fit.
7539 * This is equivalent to:
7541 * <informalexample><programlisting>
7542 * gtk_entry_buffer_set_max_length (gtk_entry_get_buffer (entry), max);
7543 * </programlisting></informalexample>
7546 gtk_entry_set_max_length (GtkEntry *entry,
7549 g_return_if_fail (GTK_IS_ENTRY (entry));
7550 gtk_entry_buffer_set_max_length (get_buffer (entry), max);
7554 * gtk_entry_get_max_length:
7555 * @entry: a #GtkEntry
7557 * Retrieves the maximum allowed length of the text in
7558 * @entry. See gtk_entry_set_max_length().
7560 * This is equivalent to:
7562 * <informalexample><programlisting>
7563 * gtk_entry_buffer_get_max_length (gtk_entry_get_buffer (entry));
7564 * </programlisting></informalexample>
7566 * Return value: the maximum allowed number of characters
7567 * in #GtkEntry, or 0 if there is no maximum.
7570 gtk_entry_get_max_length (GtkEntry *entry)
7572 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
7574 return gtk_entry_buffer_get_max_length (get_buffer (entry));
7578 * gtk_entry_get_text_length:
7579 * @entry: a #GtkEntry
7581 * Retrieves the current length of the text in
7584 * This is equivalent to:
7586 * <informalexample><programlisting>
7587 * gtk_entry_buffer_get_length (gtk_entry_get_buffer (entry));
7588 * </programlisting></informalexample>
7590 * Return value: the current number of characters
7591 * in #GtkEntry, or 0 if there are none.
7596 gtk_entry_get_text_length (GtkEntry *entry)
7598 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
7600 return gtk_entry_buffer_get_length (get_buffer (entry));
7604 * gtk_entry_set_activates_default:
7605 * @entry: a #GtkEntry
7606 * @setting: %TRUE to activate window's default widget on Enter keypress
7608 * If @setting is %TRUE, pressing Enter in the @entry will activate the default
7609 * widget for the window containing the entry. This usually means that
7610 * the dialog box containing the entry will be closed, since the default
7611 * widget is usually one of the dialog buttons.
7613 * (For experts: if @setting is %TRUE, the entry calls
7614 * gtk_window_activate_default() on the window containing the entry, in
7615 * the default handler for the #GtkEntry::activate signal.)
7618 gtk_entry_set_activates_default (GtkEntry *entry,
7621 GtkEntryPrivate *priv;
7623 g_return_if_fail (GTK_IS_ENTRY (entry));
7627 setting = setting != FALSE;
7629 if (setting != priv->activates_default)
7631 priv->activates_default = setting;
7632 g_object_notify (G_OBJECT (entry), "activates-default");
7637 * gtk_entry_get_activates_default:
7638 * @entry: a #GtkEntry
7640 * Retrieves the value set by gtk_entry_set_activates_default().
7642 * Return value: %TRUE if the entry will activate the default widget
7645 gtk_entry_get_activates_default (GtkEntry *entry)
7647 g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
7649 return entry->priv->activates_default;
7653 * gtk_entry_set_width_chars:
7654 * @entry: a #GtkEntry
7655 * @n_chars: width in chars
7657 * Changes the size request of the entry to be about the right size
7658 * for @n_chars characters. Note that it changes the size
7659 * <emphasis>request</emphasis>, the size can still be affected by
7660 * how you pack the widget into containers. If @n_chars is -1, the
7661 * size reverts to the default entry size.
7664 gtk_entry_set_width_chars (GtkEntry *entry,
7667 GtkEntryPrivate *priv;
7669 g_return_if_fail (GTK_IS_ENTRY (entry));
7673 if (priv->width_chars != n_chars)
7675 priv->width_chars = n_chars;
7676 g_object_notify (G_OBJECT (entry), "width-chars");
7677 gtk_widget_queue_resize (GTK_WIDGET (entry));
7682 * gtk_entry_get_width_chars:
7683 * @entry: a #GtkEntry
7685 * Gets the value set by gtk_entry_set_width_chars().
7687 * Return value: number of chars to request space for, or negative if unset
7690 gtk_entry_get_width_chars (GtkEntry *entry)
7692 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
7694 return entry->priv->width_chars;
7698 * gtk_entry_set_has_frame:
7699 * @entry: a #GtkEntry
7700 * @setting: new value
7702 * Sets whether the entry has a beveled frame around it.
7705 gtk_entry_set_has_frame (GtkEntry *entry,
7708 GtkEntryPrivate *priv;
7710 g_return_if_fail (GTK_IS_ENTRY (entry));
7714 setting = (setting != FALSE);
7716 if (priv->has_frame == setting)
7719 gtk_widget_queue_resize (GTK_WIDGET (entry));
7720 priv->has_frame = setting;
7721 g_object_notify (G_OBJECT (entry), "has-frame");
7725 * gtk_entry_get_has_frame:
7726 * @entry: a #GtkEntry
7728 * Gets the value set by gtk_entry_set_has_frame().
7730 * Return value: whether the entry has a beveled frame
7733 gtk_entry_get_has_frame (GtkEntry *entry)
7735 g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
7737 return entry->priv->has_frame;
7741 * gtk_entry_set_inner_border:
7742 * @entry: a #GtkEntry
7743 * @border: (allow-none): a #GtkBorder, or %NULL
7745 * Sets %entry's inner-border property to %border, or clears it if %NULL
7746 * is passed. The inner-border is the area around the entry's text, but
7749 * If set, this property overrides the inner-border style property.
7750 * Overriding the style-provided border is useful when you want to do
7751 * in-place editing of some text in a canvas or list widget, where
7752 * pixel-exact positioning of the entry is important.
7756 * Deprecated: 3.4: Use the standard border and padding CSS properties (through
7757 * objects like #GtkStyleContext and #GtkCssProvider); the value set with
7758 * this function is ignored by #GtkEntry.
7761 gtk_entry_set_inner_border (GtkEntry *entry,
7762 const GtkBorder *border)
7764 g_return_if_fail (GTK_IS_ENTRY (entry));
7766 gtk_entry_do_set_inner_border (entry, border);
7770 * gtk_entry_get_inner_border:
7771 * @entry: a #GtkEntry
7773 * This function returns the entry's #GtkEntry:inner-border property. See
7774 * gtk_entry_set_inner_border() for more information.
7776 * Return value: (transfer none): the entry's #GtkBorder, or %NULL if none was set.
7780 * Deprecated: 3.4: Use the standard border and padding CSS properties (through
7781 * objects like #GtkStyleContext and #GtkCssProvider); the value returned by
7782 * this function is ignored by #GtkEntry.
7785 gtk_entry_get_inner_border (GtkEntry *entry)
7787 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
7789 return gtk_entry_do_get_inner_border (entry);
7793 * gtk_entry_get_layout:
7794 * @entry: a #GtkEntry
7796 * Gets the #PangoLayout used to display the entry.
7797 * The layout is useful to e.g. convert text positions to
7798 * pixel positions, in combination with gtk_entry_get_layout_offsets().
7799 * The returned layout is owned by the entry and must not be
7800 * modified or freed by the caller.
7802 * Keep in mind that the layout text may contain a preedit string, so
7803 * gtk_entry_layout_index_to_text_index() and
7804 * gtk_entry_text_index_to_layout_index() are needed to convert byte
7805 * indices in the layout to byte indices in the entry contents.
7807 * Return value: (transfer none): the #PangoLayout for this entry
7810 gtk_entry_get_layout (GtkEntry *entry)
7812 PangoLayout *layout;
7814 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
7816 layout = gtk_entry_ensure_layout (entry, TRUE);
7823 * gtk_entry_layout_index_to_text_index:
7824 * @entry: a #GtkEntry
7825 * @layout_index: byte index into the entry layout text
7827 * Converts from a position in the entry contents (returned
7828 * by gtk_entry_get_text()) to a position in the
7829 * entry's #PangoLayout (returned by gtk_entry_get_layout(),
7830 * with text retrieved via pango_layout_get_text()).
7832 * Return value: byte index into the entry contents
7835 gtk_entry_layout_index_to_text_index (GtkEntry *entry,
7838 GtkEntryPrivate *priv;
7839 PangoLayout *layout;
7843 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
7847 layout = gtk_entry_ensure_layout (entry, TRUE);
7848 text = pango_layout_get_text (layout);
7849 cursor_index = g_utf8_offset_to_pointer (text, priv->current_pos) - text;
7851 if (layout_index >= cursor_index && priv->preedit_length)
7853 if (layout_index >= cursor_index + priv->preedit_length)
7854 layout_index -= priv->preedit_length;
7856 layout_index = cursor_index;
7859 return layout_index;
7863 * gtk_entry_text_index_to_layout_index:
7864 * @entry: a #GtkEntry
7865 * @text_index: byte index into the entry contents
7867 * Converts from a position in the entry's #PangoLayout (returned by
7868 * gtk_entry_get_layout()) to a position in the entry contents
7869 * (returned by gtk_entry_get_text()).
7871 * Return value: byte index into the entry layout text
7874 gtk_entry_text_index_to_layout_index (GtkEntry *entry,
7877 GtkEntryPrivate *priv;
7878 PangoLayout *layout;
7882 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
7886 layout = gtk_entry_ensure_layout (entry, TRUE);
7887 text = pango_layout_get_text (layout);
7888 cursor_index = g_utf8_offset_to_pointer (text, priv->current_pos) - text;
7890 if (text_index > cursor_index)
7891 text_index += priv->preedit_length;
7897 * gtk_entry_get_layout_offsets:
7898 * @entry: a #GtkEntry
7899 * @x: (out) (allow-none): location to store X offset of layout, or %NULL
7900 * @y: (out) (allow-none): location to store Y offset of layout, or %NULL
7903 * Obtains the position of the #PangoLayout used to render text
7904 * in the entry, in widget coordinates. Useful if you want to line
7905 * up the text in an entry with some other text, e.g. when using the
7906 * entry to implement editable cells in a sheet widget.
7908 * Also useful to convert mouse events into coordinates inside the
7909 * #PangoLayout, e.g. to take some action if some part of the entry text
7912 * Note that as the user scrolls around in the entry the offsets will
7913 * change; you'll need to connect to the "notify::scroll-offset"
7914 * signal to track this. Remember when using the #PangoLayout
7915 * functions you need to convert to and from pixels using
7916 * PANGO_PIXELS() or #PANGO_SCALE.
7918 * Keep in mind that the layout text may contain a preedit string, so
7919 * gtk_entry_layout_index_to_text_index() and
7920 * gtk_entry_text_index_to_layout_index() are needed to convert byte
7921 * indices in the layout to byte indices in the entry contents.
7924 gtk_entry_get_layout_offsets (GtkEntry *entry,
7928 gint text_area_x, text_area_y;
7930 g_return_if_fail (GTK_IS_ENTRY (entry));
7932 /* this gets coords relative to text area */
7933 get_layout_position (entry, x, y);
7935 /* convert to widget coords */
7936 gtk_entry_get_text_area_size (entry, &text_area_x, &text_area_y, NULL, NULL);
7947 * gtk_entry_set_alignment:
7948 * @entry: a #GtkEntry
7949 * @xalign: The horizontal alignment, from 0 (left) to 1 (right).
7950 * Reversed for RTL layouts
7952 * Sets the alignment for the contents of the entry. This controls
7953 * the horizontal positioning of the contents when the displayed
7954 * text is shorter than the width of the entry.
7959 gtk_entry_set_alignment (GtkEntry *entry, gfloat xalign)
7961 GtkEntryPrivate *priv;
7963 g_return_if_fail (GTK_IS_ENTRY (entry));
7969 else if (xalign > 1.0)
7972 if (xalign != priv->xalign)
7974 priv->xalign = xalign;
7976 gtk_entry_recompute (entry);
7978 g_object_notify (G_OBJECT (entry), "xalign");
7983 * gtk_entry_get_alignment:
7984 * @entry: a #GtkEntry
7986 * Gets the value set by gtk_entry_set_alignment().
7988 * Return value: the alignment
7993 gtk_entry_get_alignment (GtkEntry *entry)
7995 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0.0);
7997 return entry->priv->xalign;
8001 * gtk_entry_set_icon_from_pixbuf:
8002 * @entry: a #GtkEntry
8003 * @icon_pos: Icon position
8004 * @pixbuf: (allow-none): A #GdkPixbuf, or %NULL
8006 * Sets the icon shown in the specified position using a pixbuf.
8008 * If @pixbuf is %NULL, no icon will be shown in the specified position.
8013 gtk_entry_set_icon_from_pixbuf (GtkEntry *entry,
8014 GtkEntryIconPosition icon_pos,
8017 GtkEntryPrivate *priv;
8018 EntryIconInfo *icon_info;
8020 g_return_if_fail (GTK_IS_ENTRY (entry));
8021 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
8025 if ((icon_info = priv->icons[icon_pos]) == NULL)
8026 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
8028 g_object_freeze_notify (G_OBJECT (entry));
8031 g_object_ref (pixbuf);
8033 gtk_entry_clear (entry, icon_pos);
8037 _gtk_icon_helper_set_pixbuf (icon_info->icon_helper, pixbuf);
8038 _gtk_icon_helper_set_icon_size (icon_info->icon_helper,
8039 GTK_ICON_SIZE_MENU);
8041 if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
8043 g_object_notify (G_OBJECT (entry), "primary-icon-pixbuf");
8044 g_object_notify (G_OBJECT (entry), "primary-icon-storage-type");
8048 g_object_notify (G_OBJECT (entry), "secondary-icon-pixbuf");
8049 g_object_notify (G_OBJECT (entry), "secondary-icon-storage-type");
8052 if (gtk_widget_get_mapped (GTK_WIDGET (entry)))
8053 gdk_window_show_unraised (icon_info->window);
8055 g_object_unref (pixbuf);
8058 if (gtk_widget_get_visible (GTK_WIDGET (entry)))
8059 gtk_widget_queue_resize (GTK_WIDGET (entry));
8061 g_object_thaw_notify (G_OBJECT (entry));
8065 * gtk_entry_set_icon_from_stock:
8066 * @entry: A #GtkEntry
8067 * @icon_pos: Icon position
8068 * @stock_id: (allow-none): The name of the stock item, or %NULL
8070 * Sets the icon shown in the entry at the specified position from
8073 * If @stock_id is %NULL, no icon will be shown in the specified position.
8078 gtk_entry_set_icon_from_stock (GtkEntry *entry,
8079 GtkEntryIconPosition icon_pos,
8080 const gchar *stock_id)
8082 GtkEntryPrivate *priv;
8083 EntryIconInfo *icon_info;
8086 g_return_if_fail (GTK_IS_ENTRY (entry));
8087 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
8091 if ((icon_info = priv->icons[icon_pos]) == NULL)
8092 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
8094 g_object_freeze_notify (G_OBJECT (entry));
8096 /* need to dup before clearing */
8097 new_id = g_strdup (stock_id);
8099 gtk_entry_clear (entry, icon_pos);
8103 _gtk_icon_helper_set_stock_id (icon_info->icon_helper, new_id, GTK_ICON_SIZE_MENU);
8105 if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
8107 g_object_notify (G_OBJECT (entry), "primary-icon-stock");
8108 g_object_notify (G_OBJECT (entry), "primary-icon-storage-type");
8112 g_object_notify (G_OBJECT (entry), "secondary-icon-stock");
8113 g_object_notify (G_OBJECT (entry), "secondary-icon-storage-type");
8116 if (gtk_widget_get_mapped (GTK_WIDGET (entry)))
8117 gdk_window_show_unraised (icon_info->window);
8122 if (gtk_widget_get_visible (GTK_WIDGET (entry)))
8123 gtk_widget_queue_resize (GTK_WIDGET (entry));
8125 g_object_thaw_notify (G_OBJECT (entry));
8129 * gtk_entry_set_icon_from_icon_name:
8130 * @entry: A #GtkEntry
8131 * @icon_pos: The position at which to set the icon
8132 * @icon_name: (allow-none): An icon name, or %NULL
8134 * Sets the icon shown in the entry at the specified position
8135 * from the current icon theme.
8137 * If the icon name isn't known, a "broken image" icon will be displayed
8140 * If @icon_name is %NULL, no icon will be shown in the specified position.
8145 gtk_entry_set_icon_from_icon_name (GtkEntry *entry,
8146 GtkEntryIconPosition icon_pos,
8147 const gchar *icon_name)
8149 GtkEntryPrivate *priv;
8150 EntryIconInfo *icon_info;
8153 g_return_if_fail (GTK_IS_ENTRY (entry));
8154 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
8158 if ((icon_info = priv->icons[icon_pos]) == NULL)
8159 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
8161 g_object_freeze_notify (G_OBJECT (entry));
8163 /* need to dup before clearing */
8164 new_name = g_strdup (icon_name);
8166 gtk_entry_clear (entry, icon_pos);
8168 if (new_name != NULL)
8170 _gtk_icon_helper_set_icon_name (icon_info->icon_helper, new_name, GTK_ICON_SIZE_MENU);
8172 if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
8174 g_object_notify (G_OBJECT (entry), "primary-icon-name");
8175 g_object_notify (G_OBJECT (entry), "primary-icon-storage-type");
8179 g_object_notify (G_OBJECT (entry), "secondary-icon-name");
8180 g_object_notify (G_OBJECT (entry), "secondary-icon-storage-type");
8183 if (gtk_widget_get_mapped (GTK_WIDGET (entry)))
8184 gdk_window_show_unraised (icon_info->window);
8189 if (gtk_widget_get_visible (GTK_WIDGET (entry)))
8190 gtk_widget_queue_resize (GTK_WIDGET (entry));
8192 g_object_thaw_notify (G_OBJECT (entry));
8196 * gtk_entry_set_icon_from_gicon:
8197 * @entry: A #GtkEntry
8198 * @icon_pos: The position at which to set the icon
8199 * @icon: (allow-none): The icon to set, or %NULL
8201 * Sets the icon shown in the entry at the specified position
8202 * from the current icon theme.
8203 * If the icon isn't known, a "broken image" icon will be displayed
8206 * If @icon is %NULL, no icon will be shown in the specified position.
8211 gtk_entry_set_icon_from_gicon (GtkEntry *entry,
8212 GtkEntryIconPosition icon_pos,
8215 GtkEntryPrivate *priv;
8216 EntryIconInfo *icon_info;
8218 g_return_if_fail (GTK_IS_ENTRY (entry));
8219 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
8223 if ((icon_info = priv->icons[icon_pos]) == NULL)
8224 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
8226 g_object_freeze_notify (G_OBJECT (entry));
8228 /* need to ref before clearing */
8230 g_object_ref (icon);
8232 gtk_entry_clear (entry, icon_pos);
8236 _gtk_icon_helper_set_gicon (icon_info->icon_helper, icon, GTK_ICON_SIZE_MENU);
8238 if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
8240 g_object_notify (G_OBJECT (entry), "primary-icon-gicon");
8241 g_object_notify (G_OBJECT (entry), "primary-icon-storage-type");
8245 g_object_notify (G_OBJECT (entry), "secondary-icon-gicon");
8246 g_object_notify (G_OBJECT (entry), "secondary-icon-storage-type");
8249 if (gtk_widget_get_mapped (GTK_WIDGET (entry)))
8250 gdk_window_show_unraised (icon_info->window);
8252 g_object_unref (icon);
8255 if (gtk_widget_get_visible (GTK_WIDGET (entry)))
8256 gtk_widget_queue_resize (GTK_WIDGET (entry));
8258 g_object_thaw_notify (G_OBJECT (entry));
8262 * gtk_entry_set_icon_activatable:
8263 * @entry: A #GtkEntry
8264 * @icon_pos: Icon position
8265 * @activatable: %TRUE if the icon should be activatable
8267 * Sets whether the icon is activatable.
8272 gtk_entry_set_icon_activatable (GtkEntry *entry,
8273 GtkEntryIconPosition icon_pos,
8274 gboolean activatable)
8276 GtkEntryPrivate *priv;
8277 EntryIconInfo *icon_info;
8279 g_return_if_fail (GTK_IS_ENTRY (entry));
8280 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
8284 if ((icon_info = priv->icons[icon_pos]) == NULL)
8285 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
8287 activatable = activatable != FALSE;
8289 if (icon_info->nonactivatable != !activatable)
8291 icon_info->nonactivatable = !activatable;
8293 if (gtk_widget_get_realized (GTK_WIDGET (entry)))
8294 update_cursors (GTK_WIDGET (entry));
8296 g_object_notify (G_OBJECT (entry),
8297 icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-activatable" : "secondary-icon-activatable");
8302 * gtk_entry_get_icon_activatable:
8303 * @entry: a #GtkEntry
8304 * @icon_pos: Icon position
8306 * Returns whether the icon is activatable.
8308 * Returns: %TRUE if the icon is activatable.
8313 gtk_entry_get_icon_activatable (GtkEntry *entry,
8314 GtkEntryIconPosition icon_pos)
8316 GtkEntryPrivate *priv;
8317 EntryIconInfo *icon_info;
8319 g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
8320 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), FALSE);
8323 icon_info = priv->icons[icon_pos];
8325 return (!icon_info || !icon_info->nonactivatable);
8329 * gtk_entry_get_icon_pixbuf:
8330 * @entry: A #GtkEntry
8331 * @icon_pos: Icon position
8333 * Retrieves the image used for the icon.
8335 * Unlike the other methods of setting and getting icon data, this
8336 * method will work regardless of whether the icon was set using a
8337 * #GdkPixbuf, a #GIcon, a stock item, or an icon name.
8339 * Returns: (transfer none): A #GdkPixbuf, or %NULL if no icon is
8340 * set for this position.
8345 gtk_entry_get_icon_pixbuf (GtkEntry *entry,
8346 GtkEntryIconPosition icon_pos)
8348 GtkEntryPrivate *priv;
8349 EntryIconInfo *icon_info;
8352 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
8353 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), NULL);
8357 icon_info = priv->icons[icon_pos];
8362 /* HACK: unfortunately this is transfer none, so we need to return
8363 * the icon helper's cache ref directly.
8365 pixbuf = gtk_entry_ensure_pixbuf (entry, icon_pos);
8367 g_object_unref (pixbuf);
8373 * gtk_entry_get_icon_gicon:
8374 * @entry: A #GtkEntry
8375 * @icon_pos: Icon position
8377 * Retrieves the #GIcon used for the icon, or %NULL if there is
8378 * no icon or if the icon was set by some other method (e.g., by
8379 * stock, pixbuf, or icon name).
8381 * Returns: (transfer none): A #GIcon, or %NULL if no icon is set
8382 * or if the icon is not a #GIcon
8387 gtk_entry_get_icon_gicon (GtkEntry *entry,
8388 GtkEntryIconPosition icon_pos)
8390 GtkEntryPrivate *priv;
8391 EntryIconInfo *icon_info;
8393 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
8394 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), NULL);
8397 icon_info = priv->icons[icon_pos];
8402 return _gtk_icon_helper_peek_gicon (icon_info->icon_helper);
8406 * gtk_entry_get_icon_stock:
8407 * @entry: A #GtkEntry
8408 * @icon_pos: Icon position
8410 * Retrieves the stock id used for the icon, or %NULL if there is
8411 * no icon or if the icon was set by some other method (e.g., by
8412 * pixbuf, icon name or gicon).
8414 * Returns: A stock id, or %NULL if no icon is set or if the icon
8415 * wasn't set from a stock id
8420 gtk_entry_get_icon_stock (GtkEntry *entry,
8421 GtkEntryIconPosition icon_pos)
8423 GtkEntryPrivate *priv;
8424 EntryIconInfo *icon_info;
8426 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
8427 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), NULL);
8430 icon_info = priv->icons[icon_pos];
8435 return _gtk_icon_helper_get_stock_id (icon_info->icon_helper);
8439 * gtk_entry_get_icon_name:
8440 * @entry: A #GtkEntry
8441 * @icon_pos: Icon position
8443 * Retrieves the icon name used for the icon, or %NULL if there is
8444 * no icon or if the icon was set by some other method (e.g., by
8445 * pixbuf, stock or gicon).
8447 * Returns: An icon name, or %NULL if no icon is set or if the icon
8448 * wasn't set from an icon name
8453 gtk_entry_get_icon_name (GtkEntry *entry,
8454 GtkEntryIconPosition icon_pos)
8456 GtkEntryPrivate *priv;
8457 EntryIconInfo *icon_info;
8459 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
8460 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), NULL);
8463 icon_info = priv->icons[icon_pos];
8468 return _gtk_icon_helper_get_icon_name (icon_info->icon_helper);
8472 * gtk_entry_set_icon_sensitive:
8473 * @entry: A #GtkEntry
8474 * @icon_pos: Icon position
8475 * @sensitive: Specifies whether the icon should appear
8476 * sensitive or insensitive
8478 * Sets the sensitivity for the specified icon.
8483 gtk_entry_set_icon_sensitive (GtkEntry *entry,
8484 GtkEntryIconPosition icon_pos,
8487 GtkEntryPrivate *priv;
8488 EntryIconInfo *icon_info;
8490 g_return_if_fail (GTK_IS_ENTRY (entry));
8491 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
8495 if ((icon_info = priv->icons[icon_pos]) == NULL)
8496 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
8498 if (icon_info->insensitive != !sensitive)
8500 icon_info->insensitive = !sensitive;
8502 icon_info->pressed = FALSE;
8503 icon_info->prelight = FALSE;
8505 if (gtk_widget_get_realized (GTK_WIDGET (entry)))
8506 update_cursors (GTK_WIDGET (entry));
8508 gtk_widget_queue_draw (GTK_WIDGET (entry));
8510 g_object_notify (G_OBJECT (entry),
8511 icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-sensitive" : "secondary-icon-sensitive");
8516 * gtk_entry_get_icon_sensitive:
8517 * @entry: a #GtkEntry
8518 * @icon_pos: Icon position
8520 * Returns whether the icon appears sensitive or insensitive.
8522 * Returns: %TRUE if the icon is sensitive.
8527 gtk_entry_get_icon_sensitive (GtkEntry *entry,
8528 GtkEntryIconPosition icon_pos)
8530 GtkEntryPrivate *priv;
8531 EntryIconInfo *icon_info;
8533 g_return_val_if_fail (GTK_IS_ENTRY (entry), TRUE);
8534 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), TRUE);
8538 icon_info = priv->icons[icon_pos];
8540 return (!icon_info || !icon_info->insensitive);
8545 * gtk_entry_get_icon_storage_type:
8546 * @entry: a #GtkEntry
8547 * @icon_pos: Icon position
8549 * Gets the type of representation being used by the icon
8550 * to store image data. If the icon has no image data,
8551 * the return value will be %GTK_IMAGE_EMPTY.
8553 * Return value: image representation being used
8558 gtk_entry_get_icon_storage_type (GtkEntry *entry,
8559 GtkEntryIconPosition icon_pos)
8561 GtkEntryPrivate *priv;
8562 EntryIconInfo *icon_info;
8564 g_return_val_if_fail (GTK_IS_ENTRY (entry), GTK_IMAGE_EMPTY);
8565 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), GTK_IMAGE_EMPTY);
8569 icon_info = priv->icons[icon_pos];
8572 return GTK_IMAGE_EMPTY;
8574 return _gtk_icon_helper_get_storage_type (icon_info->icon_helper);
8578 * gtk_entry_get_icon_at_pos:
8579 * @entry: a #GtkEntry
8580 * @x: the x coordinate of the position to find
8581 * @y: the y coordinate of the position to find
8583 * Finds the icon at the given position and return its index. The
8584 * position's coordinates are relative to the @entry's top left corner.
8585 * If @x, @y doesn't lie inside an icon, -1 is returned.
8586 * This function is intended for use in a #GtkWidget::query-tooltip
8589 * Returns: the index of the icon at the given position, or -1
8594 gtk_entry_get_icon_at_pos (GtkEntry *entry,
8598 GtkAllocation primary;
8599 GtkAllocation secondary;
8600 gint frame_x, frame_y;
8602 g_return_val_if_fail (GTK_IS_ENTRY (entry), -1);
8604 get_frame_size (entry, FALSE, &frame_x, &frame_y, NULL, NULL);
8608 get_icon_allocations (entry, &primary, &secondary);
8610 if (primary.x <= x && x < primary.x + primary.width &&
8611 primary.y <= y && y < primary.y + primary.height)
8612 return GTK_ENTRY_ICON_PRIMARY;
8614 if (secondary.x <= x && x < secondary.x + secondary.width &&
8615 secondary.y <= y && y < secondary.y + secondary.height)
8616 return GTK_ENTRY_ICON_SECONDARY;
8622 * gtk_entry_set_icon_drag_source:
8623 * @entry: a #GtkEntry
8624 * @icon_pos: icon position
8625 * @target_list: the targets (data formats) in which the data can be provided
8626 * @actions: a bitmask of the allowed drag actions
8628 * Sets up the icon at the given position so that GTK+ will start a drag
8629 * operation when the user clicks and drags the icon.
8631 * To handle the drag operation, you need to connect to the usual
8632 * #GtkWidget::drag-data-get (or possibly #GtkWidget::drag-data-delete)
8633 * signal, and use gtk_entry_get_current_icon_drag_source() in
8634 * your signal handler to find out if the drag was started from
8637 * By default, GTK+ uses the icon as the drag icon. You can use the
8638 * #GtkWidget::drag-begin signal to set a different icon. Note that you
8639 * have to use g_signal_connect_after() to ensure that your signal handler
8640 * gets executed after the default handler.
8645 gtk_entry_set_icon_drag_source (GtkEntry *entry,
8646 GtkEntryIconPosition icon_pos,
8647 GtkTargetList *target_list,
8648 GdkDragAction actions)
8650 GtkEntryPrivate *priv;
8651 EntryIconInfo *icon_info;
8653 g_return_if_fail (GTK_IS_ENTRY (entry));
8654 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
8658 if ((icon_info = priv->icons[icon_pos]) == NULL)
8659 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
8661 if (icon_info->target_list)
8662 gtk_target_list_unref (icon_info->target_list);
8663 icon_info->target_list = target_list;
8664 if (icon_info->target_list)
8665 gtk_target_list_ref (icon_info->target_list);
8667 icon_info->actions = actions;
8671 * gtk_entry_get_current_icon_drag_source:
8672 * @entry: a #GtkIconEntry
8674 * Returns the index of the icon which is the source of the current
8675 * DND operation, or -1.
8677 * This function is meant to be used in a #GtkWidget::drag-data-get
8680 * Returns: index of the icon which is the source of the current
8681 * DND operation, or -1.
8686 gtk_entry_get_current_icon_drag_source (GtkEntry *entry)
8688 GtkEntryPrivate *priv;
8689 EntryIconInfo *icon_info = NULL;
8692 g_return_val_if_fail (GTK_IS_ENTRY (entry), -1);
8696 for (i = 0; i < MAX_ICONS; i++)
8698 if ((icon_info = priv->icons[i]))
8700 if (icon_info->in_drag)
8709 * gtk_entry_get_icon_area:
8710 * @entry: A #GtkEntry
8711 * @icon_pos: Icon position
8712 * @icon_area: (out): Return location for the icon's area
8714 * Gets the area where entry's icon at @icon_pos is drawn.
8715 * This function is useful when drawing something to the
8716 * entry in a draw callback.
8718 * If the entry is not realized or has no icon at the given position,
8719 * @icon_area is filled with zeros.
8721 * See also gtk_entry_get_text_area()
8726 gtk_entry_get_icon_area (GtkEntry *entry,
8727 GtkEntryIconPosition icon_pos,
8728 GdkRectangle *icon_area)
8730 GtkEntryPrivate *priv;
8731 EntryIconInfo *icon_info;
8733 g_return_if_fail (GTK_IS_ENTRY (entry));
8734 g_return_if_fail (icon_area != NULL);
8738 icon_info = priv->icons[icon_pos];
8742 GtkAllocation primary;
8743 GtkAllocation secondary;
8745 get_icon_allocations (entry, &primary, &secondary);
8747 if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
8748 *icon_area = primary;
8750 *icon_area = secondary;
8756 icon_area->width = 0;
8757 icon_area->height = 0;
8762 ensure_has_tooltip (GtkEntry *entry)
8764 GtkEntryPrivate *priv;
8765 EntryIconInfo *icon_info;
8767 gboolean has_tooltip = FALSE;
8771 for (i = 0; i < MAX_ICONS; i++)
8773 if ((icon_info = priv->icons[i]) != NULL)
8775 if (icon_info->tooltip != NULL)
8783 gtk_widget_set_has_tooltip (GTK_WIDGET (entry), has_tooltip);
8787 * gtk_entry_get_icon_tooltip_text:
8788 * @entry: a #GtkEntry
8789 * @icon_pos: the icon position
8791 * Gets the contents of the tooltip on the icon at the specified
8792 * position in @entry.
8794 * Returns: the tooltip text, or %NULL. Free the returned string
8795 * with g_free() when done.
8800 gtk_entry_get_icon_tooltip_text (GtkEntry *entry,
8801 GtkEntryIconPosition icon_pos)
8803 GtkEntryPrivate *priv;
8804 EntryIconInfo *icon_info;
8807 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
8808 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), NULL);
8812 icon_info = priv->icons[icon_pos];
8817 if (icon_info->tooltip &&
8818 !pango_parse_markup (icon_info->tooltip, -1, 0, NULL, &text, NULL, NULL))
8819 g_assert (NULL == text); /* text should still be NULL in case of markup errors */
8825 * gtk_entry_set_icon_tooltip_text:
8826 * @entry: a #GtkEntry
8827 * @icon_pos: the icon position
8828 * @tooltip: (allow-none): the contents of the tooltip for the icon, or %NULL
8830 * Sets @tooltip as the contents of the tooltip for the icon
8831 * at the specified position.
8833 * Use %NULL for @tooltip to remove an existing tooltip.
8835 * See also gtk_widget_set_tooltip_text() and
8836 * gtk_entry_set_icon_tooltip_markup().
8841 gtk_entry_set_icon_tooltip_text (GtkEntry *entry,
8842 GtkEntryIconPosition icon_pos,
8843 const gchar *tooltip)
8845 GtkEntryPrivate *priv;
8846 EntryIconInfo *icon_info;
8848 g_return_if_fail (GTK_IS_ENTRY (entry));
8849 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
8853 if ((icon_info = priv->icons[icon_pos]) == NULL)
8854 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
8856 if (icon_info->tooltip)
8857 g_free (icon_info->tooltip);
8859 /* Treat an empty string as a NULL string,
8860 * because an empty string would be useless for a tooltip:
8862 if (tooltip && tooltip[0] == '\0')
8865 icon_info->tooltip = tooltip ? g_markup_escape_text (tooltip, -1) : NULL;
8867 ensure_has_tooltip (entry);
8869 g_object_notify (G_OBJECT (entry),
8870 icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-tooltip-text" : "secondary-icon-tooltip-text");
8874 * gtk_entry_get_icon_tooltip_markup:
8875 * @entry: a #GtkEntry
8876 * @icon_pos: the icon position
8878 * Gets the contents of the tooltip on the icon at the specified
8879 * position in @entry.
8881 * Returns: the tooltip text, or %NULL. Free the returned string
8882 * with g_free() when done.
8887 gtk_entry_get_icon_tooltip_markup (GtkEntry *entry,
8888 GtkEntryIconPosition icon_pos)
8890 GtkEntryPrivate *priv;
8891 EntryIconInfo *icon_info;
8893 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
8894 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), NULL);
8898 icon_info = priv->icons[icon_pos];
8903 return g_strdup (icon_info->tooltip);
8907 * gtk_entry_set_icon_tooltip_markup:
8908 * @entry: a #GtkEntry
8909 * @icon_pos: the icon position
8910 * @tooltip: (allow-none): the contents of the tooltip for the icon, or %NULL
8912 * Sets @tooltip as the contents of the tooltip for the icon at
8913 * the specified position. @tooltip is assumed to be marked up with
8914 * the <link linkend="PangoMarkupFormat">Pango text markup language</link>.
8916 * Use %NULL for @tooltip to remove an existing tooltip.
8918 * See also gtk_widget_set_tooltip_markup() and
8919 * gtk_entry_set_icon_tooltip_text().
8924 gtk_entry_set_icon_tooltip_markup (GtkEntry *entry,
8925 GtkEntryIconPosition icon_pos,
8926 const gchar *tooltip)
8928 GtkEntryPrivate *priv;
8929 EntryIconInfo *icon_info;
8931 g_return_if_fail (GTK_IS_ENTRY (entry));
8932 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
8936 if ((icon_info = priv->icons[icon_pos]) == NULL)
8937 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
8939 if (icon_info->tooltip)
8940 g_free (icon_info->tooltip);
8942 /* Treat an empty string as a NULL string,
8943 * because an empty string would be useless for a tooltip:
8945 if (tooltip && tooltip[0] == '\0')
8948 icon_info->tooltip = g_strdup (tooltip);
8950 ensure_has_tooltip (entry);
8954 gtk_entry_query_tooltip (GtkWidget *widget,
8957 gboolean keyboard_tip,
8958 GtkTooltip *tooltip)
8961 GtkEntryPrivate *priv;
8962 EntryIconInfo *icon_info;
8965 entry = GTK_ENTRY (widget);
8970 icon_pos = gtk_entry_get_icon_at_pos (entry, x, y);
8973 if ((icon_info = priv->icons[icon_pos]) != NULL)
8975 if (icon_info->tooltip)
8977 gtk_tooltip_set_markup (tooltip, icon_info->tooltip);
8986 return GTK_WIDGET_CLASS (gtk_entry_parent_class)->query_tooltip (widget,
8993 /* Quick hack of a popup menu
8996 activate_cb (GtkWidget *menuitem,
8999 const gchar *signal = g_object_get_data (G_OBJECT (menuitem), "gtk-signal");
9000 g_signal_emit_by_name (entry, signal);
9005 gtk_entry_mnemonic_activate (GtkWidget *widget,
9006 gboolean group_cycling)
9008 gtk_widget_grab_focus (widget);
9013 gtk_entry_grab_notify (GtkWidget *widget,
9014 gboolean was_grabbed)
9016 GtkEntryPrivate *priv;
9018 priv = GTK_ENTRY (widget)->priv;
9021 gtk_widget_device_is_shadowed (widget, priv->device))
9023 /* Unset button so we don't expect
9024 * a button release anymore
9027 priv->device = NULL;
9028 priv->in_drag = FALSE;
9033 append_action_signal (GtkEntry *entry,
9035 const gchar *stock_id,
9036 const gchar *signal,
9039 GtkWidget *menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL);
9041 g_object_set_data (G_OBJECT (menuitem), I_("gtk-signal"), (char *)signal);
9042 g_signal_connect (menuitem, "activate",
9043 G_CALLBACK (activate_cb), entry);
9045 gtk_widget_set_sensitive (menuitem, sensitive);
9047 gtk_widget_show (menuitem);
9048 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
9052 popup_menu_detach (GtkWidget *attach_widget,
9055 GtkEntry *entry_attach = GTK_ENTRY (attach_widget);
9056 GtkEntryPrivate *priv_attach = entry_attach->priv;
9058 priv_attach->popup_menu = NULL;
9062 popup_position_func (GtkMenu *menu,
9068 GtkEntry *entry = GTK_ENTRY (user_data);
9069 GtkEntryPrivate *priv = entry->priv;
9070 GtkWidget *widget = GTK_WIDGET (entry);
9072 GtkRequisition menu_req;
9073 GdkRectangle monitor;
9075 gint monitor_num, strong_x, height;
9077 g_return_if_fail (gtk_widget_get_realized (widget));
9079 gdk_window_get_origin (priv->text_area, x, y);
9081 screen = gtk_widget_get_screen (widget);
9082 monitor_num = gdk_screen_get_monitor_at_window (screen, priv->text_area);
9083 if (monitor_num < 0)
9085 gtk_menu_set_monitor (menu, monitor_num);
9087 gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor);
9088 gtk_widget_get_preferred_size (priv->popup_menu,
9090 height = gdk_window_get_height (priv->text_area);
9091 gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &strong_x, NULL);
9092 _gtk_entry_get_borders (entry, &borders);
9094 *x += borders.left + strong_x - priv->scroll_offset;
9095 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
9096 *x -= menu_req.width;
9098 if ((*y + height + menu_req.height) <= monitor.y + monitor.height)
9100 else if ((*y - menu_req.height) >= monitor.y)
9101 *y -= menu_req.height;
9102 else if (monitor.y + monitor.height - (*y + height) > *y)
9105 *y -= menu_req.height;
9111 unichar_chosen_func (const char *text,
9114 GtkEntry *entry = GTK_ENTRY (data);
9115 GtkEntryPrivate *priv = entry->priv;
9118 gtk_entry_enter_text (entry, text);
9130 popup_targets_received (GtkClipboard *clipboard,
9131 GtkSelectionData *data,
9134 PopupInfo *info = user_data;
9135 GtkEntry *entry = info->entry;
9136 GtkEntryPrivate *info_entry_priv = entry->priv;
9138 if (gtk_widget_get_realized (GTK_WIDGET (entry)))
9141 gboolean clipboard_contains_text;
9142 GtkWidget *menuitem;
9144 gboolean show_input_method_menu;
9145 gboolean show_unicode_menu;
9147 clipboard_contains_text = gtk_selection_data_targets_include_text (data);
9148 if (info_entry_priv->popup_menu)
9149 gtk_widget_destroy (info_entry_priv->popup_menu);
9151 info_entry_priv->popup_menu = gtk_menu_new ();
9153 gtk_menu_attach_to_widget (GTK_MENU (info_entry_priv->popup_menu),
9157 mode = gtk_entry_get_display_mode (entry);
9158 append_action_signal (entry, info_entry_priv->popup_menu, GTK_STOCK_CUT, "cut-clipboard",
9159 info_entry_priv->editable && mode == DISPLAY_NORMAL &&
9160 info_entry_priv->current_pos != info_entry_priv->selection_bound);
9162 append_action_signal (entry, info_entry_priv->popup_menu, GTK_STOCK_COPY, "copy-clipboard",
9163 mode == DISPLAY_NORMAL &&
9164 info_entry_priv->current_pos != info_entry_priv->selection_bound);
9166 append_action_signal (entry, info_entry_priv->popup_menu, GTK_STOCK_PASTE, "paste-clipboard",
9167 info_entry_priv->editable && clipboard_contains_text);
9169 menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_DELETE, NULL);
9170 gtk_widget_set_sensitive (menuitem, info_entry_priv->editable && info_entry_priv->current_pos != info_entry_priv->selection_bound);
9171 g_signal_connect_swapped (menuitem, "activate",
9172 G_CALLBACK (gtk_entry_delete_cb), entry);
9173 gtk_widget_show (menuitem);
9174 gtk_menu_shell_append (GTK_MENU_SHELL (info_entry_priv->popup_menu), menuitem);
9176 menuitem = gtk_separator_menu_item_new ();
9177 gtk_widget_show (menuitem);
9178 gtk_menu_shell_append (GTK_MENU_SHELL (info_entry_priv->popup_menu), menuitem);
9180 menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_SELECT_ALL, NULL);
9181 gtk_widget_set_sensitive (menuitem, gtk_entry_buffer_get_length (info_entry_priv->buffer) > 0);
9182 g_signal_connect_swapped (menuitem, "activate",
9183 G_CALLBACK (gtk_entry_select_all), entry);
9184 gtk_widget_show (menuitem);
9185 gtk_menu_shell_append (GTK_MENU_SHELL (info_entry_priv->popup_menu), menuitem);
9187 g_object_get (gtk_widget_get_settings (GTK_WIDGET (entry)),
9188 "gtk-show-input-method-menu", &show_input_method_menu,
9189 "gtk-show-unicode-menu", &show_unicode_menu,
9192 if (show_input_method_menu || show_unicode_menu)
9194 menuitem = gtk_separator_menu_item_new ();
9195 gtk_widget_show (menuitem);
9196 gtk_menu_shell_append (GTK_MENU_SHELL (info_entry_priv->popup_menu), menuitem);
9199 if (show_input_method_menu)
9201 menuitem = gtk_menu_item_new_with_mnemonic (_("Input _Methods"));
9202 gtk_widget_set_sensitive (menuitem, info_entry_priv->editable);
9203 gtk_widget_show (menuitem);
9204 submenu = gtk_menu_new ();
9205 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
9207 gtk_menu_shell_append (GTK_MENU_SHELL (info_entry_priv->popup_menu), menuitem);
9209 gtk_im_multicontext_append_menuitems (GTK_IM_MULTICONTEXT (info_entry_priv->im_context),
9210 GTK_MENU_SHELL (submenu));
9213 if (show_unicode_menu)
9215 menuitem = gtk_menu_item_new_with_mnemonic (_("_Insert Unicode Control Character"));
9216 gtk_widget_set_sensitive (menuitem, info_entry_priv->editable);
9217 gtk_widget_show (menuitem);
9219 submenu = gtk_menu_new ();
9220 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
9221 gtk_menu_shell_append (GTK_MENU_SHELL (info_entry_priv->popup_menu), menuitem);
9223 _gtk_text_util_append_special_char_menuitems (GTK_MENU_SHELL (submenu),
9224 unichar_chosen_func,
9228 g_signal_emit (entry,
9229 signals[POPULATE_POPUP],
9231 info_entry_priv->popup_menu);
9235 gtk_menu_popup_for_device (GTK_MENU (info_entry_priv->popup_menu),
9236 info->device, NULL, NULL, NULL, NULL, NULL,
9237 info->button, info->time);
9240 gtk_menu_popup (GTK_MENU (info_entry_priv->popup_menu), NULL, NULL,
9241 popup_position_func, entry,
9242 0, gtk_get_current_event_time ());
9243 gtk_menu_shell_select_first (GTK_MENU_SHELL (info_entry_priv->popup_menu), FALSE);
9247 g_object_unref (entry);
9248 g_slice_free (PopupInfo, info);
9252 gtk_entry_do_popup (GtkEntry *entry,
9253 GdkEventButton *event)
9255 PopupInfo *info = g_slice_new (PopupInfo);
9257 /* In order to know what entries we should make sensitive, we
9258 * ask for the current targets of the clipboard, and when
9259 * we get them, then we actually pop up the menu.
9261 info->entry = g_object_ref (entry);
9265 info->button = event->button;
9266 info->time = event->time;
9267 info->device = event->device;
9272 info->time = gtk_get_current_event_time ();
9273 info->device = NULL;
9276 gtk_clipboard_request_contents (gtk_widget_get_clipboard (GTK_WIDGET (entry), GDK_SELECTION_CLIPBOARD),
9277 gdk_atom_intern_static_string ("TARGETS"),
9278 popup_targets_received,
9283 gtk_entry_popup_menu (GtkWidget *widget)
9285 gtk_entry_do_popup (GTK_ENTRY (widget), NULL);
9290 activate_bubble_cb (GtkWidget *item,
9293 const gchar *signal = g_object_get_data (G_OBJECT (item), "gtk-signal");
9294 g_signal_emit_by_name (entry, signal);
9295 gtk_bubble_window_popdown (GTK_BUBBLE_WINDOW (entry->priv->selection_bubble));
9299 append_bubble_action (GtkEntry *entry,
9301 const gchar *stock_id,
9302 const gchar *signal,
9305 GtkToolItem *item = gtk_tool_button_new_from_stock (stock_id);
9306 g_object_set_data (G_OBJECT (item), I_("gtk-signal"), (char *)signal);
9307 g_signal_connect (item, "clicked", G_CALLBACK (activate_bubble_cb), entry);
9308 gtk_widget_set_sensitive (GTK_WIDGET (item), sensitive);
9309 gtk_widget_show (GTK_WIDGET (item));
9310 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
9314 bubble_targets_received (GtkClipboard *clipboard,
9315 GtkSelectionData *data,
9318 GtkEntry *entry = user_data;
9319 GtkEntryPrivate *priv = entry->priv;
9320 cairo_rectangle_int_t rect;
9321 GtkAllocation allocation;
9322 gint start_x, end_x;
9323 gboolean has_selection;
9324 gboolean has_clipboard;
9328 has_selection = gtk_editable_get_selection_bounds (GTK_EDITABLE (entry),
9330 if (!has_selection && !priv->editable)
9332 priv->selection_bubble_timeout_id = 0;
9336 if (priv->selection_bubble)
9337 gtk_widget_destroy (priv->selection_bubble);
9339 priv->selection_bubble = gtk_bubble_window_new ();
9340 toolbar = GTK_WIDGET (gtk_toolbar_new ());
9341 gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_TEXT);
9342 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), FALSE);
9343 gtk_widget_show (toolbar);
9344 gtk_container_add (GTK_CONTAINER (priv->selection_bubble), toolbar);
9346 has_clipboard = gtk_selection_data_targets_include_text (data);
9347 mode = gtk_entry_get_display_mode (entry);
9349 append_bubble_action (entry, toolbar, GTK_STOCK_CUT, "cut-clipboard",
9350 priv->editable && has_selection && mode == DISPLAY_NORMAL);
9352 append_bubble_action (entry, toolbar, GTK_STOCK_COPY, "copy-clipboard",
9353 has_selection && mode == DISPLAY_NORMAL);
9355 append_bubble_action (entry, toolbar, GTK_STOCK_PASTE, "paste-clipboard",
9356 priv->editable && has_clipboard);
9358 if (priv->populate_toolbar)
9359 g_signal_emit (entry, signals[POPULATE_POPUP], 0, toolbar);
9361 gtk_widget_get_allocation (GTK_WIDGET (entry), &allocation);
9363 gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &start_x, NULL);
9365 start_x -= priv->scroll_offset;
9366 start_x = CLAMP (start_x, 0, gdk_window_get_width (priv->text_area));
9369 rect.height = gdk_window_get_height (priv->text_area);
9373 end_x = gtk_entry_get_selection_bound_location (entry) - priv->scroll_offset;
9374 end_x = CLAMP (end_x, 0, gdk_window_get_width (priv->text_area));
9376 rect.x = MIN (start_x, end_x);
9377 rect.width = MAX (start_x, end_x) - rect.x;
9385 gtk_bubble_window_popup (GTK_BUBBLE_WINDOW (priv->selection_bubble),
9386 priv->text_area, &rect, GTK_POS_TOP);
9388 priv->selection_bubble_timeout_id = 0;
9392 gtk_entry_selection_bubble_popup_cb (gpointer user_data)
9394 GtkEntry *entry = user_data;
9396 gtk_clipboard_request_contents (gtk_widget_get_clipboard (GTK_WIDGET (entry), GDK_SELECTION_CLIPBOARD),
9397 gdk_atom_intern_static_string ("TARGETS"),
9398 bubble_targets_received,
9400 return G_SOURCE_REMOVE;
9404 gtk_entry_selection_bubble_popup_unset (GtkEntry *entry)
9406 GtkEntryPrivate *priv;
9410 if (priv->selection_bubble)
9411 gtk_bubble_window_popdown (GTK_BUBBLE_WINDOW (priv->selection_bubble));
9413 if (priv->selection_bubble_timeout_id)
9415 g_source_remove (priv->selection_bubble_timeout_id);
9416 priv->selection_bubble_timeout_id = 0;
9421 gtk_entry_selection_bubble_popup_set (GtkEntry *entry)
9423 GtkEntryPrivate *priv;
9427 if (priv->selection_bubble_timeout_id)
9428 g_source_remove (priv->selection_bubble_timeout_id);
9430 priv->selection_bubble_timeout_id =
9431 gdk_threads_add_timeout (1000, gtk_entry_selection_bubble_popup_cb, entry);
9435 gtk_entry_drag_begin (GtkWidget *widget,
9436 GdkDragContext *context)
9438 GtkEntry *entry = GTK_ENTRY (widget);
9439 GtkEntryPrivate *priv = entry->priv;
9442 for (i = 0; i < MAX_ICONS; i++)
9444 EntryIconInfo *icon_info = priv->icons[i];
9446 if (icon_info != NULL)
9448 if (icon_info->in_drag)
9452 pix = _gtk_icon_helper_ensure_pixbuf
9453 (icon_info->icon_helper,
9454 gtk_widget_get_style_context (GTK_WIDGET (entry)));
9455 gtk_drag_set_icon_pixbuf (context, pix, -2, -2);
9457 g_object_unref (pix);
9464 gtk_entry_drag_end (GtkWidget *widget,
9465 GdkDragContext *context)
9467 GtkEntry *entry = GTK_ENTRY (widget);
9468 GtkEntryPrivate *priv = entry->priv;
9471 for (i = 0; i < MAX_ICONS; i++)
9473 EntryIconInfo *icon_info = priv->icons[i];
9475 if (icon_info != NULL)
9476 icon_info->in_drag = 0;
9481 gtk_entry_drag_leave (GtkWidget *widget,
9482 GdkDragContext *context,
9485 GtkEntry *entry = GTK_ENTRY (widget);
9486 GtkEntryPrivate *priv = entry->priv;
9488 priv->dnd_position = -1;
9489 gtk_widget_queue_draw (widget);
9493 gtk_entry_drag_drop (GtkWidget *widget,
9494 GdkDragContext *context,
9499 GtkEntry *entry = GTK_ENTRY (widget);
9500 GtkEntryPrivate *priv = entry->priv;
9501 GdkAtom target = GDK_NONE;
9504 target = gtk_drag_dest_find_target (widget, context, NULL);
9506 if (target != GDK_NONE)
9507 gtk_drag_get_data (widget, context, target, time);
9509 gtk_drag_finish (context, FALSE, FALSE, time);
9515 gtk_entry_drag_motion (GtkWidget *widget,
9516 GdkDragContext *context,
9521 GtkEntry *entry = GTK_ENTRY (widget);
9522 GtkEntryPrivate *priv = entry->priv;
9523 GtkStyleContext *style_context;
9524 GtkWidget *source_widget;
9525 GdkDragAction suggested_action;
9526 gint new_position, old_position;
9530 style_context = gtk_widget_get_style_context (widget);
9531 gtk_style_context_get_padding (style_context, 0, &padding);
9535 old_position = priv->dnd_position;
9536 new_position = gtk_entry_find_position (entry, x + priv->scroll_offset);
9538 if (priv->editable &&
9539 gtk_drag_dest_find_target (widget, context, NULL) != GDK_NONE)
9541 source_widget = gtk_drag_get_source_widget (context);
9542 suggested_action = gdk_drag_context_get_suggested_action (context);
9544 if (!gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &sel1, &sel2) ||
9545 new_position < sel1 || new_position > sel2)
9547 if (source_widget == widget)
9549 /* Default to MOVE, unless the user has
9550 * pressed ctrl or alt to affect available actions
9552 if ((gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE) != 0)
9553 suggested_action = GDK_ACTION_MOVE;
9556 priv->dnd_position = new_position;
9560 if (source_widget == widget)
9561 suggested_action = 0; /* Can't drop in selection where drag started */
9563 priv->dnd_position = -1;
9568 /* Entry not editable, or no text */
9569 suggested_action = 0;
9570 priv->dnd_position = -1;
9573 gdk_drag_status (context, suggested_action, time);
9575 if (priv->dnd_position != old_position)
9576 gtk_widget_queue_draw (widget);
9582 gtk_entry_drag_data_received (GtkWidget *widget,
9583 GdkDragContext *context,
9586 GtkSelectionData *selection_data,
9590 GtkEntry *entry = GTK_ENTRY (widget);
9591 GtkEntryPrivate *priv = entry->priv;
9592 GtkEditable *editable = GTK_EDITABLE (widget);
9593 GtkStyleContext *style_context;
9597 str = (gchar *) gtk_selection_data_get_text (selection_data);
9599 style_context = gtk_widget_get_style_context (widget);
9600 gtk_style_context_get_padding (style_context, 0, &padding);
9604 if (str && priv->editable)
9610 if (priv->truncate_multiline)
9611 length = truncate_multiline (str);
9613 new_position = gtk_entry_find_position (entry, x + priv->scroll_offset);
9615 if (!gtk_editable_get_selection_bounds (editable, &sel1, &sel2) ||
9616 new_position < sel1 || new_position > sel2)
9618 gtk_editable_insert_text (editable, str, length, &new_position);
9622 /* Replacing selection */
9623 begin_change (entry);
9624 gtk_editable_delete_text (editable, sel1, sel2);
9625 gtk_editable_insert_text (editable, str, length, &sel1);
9629 gtk_drag_finish (context, TRUE, gdk_drag_context_get_selected_action (context) == GDK_ACTION_MOVE, time);
9633 /* Drag and drop didn't happen! */
9634 gtk_drag_finish (context, FALSE, FALSE, time);
9641 gtk_entry_drag_data_get (GtkWidget *widget,
9642 GdkDragContext *context,
9643 GtkSelectionData *selection_data,
9647 GtkEntry *entry = GTK_ENTRY (widget);
9648 GtkEntryPrivate *priv = entry->priv;
9649 GtkEditable *editable = GTK_EDITABLE (widget);
9650 gint sel_start, sel_end;
9653 /* If there is an icon drag going on, exit early. */
9654 for (i = 0; i < MAX_ICONS; i++)
9656 EntryIconInfo *icon_info = priv->icons[i];
9658 if (icon_info != NULL)
9660 if (icon_info->in_drag)
9665 if (gtk_editable_get_selection_bounds (editable, &sel_start, &sel_end))
9667 gchar *str = _gtk_entry_get_display_text (GTK_ENTRY (widget), sel_start, sel_end);
9669 gtk_selection_data_set_text (selection_data, str, -1);
9677 gtk_entry_drag_data_delete (GtkWidget *widget,
9678 GdkDragContext *context)
9680 GtkEntry *entry = GTK_ENTRY (widget);
9681 GtkEntryPrivate *priv = entry->priv;
9682 GtkEditable *editable = GTK_EDITABLE (widget);
9683 gint sel_start, sel_end;
9686 /* If there is an icon drag going on, exit early. */
9687 for (i = 0; i < MAX_ICONS; i++)
9689 EntryIconInfo *icon_info = priv->icons[i];
9691 if (icon_info != NULL)
9693 if (icon_info->in_drag)
9698 if (priv->editable &&
9699 gtk_editable_get_selection_bounds (editable, &sel_start, &sel_end))
9700 gtk_editable_delete_text (editable, sel_start, sel_end);
9703 /* We display the cursor when
9705 * - the selection is empty, AND
9706 * - the widget has focus
9709 #define CURSOR_ON_MULTIPLIER 2
9710 #define CURSOR_OFF_MULTIPLIER 1
9711 #define CURSOR_PEND_MULTIPLIER 3
9712 #define CURSOR_DIVIDER 3
9715 cursor_blinks (GtkEntry *entry)
9717 GtkEntryPrivate *priv = entry->priv;
9719 if (gtk_widget_has_focus (GTK_WIDGET (entry)) &&
9721 priv->selection_bound == priv->current_pos)
9723 GtkSettings *settings;
9726 settings = gtk_widget_get_settings (GTK_WIDGET (entry));
9727 g_object_get (settings, "gtk-cursor-blink", &blink, NULL);
9736 get_middle_click_paste (GtkEntry *entry)
9738 GtkSettings *settings;
9741 settings = gtk_widget_get_settings (GTK_WIDGET (entry));
9742 g_object_get (settings, "gtk-enable-primary-paste", &paste, NULL);
9748 get_cursor_time (GtkEntry *entry)
9750 GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (entry));
9753 g_object_get (settings, "gtk-cursor-blink-time", &time, NULL);
9759 get_cursor_blink_timeout (GtkEntry *entry)
9761 GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (entry));
9764 g_object_get (settings, "gtk-cursor-blink-timeout", &timeout, NULL);
9770 show_cursor (GtkEntry *entry)
9772 GtkEntryPrivate *priv = entry->priv;
9775 if (!priv->cursor_visible)
9777 priv->cursor_visible = TRUE;
9779 widget = GTK_WIDGET (entry);
9780 if (gtk_widget_has_focus (widget) && priv->selection_bound == priv->current_pos)
9781 gtk_widget_queue_draw (widget);
9786 hide_cursor (GtkEntry *entry)
9788 GtkEntryPrivate *priv = entry->priv;
9791 if (priv->cursor_visible)
9793 priv->cursor_visible = FALSE;
9795 widget = GTK_WIDGET (entry);
9796 if (gtk_widget_has_focus (widget) && priv->selection_bound == priv->current_pos)
9797 gtk_widget_queue_draw (widget);
9805 blink_cb (gpointer data)
9808 GtkEntryPrivate *priv;
9811 entry = GTK_ENTRY (data);
9814 if (!gtk_widget_has_focus (GTK_WIDGET (entry)))
9816 g_warning ("GtkEntry - did not receive focus-out-event. If you\n"
9817 "connect a handler to this signal, it must return\n"
9818 "FALSE so the entry gets the event as well");
9820 gtk_entry_check_cursor_blink (entry);
9825 g_assert (priv->selection_bound == priv->current_pos);
9827 blink_timeout = get_cursor_blink_timeout (entry);
9828 if (priv->blink_time > 1000 * blink_timeout &&
9829 blink_timeout < G_MAXINT/1000)
9831 /* we've blinked enough without the user doing anything, stop blinking */
9832 show_cursor (entry);
9833 priv->blink_timeout = 0;
9835 else if (priv->cursor_visible)
9837 hide_cursor (entry);
9838 priv->blink_timeout = gdk_threads_add_timeout (get_cursor_time (entry) * CURSOR_OFF_MULTIPLIER / CURSOR_DIVIDER,
9844 show_cursor (entry);
9845 priv->blink_time += get_cursor_time (entry);
9846 priv->blink_timeout = gdk_threads_add_timeout (get_cursor_time (entry) * CURSOR_ON_MULTIPLIER / CURSOR_DIVIDER,
9851 /* Remove ourselves */
9856 gtk_entry_check_cursor_blink (GtkEntry *entry)
9858 GtkEntryPrivate *priv = entry->priv;
9860 if (cursor_blinks (entry))
9862 if (!priv->blink_timeout)
9864 show_cursor (entry);
9865 priv->blink_timeout = gdk_threads_add_timeout (get_cursor_time (entry) * CURSOR_ON_MULTIPLIER / CURSOR_DIVIDER,
9872 if (priv->blink_timeout)
9874 g_source_remove (priv->blink_timeout);
9875 priv->blink_timeout = 0;
9878 priv->cursor_visible = TRUE;
9883 gtk_entry_pend_cursor_blink (GtkEntry *entry)
9885 GtkEntryPrivate *priv = entry->priv;
9887 if (cursor_blinks (entry))
9889 if (priv->blink_timeout != 0)
9890 g_source_remove (priv->blink_timeout);
9892 priv->blink_timeout = gdk_threads_add_timeout (get_cursor_time (entry) * CURSOR_PEND_MULTIPLIER / CURSOR_DIVIDER,
9895 show_cursor (entry);
9900 gtk_entry_reset_blink_time (GtkEntry *entry)
9902 GtkEntryPrivate *priv = entry->priv;
9904 priv->blink_time = 0;
9908 * gtk_entry_set_completion:
9909 * @entry: A #GtkEntry
9910 * @completion: (allow-none): The #GtkEntryCompletion or %NULL
9912 * Sets @completion to be the auxiliary completion object to use with @entry.
9913 * All further configuration of the completion mechanism is done on
9914 * @completion using the #GtkEntryCompletion API. Completion is disabled if
9915 * @completion is set to %NULL.
9920 gtk_entry_set_completion (GtkEntry *entry,
9921 GtkEntryCompletion *completion)
9923 GtkEntryCompletion *old;
9925 g_return_if_fail (GTK_IS_ENTRY (entry));
9926 g_return_if_fail (!completion || GTK_IS_ENTRY_COMPLETION (completion));
9928 old = gtk_entry_get_completion (entry);
9930 if (old == completion)
9935 _gtk_entry_completion_disconnect (old);
9936 g_object_unref (old);
9941 g_object_set_data (G_OBJECT (entry), I_(GTK_ENTRY_COMPLETION_KEY), NULL);
9945 /* hook into the entry */
9946 g_object_ref (completion);
9948 _gtk_entry_completion_connect (completion, entry);
9950 g_object_set_data (G_OBJECT (entry), I_(GTK_ENTRY_COMPLETION_KEY), completion);
9952 g_object_notify (G_OBJECT (entry), "completion");
9956 * gtk_entry_get_completion:
9957 * @entry: A #GtkEntry
9959 * Returns the auxiliary completion object currently in use by @entry.
9961 * Return value: (transfer none): The auxiliary completion object currently
9966 GtkEntryCompletion *
9967 gtk_entry_get_completion (GtkEntry *entry)
9969 GtkEntryCompletion *completion;
9971 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
9973 completion = GTK_ENTRY_COMPLETION (g_object_get_data (G_OBJECT (entry),
9974 GTK_ENTRY_COMPLETION_KEY));
9980 * gtk_entry_set_cursor_hadjustment:
9981 * @entry: a #GtkEntry
9982 * @adjustment: an adjustment which should be adjusted when the cursor
9983 * is moved, or %NULL
9985 * Hooks up an adjustment to the cursor position in an entry, so that when
9986 * the cursor is moved, the adjustment is scrolled to show that position.
9987 * See gtk_scrolled_window_get_hadjustment() for a typical way of obtaining
9990 * The adjustment has to be in pixel units and in the same coordinate system
9996 gtk_entry_set_cursor_hadjustment (GtkEntry *entry,
9997 GtkAdjustment *adjustment)
9999 g_return_if_fail (GTK_IS_ENTRY (entry));
10001 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
10004 g_object_ref (adjustment);
10006 g_object_set_qdata_full (G_OBJECT (entry),
10007 quark_cursor_hadjustment,
10013 * gtk_entry_get_cursor_hadjustment:
10014 * @entry: a #GtkEntry
10016 * Retrieves the horizontal cursor adjustment for the entry.
10017 * See gtk_entry_set_cursor_hadjustment().
10019 * Return value: (transfer none): the horizontal cursor adjustment, or %NULL
10020 * if none has been set.
10025 gtk_entry_get_cursor_hadjustment (GtkEntry *entry)
10027 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
10029 return g_object_get_qdata (G_OBJECT (entry), quark_cursor_hadjustment);
10033 * gtk_entry_set_progress_fraction:
10034 * @entry: a #GtkEntry
10035 * @fraction: fraction of the task that's been completed
10037 * Causes the entry's progress indicator to "fill in" the given
10038 * fraction of the bar. The fraction should be between 0.0 and 1.0,
10044 gtk_entry_set_progress_fraction (GtkEntry *entry,
10048 GtkEntryPrivate *private;
10049 gdouble old_fraction;
10050 gint x, y, width, height;
10051 gint old_x, old_y, old_width, old_height;
10053 g_return_if_fail (GTK_IS_ENTRY (entry));
10055 widget = GTK_WIDGET (entry);
10056 private = entry->priv;
10058 if (private->progress_pulse_mode)
10061 old_fraction = private->progress_fraction;
10063 if (gtk_widget_is_drawable (widget))
10064 get_progress_area (widget, &old_x, &old_y, &old_width, &old_height);
10066 fraction = CLAMP (fraction, 0.0, 1.0);
10068 private->progress_fraction = fraction;
10069 private->progress_pulse_mode = FALSE;
10070 private->progress_pulse_current = 0.0;
10072 if (gtk_widget_is_drawable (widget))
10074 get_progress_area (widget, &x, &y, &width, &height);
10076 if ((x != old_x) || (y != old_y) || (width != old_width) || (height != old_height))
10077 gtk_widget_queue_draw (widget);
10080 if (fraction != old_fraction)
10081 g_object_notify (G_OBJECT (entry), "progress-fraction");
10085 * gtk_entry_get_progress_fraction:
10086 * @entry: a #GtkEntry
10088 * Returns the current fraction of the task that's been completed.
10089 * See gtk_entry_set_progress_fraction().
10091 * Return value: a fraction from 0.0 to 1.0
10096 gtk_entry_get_progress_fraction (GtkEntry *entry)
10098 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0.0);
10100 return entry->priv->progress_fraction;
10104 * gtk_entry_set_progress_pulse_step:
10105 * @entry: a #GtkEntry
10106 * @fraction: fraction between 0.0 and 1.0
10108 * Sets the fraction of total entry width to move the progress
10109 * bouncing block for each call to gtk_entry_progress_pulse().
10114 gtk_entry_set_progress_pulse_step (GtkEntry *entry,
10117 GtkEntryPrivate *private;
10119 g_return_if_fail (GTK_IS_ENTRY (entry));
10121 private = entry->priv;
10123 fraction = CLAMP (fraction, 0.0, 1.0);
10125 if (fraction != private->progress_pulse_fraction)
10127 private->progress_pulse_fraction = fraction;
10129 gtk_widget_queue_draw (GTK_WIDGET (entry));
10131 g_object_notify (G_OBJECT (entry), "progress-pulse-step");
10136 * gtk_entry_get_progress_pulse_step:
10137 * @entry: a #GtkEntry
10139 * Retrieves the pulse step set with gtk_entry_set_progress_pulse_step().
10141 * Return value: a fraction from 0.0 to 1.0
10146 gtk_entry_get_progress_pulse_step (GtkEntry *entry)
10148 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0.0);
10150 return entry->priv->progress_pulse_fraction;
10154 * gtk_entry_progress_pulse:
10155 * @entry: a #GtkEntry
10157 * Indicates that some progress is made, but you don't know how much.
10158 * Causes the entry's progress indicator to enter "activity mode,"
10159 * where a block bounces back and forth. Each call to
10160 * gtk_entry_progress_pulse() causes the block to move by a little bit
10161 * (the amount of movement per pulse is determined by
10162 * gtk_entry_set_progress_pulse_step()).
10167 gtk_entry_progress_pulse (GtkEntry *entry)
10169 GtkEntryPrivate *private;
10171 g_return_if_fail (GTK_IS_ENTRY (entry));
10173 private = entry->priv;
10175 if (private->progress_pulse_mode)
10177 if (private->progress_pulse_way_back)
10179 private->progress_pulse_current -= private->progress_pulse_fraction;
10181 if (private->progress_pulse_current < 0.0)
10183 private->progress_pulse_current = 0.0;
10184 private->progress_pulse_way_back = FALSE;
10189 private->progress_pulse_current += private->progress_pulse_fraction;
10191 if (private->progress_pulse_current > 1.0 - private->progress_pulse_fraction)
10193 private->progress_pulse_current = 1.0 - private->progress_pulse_fraction;
10194 private->progress_pulse_way_back = TRUE;
10200 private->progress_fraction = 0.0;
10201 private->progress_pulse_mode = TRUE;
10202 private->progress_pulse_way_back = FALSE;
10203 private->progress_pulse_current = 0.0;
10206 gtk_widget_queue_draw (GTK_WIDGET (entry));
10210 * gtk_entry_set_placeholder_text:
10211 * @entry: a #GtkEntry
10212 * @text: a string to be displayed when @entry is empty an unfocused, or %NULL
10214 * Sets text to be displayed in @entry when it is empty and unfocused.
10215 * This can be used to give a visual hint of the expected contents of
10218 * Note that since the placeholder text gets removed when the entry
10219 * received focus, using this feature is a bit problematic if the entry
10220 * is given the initial focus in a window. Sometimes this can be
10221 * worked around by delaying the initial focus setting until the
10222 * first key event arrives.
10227 gtk_entry_set_placeholder_text (GtkEntry *entry,
10230 GtkEntryPrivate *priv;
10232 g_return_if_fail (GTK_IS_ENTRY (entry));
10234 priv = entry->priv;
10236 if (g_strcmp0 (priv->placeholder_text, text) == 0)
10239 g_free (priv->placeholder_text);
10240 priv->placeholder_text = g_strdup (text);
10242 gtk_entry_recompute (entry);
10244 g_object_notify (G_OBJECT (entry), "placeholder-text");
10248 * gtk_entry_get_placeholder_text:
10249 * @entry: a #GtkEntry
10251 * Retrieves the text that will be displayed when @entry is empty and unfocused
10253 * Returns: a pointer to the placeholder text as a string. This string points to internally allocated
10254 * storage in the widget and must not be freed, modified or stored.
10259 gtk_entry_get_placeholder_text (GtkEntry *entry)
10261 GtkEntryPrivate *priv;
10263 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
10265 priv = entry->priv;
10267 return priv->placeholder_text;
10270 /* Caps Lock warning for password entries */
10273 show_capslock_feedback (GtkEntry *entry,
10276 GtkEntryPrivate *priv = entry->priv;
10278 if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY)
10280 gtk_entry_set_icon_from_stock (entry, GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CAPS_LOCK_WARNING);
10281 gtk_entry_set_icon_activatable (entry, GTK_ENTRY_ICON_SECONDARY, FALSE);
10282 priv->caps_lock_warning_shown = TRUE;
10285 if (priv->caps_lock_warning_shown)
10286 gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY, text);
10288 g_warning ("Can't show Caps Lock warning, since secondary icon is set");
10292 remove_capslock_feedback (GtkEntry *entry)
10294 GtkEntryPrivate *priv = entry->priv;
10296 if (priv->caps_lock_warning_shown)
10298 gtk_entry_set_icon_from_stock (entry, GTK_ENTRY_ICON_SECONDARY, NULL);
10299 priv->caps_lock_warning_shown = FALSE;
10304 keymap_state_changed (GdkKeymap *keymap,
10307 GtkEntryPrivate *priv = entry->priv;
10310 if (gtk_entry_get_display_mode (entry) != DISPLAY_NORMAL && priv->caps_lock_warning)
10312 if (gdk_keymap_get_caps_lock_state (keymap))
10313 text = _("Caps Lock is on");
10317 show_capslock_feedback (entry, text);
10319 remove_capslock_feedback (entry);
10323 * _gtk_entry_set_is_cell_renderer:
10324 * @entry: a #GtkEntry
10325 * @is_cell_renderer: new value
10327 * This is a helper function for GtkComboBox. A GtkEntry in a GtkComboBox
10328 * is supposed to behave like a GtkCellEditable when placed in a combo box.
10330 * I.e take up its allocation and get GtkEntry->is_cell_renderer = TRUE.
10334 _gtk_entry_set_is_cell_renderer (GtkEntry *entry,
10335 gboolean is_cell_renderer)
10337 entry->priv->is_cell_renderer = is_cell_renderer;
10341 * gtk_entry_set_input_purpose:
10342 * @entry: a #GtkEntry
10343 * @purpose: the purpose
10345 * Sets the #GtkEntry:input-purpose property which
10346 * can be used by on-screen keyboards and other input
10347 * methods to adjust their behaviour.
10352 gtk_entry_set_input_purpose (GtkEntry *entry,
10353 GtkInputPurpose purpose)
10356 g_return_if_fail (GTK_IS_ENTRY (entry));
10358 if (gtk_entry_get_input_purpose (entry) != purpose)
10360 g_object_set (G_OBJECT (entry->priv->im_context),
10361 "input-purpose", purpose,
10364 g_object_notify (G_OBJECT (entry), "input-purpose");
10369 * gtk_entry_get_input_purpose:
10370 * @entry: a #GtkEntry
10372 * Gets the value of the #GtkEntry:input-purpose property.
10377 gtk_entry_get_input_purpose (GtkEntry *entry)
10379 GtkInputPurpose purpose;
10381 g_return_val_if_fail (GTK_IS_ENTRY (entry), GTK_INPUT_PURPOSE_FREE_FORM);
10383 g_object_get (G_OBJECT (entry->priv->im_context),
10384 "input-purpose", &purpose,
10391 * gtk_entry_set_input_hints:
10392 * @entry: a #GtkEntry
10393 * @hints: the hints
10395 * Sets the #GtkEntry:input-hints property, which
10396 * allows input methods to fine-tune their behaviour.
10401 gtk_entry_set_input_hints (GtkEntry *entry,
10402 GtkInputHints hints)
10405 g_return_if_fail (GTK_IS_ENTRY (entry));
10407 if (gtk_entry_get_input_hints (entry) != hints)
10409 g_object_set (G_OBJECT (entry->priv->im_context),
10410 "input-hints", hints,
10413 g_object_notify (G_OBJECT (entry), "input-hints");
10418 * gtk_entry_get_input_hints:
10419 * @entry: a #GtkEntry
10421 * Gets the value of the #GtkEntry:input-hints property.
10426 gtk_entry_get_input_hints (GtkEntry *entry)
10428 GtkInputHints hints;
10430 g_return_val_if_fail (GTK_IS_ENTRY (entry), GTK_INPUT_HINT_NONE);
10432 g_object_get (G_OBJECT (entry->priv->im_context),
10433 "input-hints", &hints,
10440 * gtk_entry_set_attributes:
10441 * @entry: a #GtkEntry
10442 * @attrs: a #PangoAttrList
10444 * Sets a #PangoAttrList; the attributes in the list are applied to the
10450 gtk_entry_set_attributes (GtkEntry *entry,
10451 PangoAttrList *attrs)
10453 GtkEntryPrivate *priv = entry->priv;
10454 g_return_if_fail (GTK_IS_ENTRY (entry));
10457 pango_attr_list_ref (attrs);
10460 pango_attr_list_unref (priv->attrs);
10461 priv->attrs = attrs;
10463 g_object_notify (G_OBJECT (entry), "attributes");
10465 gtk_entry_recompute (entry);
10466 gtk_widget_queue_resize (GTK_WIDGET (entry));
10470 * gtk_entry_get_attributes:
10471 * @entry: a #GtkEntry
10473 * Gets the attribute list that was set on the entry using
10474 * gtk_entry_set_attributes(), if any.
10476 * Return value: (transfer none): the attribute list, or %NULL
10482 gtk_entry_get_attributes (GtkEntry *entry)
10484 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
10486 return entry->priv->attrs;