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"
69 #include "a11y/gtkentryaccessible.h"
73 * @Short_description: A single line text entry field
75 * @See_also: #GtkTextView, #GtkEntryCompletion
77 * The #GtkEntry widget is a single line text entry
78 * widget. A fairly large set of key bindings are supported
79 * by default. If the entered text is longer than the allocation
80 * of the widget, the widget will scroll so that the cursor
81 * position is visible.
83 * When using an entry for passwords and other sensitive information,
84 * it can be put into "password mode" using gtk_entry_set_visibility().
85 * In this mode, entered text is displayed using a 'invisible' character.
86 * By default, GTK+ picks the best invisible character that is available
87 * in the current font, but it can be changed with
88 * gtk_entry_set_invisible_char(). Since 2.16, GTK+ displays a warning
89 * when Caps Lock or input methods might interfere with entering text in
90 * a password entry. The warning can be turned off with the
91 * #GtkEntry:caps-lock-warning property.
93 * Since 2.16, GtkEntry has the ability to display progress or activity
94 * information behind the text. To make an entry display such information,
95 * use gtk_entry_set_progress_fraction() or gtk_entry_set_progress_pulse_step().
97 * Additionally, GtkEntry can show icons at either side of the entry. These
98 * icons can be activatable by clicking, can be set up as drag source and
99 * can have tooltips. To add an icon, use gtk_entry_set_icon_from_gicon() or
100 * one of the various other functions that set an icon from a stock id, an
101 * icon name or a pixbuf. To trigger an action when the user clicks an icon,
102 * connect to the #GtkEntry::icon-press signal. To allow DND operations
103 * from an icon, use gtk_entry_set_icon_drag_source(). To set a tooltip on
104 * an icon, use gtk_entry_set_icon_tooltip_text() or the corresponding function
107 * Note that functionality or information that is only available by clicking
108 * on an icon in an entry may not be accessible at all to users which are not
109 * able to use a mouse or other pointing device. It is therefore recommended
110 * that any such functionality should also be available by other means, e.g.
111 * via the context menu of the entry.
115 #define GTK_ENTRY_COMPLETION_KEY "gtk-entry-completion-key"
117 #define MIN_ENTRY_WIDTH 150
118 #define DRAW_TIMEOUT 20
119 #define COMPLETION_TIMEOUT 300
120 #define PASSWORD_HINT_MAX 8
125 #define IS_VALID_ICON_POSITION(pos) \
126 ((pos) == GTK_ENTRY_ICON_PRIMARY || \
127 (pos) == GTK_ENTRY_ICON_SECONDARY)
129 static const GtkBorder default_inner_border = { 2, 2, 2, 2 };
130 static GQuark quark_inner_border = 0;
131 static GQuark quark_password_hint = 0;
132 static GQuark quark_cursor_hadjustment = 0;
133 static GQuark quark_capslock_feedback = 0;
135 typedef struct _EntryIconInfo EntryIconInfo;
136 typedef struct _GtkEntryPasswordHint GtkEntryPasswordHint;
137 typedef struct _GtkEntryCapslockFeedback GtkEntryCapslockFeedback;
139 struct _GtkEntryPrivate
141 EntryIconInfo *icons[MAX_ICONS];
143 GtkEntryBuffer *buffer;
144 GtkIMContext *im_context;
145 GtkShadowType shadow_type;
146 GtkWidget *popup_menu;
150 GdkDevice *completion_device;
151 GdkWindow *text_area;
153 PangoLayout *cached_layout;
157 gdouble progress_fraction;
158 gdouble progress_pulse_fraction;
159 gdouble progress_pulse_current;
161 gchar *placeholder_text;
165 gint ascent; /* font ascent in pango units */
167 gint descent; /* font descent in pango units */
168 gint dnd_position; /* In chars, -1 == no DND cursor */
173 gint selection_bound;
179 gunichar invisible_char;
182 guint blink_time; /* time in msec the cursor has blinked since last user event */
184 guint recompute_idle;
186 guint16 x_text_size; /* allocated size, in bytes */
187 guint16 x_n_bytes; /* length in use, in bytes */
189 guint16 preedit_length; /* length of preedit string, in bytes */
190 guint16 preedit_cursor; /* offset of cursor within preedit string, in chars */
194 guint overwrite_mode : 1;
197 guint activates_default : 1;
198 guint cache_includes_preedit : 1;
199 guint caps_lock_warning : 1;
200 guint caps_lock_warning_shown : 1;
201 guint change_count : 8;
202 guint cursor_visible : 1;
203 guint editing_canceled : 1; /* Only used by GtkCellRendererText */
205 guint in_click : 1; /* Flag so we don't select all when clicking in entry to focus in */
206 guint is_cell_renderer : 1;
207 guint invisible_char_set : 1;
208 guint interior_focus : 1;
209 guint mouse_cursor_obscured : 1;
210 guint need_im_reset : 1;
211 guint progress_pulse_mode : 1;
212 guint progress_pulse_way_back : 1;
213 guint real_changed : 1;
214 guint resolved_dir : 4; /* PangoDirection */
215 guint select_words : 1;
216 guint select_lines : 1;
217 guint truncate_multiline : 1;
220 struct _EntryIconInfo
224 guint insensitive : 1;
225 guint nonactivatable : 1;
230 GtkIconHelper *icon_helper;
232 GtkTargetList *target_list;
233 GdkDragAction actions;
236 struct _GtkEntryPasswordHint
238 gint position; /* Position (in text) of the last password hint */
239 guint source_id; /* Timeout source id */
242 struct _GtkEntryCapslockFeedback
269 PROP_CURSOR_POSITION,
270 PROP_SELECTION_BOUND,
277 PROP_ACTIVATES_DEFAULT,
282 PROP_TRUNCATE_MULTILINE,
286 PROP_INVISIBLE_CHAR_SET,
287 PROP_CAPS_LOCK_WARNING,
288 PROP_PROGRESS_FRACTION,
289 PROP_PROGRESS_PULSE_STEP,
291 PROP_PIXBUF_SECONDARY,
293 PROP_STOCK_SECONDARY,
294 PROP_ICON_NAME_PRIMARY,
295 PROP_ICON_NAME_SECONDARY,
297 PROP_GICON_SECONDARY,
298 PROP_STORAGE_TYPE_PRIMARY,
299 PROP_STORAGE_TYPE_SECONDARY,
300 PROP_ACTIVATABLE_PRIMARY,
301 PROP_ACTIVATABLE_SECONDARY,
302 PROP_SENSITIVE_PRIMARY,
303 PROP_SENSITIVE_SECONDARY,
304 PROP_TOOLTIP_TEXT_PRIMARY,
305 PROP_TOOLTIP_TEXT_SECONDARY,
306 PROP_TOOLTIP_MARKUP_PRIMARY,
307 PROP_TOOLTIP_MARKUP_SECONDARY,
309 PROP_EDITING_CANCELED,
310 PROP_PLACEHOLDER_TEXT,
316 static guint signals[LAST_SIGNAL] = { 0 };
325 DISPLAY_NORMAL, /* The entry text is being shown */
326 DISPLAY_INVISIBLE, /* In invisible mode, text replaced by (eg) bullets */
327 DISPLAY_BLANK /* In invisible mode, nothing shown at all */
332 static void gtk_entry_editable_init (GtkEditableInterface *iface);
333 static void gtk_entry_cell_editable_init (GtkCellEditableIface *iface);
334 static void gtk_entry_set_property (GObject *object,
338 static void gtk_entry_get_property (GObject *object,
342 static void gtk_entry_finalize (GObject *object);
343 static void gtk_entry_dispose (GObject *object);
347 static void gtk_entry_destroy (GtkWidget *widget);
348 static void gtk_entry_realize (GtkWidget *widget);
349 static void gtk_entry_unrealize (GtkWidget *widget);
350 static void gtk_entry_map (GtkWidget *widget);
351 static void gtk_entry_unmap (GtkWidget *widget);
352 static void gtk_entry_get_preferred_width (GtkWidget *widget,
355 static void gtk_entry_get_preferred_height (GtkWidget *widget,
358 static void gtk_entry_size_allocate (GtkWidget *widget,
359 GtkAllocation *allocation);
360 static void gtk_entry_draw_frame (GtkWidget *widget,
361 GtkStyleContext *context,
363 static void gtk_entry_draw_progress (GtkWidget *widget,
364 GtkStyleContext *context,
366 static gint gtk_entry_draw (GtkWidget *widget,
368 static gint gtk_entry_button_press (GtkWidget *widget,
369 GdkEventButton *event);
370 static gint gtk_entry_button_release (GtkWidget *widget,
371 GdkEventButton *event);
372 static gint gtk_entry_enter_notify (GtkWidget *widget,
373 GdkEventCrossing *event);
374 static gint gtk_entry_leave_notify (GtkWidget *widget,
375 GdkEventCrossing *event);
376 static gint gtk_entry_motion_notify (GtkWidget *widget,
377 GdkEventMotion *event);
378 static gint gtk_entry_key_press (GtkWidget *widget,
380 static gint gtk_entry_key_release (GtkWidget *widget,
382 static gint gtk_entry_focus_in (GtkWidget *widget,
383 GdkEventFocus *event);
384 static gint gtk_entry_focus_out (GtkWidget *widget,
385 GdkEventFocus *event);
386 static void gtk_entry_grab_focus (GtkWidget *widget);
387 static void gtk_entry_style_updated (GtkWidget *widget);
388 static gboolean gtk_entry_query_tooltip (GtkWidget *widget,
391 gboolean keyboard_tip,
392 GtkTooltip *tooltip);
393 static void gtk_entry_direction_changed (GtkWidget *widget,
394 GtkTextDirection previous_dir);
395 static void gtk_entry_state_flags_changed (GtkWidget *widget,
396 GtkStateFlags previous_state);
397 static void gtk_entry_screen_changed (GtkWidget *widget,
398 GdkScreen *old_screen);
400 static gboolean gtk_entry_drag_drop (GtkWidget *widget,
401 GdkDragContext *context,
405 static gboolean gtk_entry_drag_motion (GtkWidget *widget,
406 GdkDragContext *context,
410 static void gtk_entry_drag_leave (GtkWidget *widget,
411 GdkDragContext *context,
413 static void gtk_entry_drag_data_received (GtkWidget *widget,
414 GdkDragContext *context,
417 GtkSelectionData *selection_data,
420 static void gtk_entry_drag_data_get (GtkWidget *widget,
421 GdkDragContext *context,
422 GtkSelectionData *selection_data,
425 static void gtk_entry_drag_data_delete (GtkWidget *widget,
426 GdkDragContext *context);
427 static void gtk_entry_drag_begin (GtkWidget *widget,
428 GdkDragContext *context);
429 static void gtk_entry_drag_end (GtkWidget *widget,
430 GdkDragContext *context);
433 /* GtkEditable method implementations
435 static void gtk_entry_insert_text (GtkEditable *editable,
436 const gchar *new_text,
437 gint new_text_length,
439 static void gtk_entry_delete_text (GtkEditable *editable,
442 static gchar * gtk_entry_get_chars (GtkEditable *editable,
445 static void gtk_entry_real_set_position (GtkEditable *editable,
447 static gint gtk_entry_get_position (GtkEditable *editable);
448 static void gtk_entry_set_selection_bounds (GtkEditable *editable,
451 static gboolean gtk_entry_get_selection_bounds (GtkEditable *editable,
455 /* GtkCellEditable method implementations
457 static void gtk_entry_start_editing (GtkCellEditable *cell_editable,
460 /* Default signal handlers
462 static void gtk_entry_real_insert_text (GtkEditable *editable,
463 const gchar *new_text,
464 gint new_text_length,
466 static void gtk_entry_real_delete_text (GtkEditable *editable,
469 static void gtk_entry_move_cursor (GtkEntry *entry,
470 GtkMovementStep step,
472 gboolean extend_selection);
473 static void gtk_entry_insert_at_cursor (GtkEntry *entry,
475 static void gtk_entry_delete_from_cursor (GtkEntry *entry,
478 static void gtk_entry_backspace (GtkEntry *entry);
479 static void gtk_entry_cut_clipboard (GtkEntry *entry);
480 static void gtk_entry_copy_clipboard (GtkEntry *entry);
481 static void gtk_entry_paste_clipboard (GtkEntry *entry);
482 static void gtk_entry_toggle_overwrite (GtkEntry *entry);
483 static void gtk_entry_select_all (GtkEntry *entry);
484 static void gtk_entry_real_activate (GtkEntry *entry);
485 static gboolean gtk_entry_popup_menu (GtkWidget *widget);
487 static void keymap_direction_changed (GdkKeymap *keymap,
489 static void keymap_state_changed (GdkKeymap *keymap,
491 static void remove_capslock_feedback (GtkEntry *entry);
493 /* IM Context Callbacks
495 static void gtk_entry_commit_cb (GtkIMContext *context,
498 static void gtk_entry_preedit_changed_cb (GtkIMContext *context,
500 static gboolean gtk_entry_retrieve_surrounding_cb (GtkIMContext *context,
502 static gboolean gtk_entry_delete_surrounding_cb (GtkIMContext *context,
509 static void gtk_entry_enter_text (GtkEntry *entry,
511 static void gtk_entry_set_positions (GtkEntry *entry,
513 gint selection_bound);
514 static void gtk_entry_draw_text (GtkEntry *entry,
516 static void gtk_entry_draw_cursor (GtkEntry *entry,
519 static PangoLayout *gtk_entry_ensure_layout (GtkEntry *entry,
520 gboolean include_preedit);
521 static void gtk_entry_reset_layout (GtkEntry *entry);
522 static void gtk_entry_recompute (GtkEntry *entry);
523 static gint gtk_entry_find_position (GtkEntry *entry,
525 static void gtk_entry_get_cursor_locations (GtkEntry *entry,
529 static void gtk_entry_adjust_scroll (GtkEntry *entry);
530 static gint gtk_entry_move_visually (GtkEntry *editable,
533 static gint gtk_entry_move_logically (GtkEntry *entry,
536 static gint gtk_entry_move_forward_word (GtkEntry *entry,
538 gboolean allow_whitespace);
539 static gint gtk_entry_move_backward_word (GtkEntry *entry,
541 gboolean allow_whitespace);
542 static void gtk_entry_delete_whitespace (GtkEntry *entry);
543 static void gtk_entry_select_word (GtkEntry *entry);
544 static void gtk_entry_select_line (GtkEntry *entry);
545 static void gtk_entry_paste (GtkEntry *entry,
547 static void gtk_entry_update_primary_selection (GtkEntry *entry);
548 static void gtk_entry_do_popup (GtkEntry *entry,
549 GdkEventButton *event);
550 static gboolean gtk_entry_mnemonic_activate (GtkWidget *widget,
551 gboolean group_cycling);
552 static void gtk_entry_grab_notify (GtkWidget *widget,
553 gboolean was_grabbed);
554 static void gtk_entry_check_cursor_blink (GtkEntry *entry);
555 static void gtk_entry_pend_cursor_blink (GtkEntry *entry);
556 static void gtk_entry_reset_blink_time (GtkEntry *entry);
557 static void gtk_entry_get_text_area_size (GtkEntry *entry,
562 static void get_text_area_size (GtkEntry *entry,
567 static void get_frame_size (GtkEntry *entry,
568 gboolean relative_to_window,
573 static void gtk_entry_move_adjustments (GtkEntry *entry);
574 static GdkPixbuf * gtk_entry_ensure_pixbuf (GtkEntry *entry,
575 GtkEntryIconPosition icon_pos);
576 static void gtk_entry_update_cached_style_values(GtkEntry *entry);
577 static gboolean get_middle_click_paste (GtkEntry *entry);
580 static gint gtk_entry_completion_timeout (gpointer data);
581 static gboolean gtk_entry_completion_key_press (GtkWidget *widget,
584 static void gtk_entry_completion_changed (GtkWidget *entry,
586 static gboolean check_completion_callback (GtkEntryCompletion *completion);
587 static void clear_completion_callback (GtkEntry *entry,
589 static gboolean accept_completion_callback (GtkEntry *entry);
590 static void completion_insert_text_callback (GtkEntry *entry,
594 GtkEntryCompletion *completion);
595 static void completion_changed (GtkEntryCompletion *completion,
598 static void disconnect_completion_signals (GtkEntry *entry,
599 GtkEntryCompletion *completion);
600 static void connect_completion_signals (GtkEntry *entry,
601 GtkEntryCompletion *completion);
603 static void begin_change (GtkEntry *entry);
604 static void end_change (GtkEntry *entry);
605 static void emit_changed (GtkEntry *entry);
607 static void buffer_inserted_text (GtkEntryBuffer *buffer,
612 static void buffer_deleted_text (GtkEntryBuffer *buffer,
616 static void buffer_notify_text (GtkEntryBuffer *buffer,
619 static void buffer_notify_length (GtkEntryBuffer *buffer,
622 static void buffer_notify_max_length (GtkEntryBuffer *buffer,
625 static void buffer_connect_signals (GtkEntry *entry);
626 static void buffer_disconnect_signals (GtkEntry *entry);
627 static GtkEntryBuffer *get_buffer (GtkEntry *entry);
629 G_DEFINE_TYPE_WITH_CODE (GtkEntry, gtk_entry, GTK_TYPE_WIDGET,
630 G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
631 gtk_entry_editable_init)
632 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_EDITABLE,
633 gtk_entry_cell_editable_init))
636 add_move_binding (GtkBindingSet *binding_set,
639 GtkMovementStep step,
642 g_return_if_fail ((modmask & GDK_SHIFT_MASK) == 0);
644 gtk_binding_entry_add_signal (binding_set, keyval, modmask,
648 G_TYPE_BOOLEAN, FALSE);
650 /* Selection-extending version */
651 gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
655 G_TYPE_BOOLEAN, TRUE);
659 gtk_entry_class_init (GtkEntryClass *class)
661 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
662 GtkWidgetClass *widget_class;
663 GtkBindingSet *binding_set;
665 widget_class = (GtkWidgetClass*) class;
667 gobject_class->dispose = gtk_entry_dispose;
668 gobject_class->finalize = gtk_entry_finalize;
669 gobject_class->set_property = gtk_entry_set_property;
670 gobject_class->get_property = gtk_entry_get_property;
672 widget_class->destroy = gtk_entry_destroy;
673 widget_class->map = gtk_entry_map;
674 widget_class->unmap = gtk_entry_unmap;
675 widget_class->realize = gtk_entry_realize;
676 widget_class->unrealize = gtk_entry_unrealize;
677 widget_class->get_preferred_width = gtk_entry_get_preferred_width;
678 widget_class->get_preferred_height = gtk_entry_get_preferred_height;
679 widget_class->size_allocate = gtk_entry_size_allocate;
680 widget_class->draw = gtk_entry_draw;
681 widget_class->enter_notify_event = gtk_entry_enter_notify;
682 widget_class->leave_notify_event = gtk_entry_leave_notify;
683 widget_class->button_press_event = gtk_entry_button_press;
684 widget_class->button_release_event = gtk_entry_button_release;
685 widget_class->motion_notify_event = gtk_entry_motion_notify;
686 widget_class->key_press_event = gtk_entry_key_press;
687 widget_class->key_release_event = gtk_entry_key_release;
688 widget_class->focus_in_event = gtk_entry_focus_in;
689 widget_class->focus_out_event = gtk_entry_focus_out;
690 widget_class->grab_focus = gtk_entry_grab_focus;
691 widget_class->style_updated = gtk_entry_style_updated;
692 widget_class->query_tooltip = gtk_entry_query_tooltip;
693 widget_class->drag_begin = gtk_entry_drag_begin;
694 widget_class->drag_end = gtk_entry_drag_end;
695 widget_class->direction_changed = gtk_entry_direction_changed;
696 widget_class->state_flags_changed = gtk_entry_state_flags_changed;
697 widget_class->screen_changed = gtk_entry_screen_changed;
698 widget_class->mnemonic_activate = gtk_entry_mnemonic_activate;
699 widget_class->grab_notify = gtk_entry_grab_notify;
701 widget_class->drag_drop = gtk_entry_drag_drop;
702 widget_class->drag_motion = gtk_entry_drag_motion;
703 widget_class->drag_leave = gtk_entry_drag_leave;
704 widget_class->drag_data_received = gtk_entry_drag_data_received;
705 widget_class->drag_data_get = gtk_entry_drag_data_get;
706 widget_class->drag_data_delete = gtk_entry_drag_data_delete;
708 widget_class->popup_menu = gtk_entry_popup_menu;
710 class->move_cursor = gtk_entry_move_cursor;
711 class->insert_at_cursor = gtk_entry_insert_at_cursor;
712 class->delete_from_cursor = gtk_entry_delete_from_cursor;
713 class->backspace = gtk_entry_backspace;
714 class->cut_clipboard = gtk_entry_cut_clipboard;
715 class->copy_clipboard = gtk_entry_copy_clipboard;
716 class->paste_clipboard = gtk_entry_paste_clipboard;
717 class->toggle_overwrite = gtk_entry_toggle_overwrite;
718 class->activate = gtk_entry_real_activate;
719 class->get_text_area_size = gtk_entry_get_text_area_size;
721 quark_inner_border = g_quark_from_static_string ("gtk-entry-inner-border");
722 quark_password_hint = g_quark_from_static_string ("gtk-entry-password-hint");
723 quark_cursor_hadjustment = g_quark_from_static_string ("gtk-hadjustment");
724 quark_capslock_feedback = g_quark_from_static_string ("gtk-entry-capslock-feedback");
726 g_object_class_override_property (gobject_class,
727 PROP_EDITING_CANCELED,
730 g_object_class_install_property (gobject_class,
732 g_param_spec_object ("buffer",
734 P_("Text buffer object which actually stores entry text"),
735 GTK_TYPE_ENTRY_BUFFER,
736 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
738 g_object_class_install_property (gobject_class,
739 PROP_CURSOR_POSITION,
740 g_param_spec_int ("cursor-position",
741 P_("Cursor Position"),
742 P_("The current position of the insertion cursor in chars"),
744 GTK_ENTRY_BUFFER_MAX_SIZE,
746 GTK_PARAM_READABLE));
748 g_object_class_install_property (gobject_class,
749 PROP_SELECTION_BOUND,
750 g_param_spec_int ("selection-bound",
751 P_("Selection Bound"),
752 P_("The position of the opposite end of the selection from the cursor in chars"),
754 GTK_ENTRY_BUFFER_MAX_SIZE,
756 GTK_PARAM_READABLE));
758 g_object_class_install_property (gobject_class,
760 g_param_spec_boolean ("editable",
762 P_("Whether the entry contents can be edited"),
764 GTK_PARAM_READWRITE));
766 g_object_class_install_property (gobject_class,
768 g_param_spec_int ("max-length",
769 P_("Maximum length"),
770 P_("Maximum number of characters for this entry. Zero if no maximum"),
772 GTK_ENTRY_BUFFER_MAX_SIZE,
774 GTK_PARAM_READWRITE));
775 g_object_class_install_property (gobject_class,
777 g_param_spec_boolean ("visibility",
779 P_("FALSE displays the \"invisible char\" instead of the actual text (password mode)"),
781 GTK_PARAM_READWRITE));
783 g_object_class_install_property (gobject_class,
785 g_param_spec_boolean ("has-frame",
787 P_("FALSE removes outside bevel from entry"),
789 GTK_PARAM_READWRITE));
792 * GtkEntry:inner-border:
794 * Sets the text area's border between the text and the frame.
796 * Deprecated: 3.4: Use the standard border and padding CSS properties
797 * (through objects like #GtkStyleContext and #GtkCssProvider); the value
798 * of this style property is ignored.
800 g_object_class_install_property (gobject_class,
802 g_param_spec_boxed ("inner-border",
804 P_("Border between text and frame. Overrides the inner-border style property"),
806 GTK_PARAM_READWRITE |
807 G_PARAM_DEPRECATED));
809 g_object_class_install_property (gobject_class,
811 g_param_spec_unichar ("invisible-char",
812 P_("Invisible character"),
813 P_("The character to use when masking entry contents (in \"password mode\")"),
815 GTK_PARAM_READWRITE));
817 g_object_class_install_property (gobject_class,
818 PROP_ACTIVATES_DEFAULT,
819 g_param_spec_boolean ("activates-default",
820 P_("Activates default"),
821 P_("Whether to activate the default widget (such as the default button in a dialog) when Enter is pressed"),
823 GTK_PARAM_READWRITE));
824 g_object_class_install_property (gobject_class,
826 g_param_spec_int ("width-chars",
827 P_("Width in chars"),
828 P_("Number of characters to leave space for in the entry"),
832 GTK_PARAM_READWRITE));
834 g_object_class_install_property (gobject_class,
836 g_param_spec_int ("scroll-offset",
838 P_("Number of pixels of the entry scrolled off the screen to the left"),
842 GTK_PARAM_READABLE));
844 g_object_class_install_property (gobject_class,
846 g_param_spec_string ("text",
848 P_("The contents of the entry"),
850 GTK_PARAM_READWRITE));
855 * The horizontal alignment, from 0 (left) to 1 (right).
856 * Reversed for RTL layouts.
860 g_object_class_install_property (gobject_class,
862 g_param_spec_float ("xalign",
864 P_("The horizontal alignment, from 0 (left) to 1 (right). Reversed for RTL layouts."),
868 GTK_PARAM_READWRITE));
871 * GtkEntry:truncate-multiline:
873 * When %TRUE, pasted multi-line text is truncated to the first line.
877 g_object_class_install_property (gobject_class,
878 PROP_TRUNCATE_MULTILINE,
879 g_param_spec_boolean ("truncate-multiline",
880 P_("Truncate multiline"),
881 P_("Whether to truncate multiline pastes to one line."),
883 GTK_PARAM_READWRITE));
886 * GtkEntry:shadow-type:
888 * Which kind of shadow to draw around the entry when
889 * #GtkEntry:has-frame is set to %TRUE.
893 g_object_class_install_property (gobject_class,
895 g_param_spec_enum ("shadow-type",
897 P_("Which kind of shadow to draw around the entry when has-frame is set"),
898 GTK_TYPE_SHADOW_TYPE,
900 GTK_PARAM_READWRITE));
903 * GtkEntry:overwrite-mode:
905 * If text is overwritten when typing in the #GtkEntry.
909 g_object_class_install_property (gobject_class,
911 g_param_spec_boolean ("overwrite-mode",
912 P_("Overwrite mode"),
913 P_("Whether new text overwrites existing text"),
915 GTK_PARAM_READWRITE));
918 * GtkEntry:text-length:
920 * The length of the text in the #GtkEntry.
924 g_object_class_install_property (gobject_class,
926 g_param_spec_uint ("text-length",
928 P_("Length of the text currently in the entry"),
932 GTK_PARAM_READABLE));
934 * GtkEntry:invisible-char-set:
936 * Whether the invisible char has been set for the #GtkEntry.
940 g_object_class_install_property (gobject_class,
941 PROP_INVISIBLE_CHAR_SET,
942 g_param_spec_boolean ("invisible-char-set",
943 P_("Invisible character set"),
944 P_("Whether the invisible character has been set"),
946 GTK_PARAM_READWRITE));
949 * GtkEntry:caps-lock-warning:
951 * Whether password entries will show a warning when Caps Lock is on.
953 * Note that the warning is shown using a secondary icon, and thus
954 * does not work if you are using the secondary icon position for some
959 g_object_class_install_property (gobject_class,
960 PROP_CAPS_LOCK_WARNING,
961 g_param_spec_boolean ("caps-lock-warning",
962 P_("Caps Lock warning"),
963 P_("Whether password entries will show a warning when Caps Lock is on"),
965 GTK_PARAM_READWRITE));
968 * GtkEntry:progress-fraction:
970 * The current fraction of the task that's been completed.
974 g_object_class_install_property (gobject_class,
975 PROP_PROGRESS_FRACTION,
976 g_param_spec_double ("progress-fraction",
977 P_("Progress Fraction"),
978 P_("The current fraction of the task that's been completed"),
982 GTK_PARAM_READWRITE));
985 * GtkEntry:progress-pulse-step:
987 * The fraction of total entry width to move the progress
988 * bouncing block for each call to gtk_entry_progress_pulse().
992 g_object_class_install_property (gobject_class,
993 PROP_PROGRESS_PULSE_STEP,
994 g_param_spec_double ("progress-pulse-step",
995 P_("Progress Pulse Step"),
996 P_("The fraction of total entry width to move the progress bouncing block for each call to gtk_entry_progress_pulse()"),
1000 GTK_PARAM_READWRITE));
1003 * GtkEntry:placeholder-text:
1005 * The text that will be displayed in the #GtkEntry when it is empty
1010 g_object_class_install_property (gobject_class,
1011 PROP_PLACEHOLDER_TEXT,
1012 g_param_spec_string ("placeholder-text",
1013 P_("Placeholder text"),
1014 P_("Show text in the entry when it's empty and unfocused"),
1016 GTK_PARAM_READWRITE));
1019 * GtkEntry:primary-icon-pixbuf:
1021 * A pixbuf to use as the primary icon for the entry.
1025 g_object_class_install_property (gobject_class,
1026 PROP_PIXBUF_PRIMARY,
1027 g_param_spec_object ("primary-icon-pixbuf",
1028 P_("Primary pixbuf"),
1029 P_("Primary pixbuf for the entry"),
1031 GTK_PARAM_READWRITE));
1034 * GtkEntry:secondary-icon-pixbuf:
1036 * An pixbuf to use as the secondary icon for the entry.
1040 g_object_class_install_property (gobject_class,
1041 PROP_PIXBUF_SECONDARY,
1042 g_param_spec_object ("secondary-icon-pixbuf",
1043 P_("Secondary pixbuf"),
1044 P_("Secondary pixbuf for the entry"),
1046 GTK_PARAM_READWRITE));
1049 * GtkEntry:primary-icon-stock:
1051 * The stock id to use for the primary icon for the entry.
1055 g_object_class_install_property (gobject_class,
1057 g_param_spec_string ("primary-icon-stock",
1058 P_("Primary stock ID"),
1059 P_("Stock ID for primary icon"),
1061 GTK_PARAM_READWRITE));
1064 * GtkEntry:secondary-icon-stock:
1066 * The stock id to use for the secondary icon for the entry.
1070 g_object_class_install_property (gobject_class,
1071 PROP_STOCK_SECONDARY,
1072 g_param_spec_string ("secondary-icon-stock",
1073 P_("Secondary stock ID"),
1074 P_("Stock ID for secondary icon"),
1076 GTK_PARAM_READWRITE));
1079 * GtkEntry:primary-icon-name:
1081 * The icon name to use for the primary icon for the entry.
1085 g_object_class_install_property (gobject_class,
1086 PROP_ICON_NAME_PRIMARY,
1087 g_param_spec_string ("primary-icon-name",
1088 P_("Primary icon name"),
1089 P_("Icon name for primary icon"),
1091 GTK_PARAM_READWRITE));
1094 * GtkEntry:secondary-icon-name:
1096 * The icon name to use for the secondary icon for the entry.
1100 g_object_class_install_property (gobject_class,
1101 PROP_ICON_NAME_SECONDARY,
1102 g_param_spec_string ("secondary-icon-name",
1103 P_("Secondary icon name"),
1104 P_("Icon name for secondary icon"),
1106 GTK_PARAM_READWRITE));
1109 * GtkEntry:primary-icon-gicon:
1111 * The #GIcon to use for the primary icon for the entry.
1115 g_object_class_install_property (gobject_class,
1117 g_param_spec_object ("primary-icon-gicon",
1118 P_("Primary GIcon"),
1119 P_("GIcon for primary icon"),
1121 GTK_PARAM_READWRITE));
1124 * GtkEntry:secondary-icon-gicon:
1126 * The #GIcon to use for the secondary icon for the entry.
1130 g_object_class_install_property (gobject_class,
1131 PROP_GICON_SECONDARY,
1132 g_param_spec_object ("secondary-icon-gicon",
1133 P_("Secondary GIcon"),
1134 P_("GIcon for secondary icon"),
1136 GTK_PARAM_READWRITE));
1139 * GtkEntry:primary-icon-storage-type:
1141 * The representation which is used for the primary icon of the entry.
1145 g_object_class_install_property (gobject_class,
1146 PROP_STORAGE_TYPE_PRIMARY,
1147 g_param_spec_enum ("primary-icon-storage-type",
1148 P_("Primary storage type"),
1149 P_("The representation being used for primary icon"),
1150 GTK_TYPE_IMAGE_TYPE,
1152 GTK_PARAM_READABLE));
1155 * GtkEntry:secondary-icon-storage-type:
1157 * The representation which is used for the secondary icon of the entry.
1161 g_object_class_install_property (gobject_class,
1162 PROP_STORAGE_TYPE_SECONDARY,
1163 g_param_spec_enum ("secondary-icon-storage-type",
1164 P_("Secondary storage type"),
1165 P_("The representation being used for secondary icon"),
1166 GTK_TYPE_IMAGE_TYPE,
1168 GTK_PARAM_READABLE));
1171 * GtkEntry:primary-icon-activatable:
1173 * Whether the primary icon is activatable.
1175 * GTK+ emits the #GtkEntry::icon-press and #GtkEntry::icon-release
1176 * signals only on sensitive, activatable icons.
1178 * Sensitive, but non-activatable icons can be used for purely
1179 * informational purposes.
1183 g_object_class_install_property (gobject_class,
1184 PROP_ACTIVATABLE_PRIMARY,
1185 g_param_spec_boolean ("primary-icon-activatable",
1186 P_("Primary icon activatable"),
1187 P_("Whether the primary icon is activatable"),
1189 GTK_PARAM_READWRITE));
1192 * GtkEntry:secondary-icon-activatable:
1194 * Whether the secondary icon is activatable.
1196 * GTK+ emits the #GtkEntry::icon-press and #GtkEntry::icon-release
1197 * signals only on sensitive, activatable icons.
1199 * Sensitive, but non-activatable icons can be used for purely
1200 * informational purposes.
1204 g_object_class_install_property (gobject_class,
1205 PROP_ACTIVATABLE_SECONDARY,
1206 g_param_spec_boolean ("secondary-icon-activatable",
1207 P_("Secondary icon activatable"),
1208 P_("Whether the secondary icon is activatable"),
1210 GTK_PARAM_READWRITE));
1214 * GtkEntry:primary-icon-sensitive:
1216 * Whether the primary icon is sensitive.
1218 * An insensitive icon appears grayed out. GTK+ does not emit the
1219 * #GtkEntry::icon-press and #GtkEntry::icon-release signals and
1220 * does not allow DND from insensitive icons.
1222 * An icon should be set insensitive if the action that would trigger
1223 * when clicked is currently not available.
1227 g_object_class_install_property (gobject_class,
1228 PROP_SENSITIVE_PRIMARY,
1229 g_param_spec_boolean ("primary-icon-sensitive",
1230 P_("Primary icon sensitive"),
1231 P_("Whether the primary icon is sensitive"),
1233 GTK_PARAM_READWRITE));
1236 * GtkEntry:secondary-icon-sensitive:
1238 * Whether the secondary icon is sensitive.
1240 * An insensitive icon appears grayed out. GTK+ does not emit the
1241 * #GtkEntry::icon-press and #GtkEntry::icon-release signals and
1242 * does not allow DND from insensitive icons.
1244 * An icon should be set insensitive if the action that would trigger
1245 * when clicked is currently not available.
1249 g_object_class_install_property (gobject_class,
1250 PROP_SENSITIVE_SECONDARY,
1251 g_param_spec_boolean ("secondary-icon-sensitive",
1252 P_("Secondary icon sensitive"),
1253 P_("Whether the secondary icon is sensitive"),
1255 GTK_PARAM_READWRITE));
1258 * GtkEntry:primary-icon-tooltip-text:
1260 * The contents of the tooltip on the primary icon.
1262 * Also see gtk_entry_set_icon_tooltip_text().
1266 g_object_class_install_property (gobject_class,
1267 PROP_TOOLTIP_TEXT_PRIMARY,
1268 g_param_spec_string ("primary-icon-tooltip-text",
1269 P_("Primary icon tooltip text"),
1270 P_("The contents of the tooltip on the primary icon"),
1272 GTK_PARAM_READWRITE));
1275 * GtkEntry:secondary-icon-tooltip-text:
1277 * The contents of the tooltip on the secondary icon.
1279 * Also see gtk_entry_set_icon_tooltip_text().
1283 g_object_class_install_property (gobject_class,
1284 PROP_TOOLTIP_TEXT_SECONDARY,
1285 g_param_spec_string ("secondary-icon-tooltip-text",
1286 P_("Secondary icon tooltip text"),
1287 P_("The contents of the tooltip on the secondary icon"),
1289 GTK_PARAM_READWRITE));
1292 * GtkEntry:primary-icon-tooltip-markup:
1294 * The contents of the tooltip on the primary icon, which is marked up
1295 * with the <link linkend="PangoMarkupFormat">Pango text markup
1298 * Also see gtk_entry_set_icon_tooltip_markup().
1302 g_object_class_install_property (gobject_class,
1303 PROP_TOOLTIP_MARKUP_PRIMARY,
1304 g_param_spec_string ("primary-icon-tooltip-markup",
1305 P_("Primary icon tooltip markup"),
1306 P_("The contents of the tooltip on the primary icon"),
1308 GTK_PARAM_READWRITE));
1311 * GtkEntry:secondary-icon-tooltip-markup:
1313 * The contents of the tooltip on the secondary icon, which is marked up
1314 * with the <link linkend="PangoMarkupFormat">Pango text markup
1317 * Also see gtk_entry_set_icon_tooltip_markup().
1321 g_object_class_install_property (gobject_class,
1322 PROP_TOOLTIP_MARKUP_SECONDARY,
1323 g_param_spec_string ("secondary-icon-tooltip-markup",
1324 P_("Secondary icon tooltip markup"),
1325 P_("The contents of the tooltip on the secondary icon"),
1327 GTK_PARAM_READWRITE));
1330 * GtkEntry:im-module:
1332 * Which IM (input method) module should be used for this entry.
1333 * See #GtkIMContext.
1335 * Setting this to a non-%NULL value overrides the
1336 * system-wide IM module setting. See the GtkSettings
1337 * #GtkSettings:gtk-im-module property.
1341 g_object_class_install_property (gobject_class,
1343 g_param_spec_string ("im-module",
1345 P_("Which IM module should be used"),
1347 GTK_PARAM_READWRITE));
1350 * GtkEntry:completion:
1352 * The auxiliary completion object to use with the entry.
1356 g_object_class_install_property (gobject_class,
1358 g_param_spec_object ("completion",
1360 P_("The auxiliary completion object"),
1361 GTK_TYPE_ENTRY_COMPLETION,
1362 GTK_PARAM_READWRITE));
1364 g_object_class_install_property (gobject_class,
1366 g_param_spec_enum ("input-purpose",
1368 P_("Purpose of the text field"),
1369 GTK_TYPE_INPUT_PURPOSE,
1370 GTK_INPUT_PURPOSE_FREE_FORM,
1371 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1373 g_object_class_install_property (gobject_class,
1375 g_param_spec_flags ("input-hints",
1377 P_("Hints for the text field behaviour"),
1378 GTK_TYPE_INPUT_HINTS,
1379 GTK_INPUT_HINT_NONE,
1380 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1384 * GtkEntry:icon-prelight:
1386 * The prelight style property determines whether activatable
1387 * icons prelight on mouseover.
1391 gtk_widget_class_install_style_property (widget_class,
1392 g_param_spec_boolean ("icon-prelight",
1393 P_("Icon Prelight"),
1394 P_("Whether activatable icons should prelight when hovered"),
1396 GTK_PARAM_READABLE));
1399 * GtkEntry:progress-border:
1401 * The border around the progress bar in the entry.
1405 * Deprecated: 3.4: Use the standard margin CSS property (through objects
1406 * like #GtkStyleContext and #GtkCssProvider); the value of this style
1407 * property is ignored.
1409 gtk_widget_class_install_style_property (widget_class,
1410 g_param_spec_boxed ("progress-border",
1411 P_("Progress Border"),
1412 P_("Border around the progress bar"),
1414 GTK_PARAM_READABLE |
1415 G_PARAM_DEPRECATED));
1418 * GtkEntry:invisible-char:
1420 * The invisible character is used when masking entry contents (in
1421 * \"password mode\")"). When it is not explicitly set with the
1422 * #GtkEntry:invisible-char property, GTK+ determines the character
1423 * to use from a list of possible candidates, depending on availability
1424 * in the current font.
1426 * This style property allows the theme to prepend a character
1427 * to the list of candidates.
1431 gtk_widget_class_install_style_property (widget_class,
1432 g_param_spec_unichar ("invisible-char",
1433 P_("Invisible character"),
1434 P_("The character to use when masking entry contents (in \"password mode\")"),
1436 GTK_PARAM_READABLE));
1439 * GtkEntry::populate-popup:
1440 * @entry: The entry on which the signal is emitted
1441 * @menu: the menu that is being populated
1443 * The ::populate-popup signal gets emitted before showing the
1444 * context menu of the entry.
1446 * If you need to add items to the context menu, connect
1447 * to this signal and append your menuitems to the @menu.
1449 signals[POPULATE_POPUP] =
1450 g_signal_new (I_("populate-popup"),
1451 G_OBJECT_CLASS_TYPE (gobject_class),
1453 G_STRUCT_OFFSET (GtkEntryClass, populate_popup),
1455 _gtk_marshal_VOID__OBJECT,
1459 /* Action signals */
1462 * GtkEntry::activate:
1463 * @entry: The entry on which the signal is emitted
1465 * The ::activate signal is emitted when the user hits
1468 * While this signal is used as a
1469 * <link linkend="keybinding-signals">keybinding signal</link>,
1470 * it is also commonly used by applications to intercept
1471 * activation of entries.
1473 * The default bindings for this signal are all forms of the Enter key.
1476 g_signal_new (I_("activate"),
1477 G_OBJECT_CLASS_TYPE (gobject_class),
1478 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1479 G_STRUCT_OFFSET (GtkEntryClass, activate),
1481 _gtk_marshal_VOID__VOID,
1483 widget_class->activate_signal = signals[ACTIVATE];
1486 * GtkEntry::move-cursor:
1487 * @entry: the object which received the signal
1488 * @step: the granularity of the move, as a #GtkMovementStep
1489 * @count: the number of @step units to move
1490 * @extend_selection: %TRUE if the move should extend the selection
1492 * The ::move-cursor signal is a
1493 * <link linkend="keybinding-signals">keybinding signal</link>
1494 * which gets emitted when the user initiates a cursor movement.
1495 * If the cursor is not visible in @entry, this signal causes
1496 * the viewport to be moved instead.
1498 * Applications should not connect to it, but may emit it with
1499 * g_signal_emit_by_name() if they need to control the cursor
1502 * The default bindings for this signal come in two variants,
1503 * the variant with the Shift modifier extends the selection,
1504 * the variant without the Shift modifer does not.
1505 * There are too many key combinations to list them all here.
1507 * <listitem>Arrow keys move by individual characters/lines</listitem>
1508 * <listitem>Ctrl-arrow key combinations move by words/paragraphs</listitem>
1509 * <listitem>Home/End keys move to the ends of the buffer</listitem>
1512 signals[MOVE_CURSOR] =
1513 g_signal_new (I_("move-cursor"),
1514 G_OBJECT_CLASS_TYPE (gobject_class),
1515 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1516 G_STRUCT_OFFSET (GtkEntryClass, move_cursor),
1518 _gtk_marshal_VOID__ENUM_INT_BOOLEAN,
1520 GTK_TYPE_MOVEMENT_STEP,
1525 * GtkEntry::insert-at-cursor:
1526 * @entry: the object which received the signal
1527 * @string: the string to insert
1529 * The ::insert-at-cursor signal is a
1530 * <link linkend="keybinding-signals">keybinding signal</link>
1531 * which gets emitted when the user initiates the insertion of a
1532 * fixed string at the cursor.
1534 * This signal has no default bindings.
1536 signals[INSERT_AT_CURSOR] =
1537 g_signal_new (I_("insert-at-cursor"),
1538 G_OBJECT_CLASS_TYPE (gobject_class),
1539 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1540 G_STRUCT_OFFSET (GtkEntryClass, insert_at_cursor),
1542 _gtk_marshal_VOID__STRING,
1547 * GtkEntry::delete-from-cursor:
1548 * @entry: the object which received the signal
1549 * @type: the granularity of the deletion, as a #GtkDeleteType
1550 * @count: the number of @type units to delete
1552 * The ::delete-from-cursor signal is a
1553 * <link linkend="keybinding-signals">keybinding signal</link>
1554 * which gets emitted when the user initiates a text deletion.
1556 * If the @type is %GTK_DELETE_CHARS, GTK+ deletes the selection
1557 * if there is one, otherwise it deletes the requested number
1560 * The default bindings for this signal are
1561 * Delete for deleting a character and Ctrl-Delete for
1564 signals[DELETE_FROM_CURSOR] =
1565 g_signal_new (I_("delete-from-cursor"),
1566 G_OBJECT_CLASS_TYPE (gobject_class),
1567 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1568 G_STRUCT_OFFSET (GtkEntryClass, delete_from_cursor),
1570 _gtk_marshal_VOID__ENUM_INT,
1572 GTK_TYPE_DELETE_TYPE,
1576 * GtkEntry::backspace:
1577 * @entry: the object which received the signal
1579 * The ::backspace signal is a
1580 * <link linkend="keybinding-signals">keybinding signal</link>
1581 * which gets emitted when the user asks for it.
1583 * The default bindings for this signal are
1584 * Backspace and Shift-Backspace.
1586 signals[BACKSPACE] =
1587 g_signal_new (I_("backspace"),
1588 G_OBJECT_CLASS_TYPE (gobject_class),
1589 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1590 G_STRUCT_OFFSET (GtkEntryClass, backspace),
1592 _gtk_marshal_VOID__VOID,
1596 * GtkEntry::cut-clipboard:
1597 * @entry: the object which received the signal
1599 * The ::cut-clipboard signal is a
1600 * <link linkend="keybinding-signals">keybinding signal</link>
1601 * which gets emitted to cut the selection to the clipboard.
1603 * The default bindings for this signal are
1604 * Ctrl-x and Shift-Delete.
1606 signals[CUT_CLIPBOARD] =
1607 g_signal_new (I_("cut-clipboard"),
1608 G_OBJECT_CLASS_TYPE (gobject_class),
1609 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1610 G_STRUCT_OFFSET (GtkEntryClass, cut_clipboard),
1612 _gtk_marshal_VOID__VOID,
1616 * GtkEntry::copy-clipboard:
1617 * @entry: the object which received the signal
1619 * The ::copy-clipboard signal is a
1620 * <link linkend="keybinding-signals">keybinding signal</link>
1621 * which gets emitted to copy the selection to the clipboard.
1623 * The default bindings for this signal are
1624 * Ctrl-c and Ctrl-Insert.
1626 signals[COPY_CLIPBOARD] =
1627 g_signal_new (I_("copy-clipboard"),
1628 G_OBJECT_CLASS_TYPE (gobject_class),
1629 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1630 G_STRUCT_OFFSET (GtkEntryClass, copy_clipboard),
1632 _gtk_marshal_VOID__VOID,
1636 * GtkEntry::paste-clipboard:
1637 * @entry: the object which received the signal
1639 * The ::paste-clipboard signal is a
1640 * <link linkend="keybinding-signals">keybinding signal</link>
1641 * which gets emitted to paste the contents of the clipboard
1642 * into the text view.
1644 * The default bindings for this signal are
1645 * Ctrl-v and Shift-Insert.
1647 signals[PASTE_CLIPBOARD] =
1648 g_signal_new (I_("paste-clipboard"),
1649 G_OBJECT_CLASS_TYPE (gobject_class),
1650 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1651 G_STRUCT_OFFSET (GtkEntryClass, paste_clipboard),
1653 _gtk_marshal_VOID__VOID,
1657 * GtkEntry::toggle-overwrite:
1658 * @entry: the object which received the signal
1660 * The ::toggle-overwrite signal is a
1661 * <link linkend="keybinding-signals">keybinding signal</link>
1662 * which gets emitted to toggle the overwrite mode of the entry.
1664 * The default bindings for this signal is Insert.
1666 signals[TOGGLE_OVERWRITE] =
1667 g_signal_new (I_("toggle-overwrite"),
1668 G_OBJECT_CLASS_TYPE (gobject_class),
1669 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1670 G_STRUCT_OFFSET (GtkEntryClass, toggle_overwrite),
1672 _gtk_marshal_VOID__VOID,
1676 * GtkEntry::icon-press:
1677 * @entry: The entry on which the signal is emitted
1678 * @icon_pos: The position of the clicked icon
1679 * @event: (type Gdk.EventButton): the button press event
1681 * The ::icon-press signal is emitted when an activatable icon
1686 signals[ICON_PRESS] =
1687 g_signal_new (I_("icon-press"),
1688 G_TYPE_FROM_CLASS (gobject_class),
1692 _gtk_marshal_VOID__ENUM_BOXED,
1694 GTK_TYPE_ENTRY_ICON_POSITION,
1695 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
1698 * GtkEntry::icon-release:
1699 * @entry: The entry on which the signal is emitted
1700 * @icon_pos: The position of the clicked icon
1701 * @event: (type Gdk.EventButton): the button release event
1703 * The ::icon-release signal is emitted on the button release from a
1704 * mouse click over an activatable icon.
1708 signals[ICON_RELEASE] =
1709 g_signal_new (I_("icon-release"),
1710 G_TYPE_FROM_CLASS (gobject_class),
1714 _gtk_marshal_VOID__ENUM_BOXED,
1716 GTK_TYPE_ENTRY_ICON_POSITION,
1717 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
1720 * GtkEntry::preedit-changed:
1721 * @entry: the object which received the signal
1722 * @preedit: the current preedit string
1724 * If an input method is used, the typed text will not immediately
1725 * be committed to the buffer. So if you are interested in the text,
1726 * connect to this signal.
1730 signals[PREEDIT_CHANGED] =
1731 g_signal_new_class_handler (I_("preedit-changed"),
1732 G_OBJECT_CLASS_TYPE (gobject_class),
1733 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1736 _gtk_marshal_VOID__STRING,
1745 binding_set = gtk_binding_set_by_class (class);
1747 /* Moving the insertion point */
1748 add_move_binding (binding_set, GDK_KEY_Right, 0,
1749 GTK_MOVEMENT_VISUAL_POSITIONS, 1);
1751 add_move_binding (binding_set, GDK_KEY_Left, 0,
1752 GTK_MOVEMENT_VISUAL_POSITIONS, -1);
1754 add_move_binding (binding_set, GDK_KEY_KP_Right, 0,
1755 GTK_MOVEMENT_VISUAL_POSITIONS, 1);
1757 add_move_binding (binding_set, GDK_KEY_KP_Left, 0,
1758 GTK_MOVEMENT_VISUAL_POSITIONS, -1);
1760 add_move_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK,
1761 GTK_MOVEMENT_WORDS, 1);
1763 add_move_binding (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK,
1764 GTK_MOVEMENT_WORDS, -1);
1766 add_move_binding (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
1767 GTK_MOVEMENT_WORDS, 1);
1769 add_move_binding (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
1770 GTK_MOVEMENT_WORDS, -1);
1772 add_move_binding (binding_set, GDK_KEY_Home, 0,
1773 GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
1775 add_move_binding (binding_set, GDK_KEY_End, 0,
1776 GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
1778 add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
1779 GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
1781 add_move_binding (binding_set, GDK_KEY_KP_End, 0,
1782 GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
1784 add_move_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK,
1785 GTK_MOVEMENT_BUFFER_ENDS, -1);
1787 add_move_binding (binding_set, GDK_KEY_End, GDK_CONTROL_MASK,
1788 GTK_MOVEMENT_BUFFER_ENDS, 1);
1790 add_move_binding (binding_set, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
1791 GTK_MOVEMENT_BUFFER_ENDS, -1);
1793 add_move_binding (binding_set, GDK_KEY_KP_End, GDK_CONTROL_MASK,
1794 GTK_MOVEMENT_BUFFER_ENDS, 1);
1798 gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
1800 GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
1802 G_TYPE_BOOLEAN, FALSE);
1803 gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
1805 GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
1807 G_TYPE_BOOLEAN, TRUE);
1809 gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
1811 GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
1813 G_TYPE_BOOLEAN, FALSE);
1814 gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
1816 GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
1818 G_TYPE_BOOLEAN, TRUE);
1821 gtk_binding_entry_add_signal (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK,
1823 GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_VISUAL_POSITIONS,
1825 G_TYPE_BOOLEAN, FALSE);
1826 gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
1828 GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_VISUAL_POSITIONS,
1830 G_TYPE_BOOLEAN, FALSE);
1834 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1836 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1838 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1842 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, 0,
1843 "delete-from-cursor", 2,
1844 G_TYPE_ENUM, GTK_DELETE_CHARS,
1847 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, 0,
1848 "delete-from-cursor", 2,
1849 G_TYPE_ENUM, GTK_DELETE_CHARS,
1852 gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, 0,
1855 /* Make this do the same as Backspace, to help with mis-typing */
1856 gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_SHIFT_MASK,
1859 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_CONTROL_MASK,
1860 "delete-from-cursor", 2,
1861 G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
1864 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_CONTROL_MASK,
1865 "delete-from-cursor", 2,
1866 G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
1869 gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_CONTROL_MASK,
1870 "delete-from-cursor", 2,
1871 G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
1874 /* Cut/copy/paste */
1876 gtk_binding_entry_add_signal (binding_set, GDK_KEY_x, GDK_CONTROL_MASK,
1877 "cut-clipboard", 0);
1878 gtk_binding_entry_add_signal (binding_set, GDK_KEY_c, GDK_CONTROL_MASK,
1879 "copy-clipboard", 0);
1880 gtk_binding_entry_add_signal (binding_set, GDK_KEY_v, GDK_CONTROL_MASK,
1881 "paste-clipboard", 0);
1883 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_SHIFT_MASK,
1884 "cut-clipboard", 0);
1885 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, GDK_CONTROL_MASK,
1886 "copy-clipboard", 0);
1887 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, GDK_SHIFT_MASK,
1888 "paste-clipboard", 0);
1891 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, 0,
1892 "toggle-overwrite", 0);
1893 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, 0,
1894 "toggle-overwrite", 0);
1897 * GtkEntry:inner-border:
1899 * Sets the text area's border between the text and the frame.
1903 * Deprecated: 3.4: Use the standard border and padding CSS properties
1904 * (through objects like #GtkStyleContext and #GtkCssProvider); the value
1905 * of this style property is ignored.
1907 gtk_widget_class_install_style_property (widget_class,
1908 g_param_spec_boxed ("inner-border",
1910 P_("Border between text and frame."),
1912 GTK_PARAM_READABLE |
1913 G_PARAM_DEPRECATED));
1915 g_type_class_add_private (gobject_class, sizeof (GtkEntryPrivate));
1917 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ENTRY_ACCESSIBLE);
1921 gtk_entry_editable_init (GtkEditableInterface *iface)
1923 iface->do_insert_text = gtk_entry_insert_text;
1924 iface->do_delete_text = gtk_entry_delete_text;
1925 iface->insert_text = gtk_entry_real_insert_text;
1926 iface->delete_text = gtk_entry_real_delete_text;
1927 iface->get_chars = gtk_entry_get_chars;
1928 iface->set_selection_bounds = gtk_entry_set_selection_bounds;
1929 iface->get_selection_bounds = gtk_entry_get_selection_bounds;
1930 iface->set_position = gtk_entry_real_set_position;
1931 iface->get_position = gtk_entry_get_position;
1935 gtk_entry_cell_editable_init (GtkCellEditableIface *iface)
1937 iface->start_editing = gtk_entry_start_editing;
1940 /* for deprecated properties */
1942 gtk_entry_do_set_inner_border (GtkEntry *entry,
1943 const GtkBorder *border)
1946 g_object_set_qdata_full (G_OBJECT (entry), quark_inner_border,
1947 gtk_border_copy (border),
1948 (GDestroyNotify) gtk_border_free);
1950 g_object_set_qdata (G_OBJECT (entry), quark_inner_border, NULL);
1952 g_object_notify (G_OBJECT (entry), "inner-border");
1955 static const GtkBorder *
1956 gtk_entry_do_get_inner_border (GtkEntry *entry)
1958 return g_object_get_qdata (G_OBJECT (entry), quark_inner_border);
1962 gtk_entry_set_property (GObject *object,
1964 const GValue *value,
1967 GtkEntry *entry = GTK_ENTRY (object);
1968 GtkEntryPrivate *priv = entry->priv;
1973 gtk_entry_set_buffer (entry, g_value_get_object (value));
1978 gboolean new_value = g_value_get_boolean (value);
1980 if (new_value != priv->editable)
1982 GtkWidget *widget = GTK_WIDGET (entry);
1986 _gtk_entry_reset_im_context (entry);
1987 if (gtk_widget_has_focus (widget))
1988 gtk_im_context_focus_out (priv->im_context);
1990 priv->preedit_length = 0;
1991 priv->preedit_cursor = 0;
1994 priv->editable = new_value;
1996 if (new_value && gtk_widget_has_focus (widget))
1997 gtk_im_context_focus_in (priv->im_context);
1999 gtk_widget_queue_draw (widget);
2004 case PROP_MAX_LENGTH:
2005 gtk_entry_set_max_length (entry, g_value_get_int (value));
2008 case PROP_VISIBILITY:
2009 gtk_entry_set_visibility (entry, g_value_get_boolean (value));
2012 case PROP_HAS_FRAME:
2013 gtk_entry_set_has_frame (entry, g_value_get_boolean (value));
2016 case PROP_INNER_BORDER:
2017 gtk_entry_do_set_inner_border (entry, g_value_get_boxed (value));
2020 case PROP_INVISIBLE_CHAR:
2021 gtk_entry_set_invisible_char (entry, g_value_get_uint (value));
2024 case PROP_ACTIVATES_DEFAULT:
2025 gtk_entry_set_activates_default (entry, g_value_get_boolean (value));
2028 case PROP_WIDTH_CHARS:
2029 gtk_entry_set_width_chars (entry, g_value_get_int (value));
2033 gtk_entry_set_text (entry, g_value_get_string (value));
2037 gtk_entry_set_alignment (entry, g_value_get_float (value));
2040 case PROP_TRUNCATE_MULTILINE:
2041 priv->truncate_multiline = g_value_get_boolean (value);
2044 case PROP_SHADOW_TYPE:
2045 priv->shadow_type = g_value_get_enum (value);
2048 case PROP_OVERWRITE_MODE:
2049 gtk_entry_set_overwrite_mode (entry, g_value_get_boolean (value));
2052 case PROP_INVISIBLE_CHAR_SET:
2053 if (g_value_get_boolean (value))
2054 priv->invisible_char_set = TRUE;
2056 gtk_entry_unset_invisible_char (entry);
2059 case PROP_CAPS_LOCK_WARNING:
2060 priv->caps_lock_warning = g_value_get_boolean (value);
2063 case PROP_PROGRESS_FRACTION:
2064 gtk_entry_set_progress_fraction (entry, g_value_get_double (value));
2067 case PROP_PROGRESS_PULSE_STEP:
2068 gtk_entry_set_progress_pulse_step (entry, g_value_get_double (value));
2071 case PROP_PLACEHOLDER_TEXT:
2072 gtk_entry_set_placeholder_text (entry, g_value_get_string (value));
2075 case PROP_PIXBUF_PRIMARY:
2076 gtk_entry_set_icon_from_pixbuf (entry,
2077 GTK_ENTRY_ICON_PRIMARY,
2078 g_value_get_object (value));
2081 case PROP_PIXBUF_SECONDARY:
2082 gtk_entry_set_icon_from_pixbuf (entry,
2083 GTK_ENTRY_ICON_SECONDARY,
2084 g_value_get_object (value));
2087 case PROP_STOCK_PRIMARY:
2088 gtk_entry_set_icon_from_stock (entry,
2089 GTK_ENTRY_ICON_PRIMARY,
2090 g_value_get_string (value));
2093 case PROP_STOCK_SECONDARY:
2094 gtk_entry_set_icon_from_stock (entry,
2095 GTK_ENTRY_ICON_SECONDARY,
2096 g_value_get_string (value));
2099 case PROP_ICON_NAME_PRIMARY:
2100 gtk_entry_set_icon_from_icon_name (entry,
2101 GTK_ENTRY_ICON_PRIMARY,
2102 g_value_get_string (value));
2105 case PROP_ICON_NAME_SECONDARY:
2106 gtk_entry_set_icon_from_icon_name (entry,
2107 GTK_ENTRY_ICON_SECONDARY,
2108 g_value_get_string (value));
2111 case PROP_GICON_PRIMARY:
2112 gtk_entry_set_icon_from_gicon (entry,
2113 GTK_ENTRY_ICON_PRIMARY,
2114 g_value_get_object (value));
2117 case PROP_GICON_SECONDARY:
2118 gtk_entry_set_icon_from_gicon (entry,
2119 GTK_ENTRY_ICON_SECONDARY,
2120 g_value_get_object (value));
2123 case PROP_ACTIVATABLE_PRIMARY:
2124 gtk_entry_set_icon_activatable (entry,
2125 GTK_ENTRY_ICON_PRIMARY,
2126 g_value_get_boolean (value));
2129 case PROP_ACTIVATABLE_SECONDARY:
2130 gtk_entry_set_icon_activatable (entry,
2131 GTK_ENTRY_ICON_SECONDARY,
2132 g_value_get_boolean (value));
2135 case PROP_SENSITIVE_PRIMARY:
2136 gtk_entry_set_icon_sensitive (entry,
2137 GTK_ENTRY_ICON_PRIMARY,
2138 g_value_get_boolean (value));
2141 case PROP_SENSITIVE_SECONDARY:
2142 gtk_entry_set_icon_sensitive (entry,
2143 GTK_ENTRY_ICON_SECONDARY,
2144 g_value_get_boolean (value));
2147 case PROP_TOOLTIP_TEXT_PRIMARY:
2148 gtk_entry_set_icon_tooltip_text (entry,
2149 GTK_ENTRY_ICON_PRIMARY,
2150 g_value_get_string (value));
2153 case PROP_TOOLTIP_TEXT_SECONDARY:
2154 gtk_entry_set_icon_tooltip_text (entry,
2155 GTK_ENTRY_ICON_SECONDARY,
2156 g_value_get_string (value));
2159 case PROP_TOOLTIP_MARKUP_PRIMARY:
2160 gtk_entry_set_icon_tooltip_markup (entry,
2161 GTK_ENTRY_ICON_PRIMARY,
2162 g_value_get_string (value));
2165 case PROP_TOOLTIP_MARKUP_SECONDARY:
2166 gtk_entry_set_icon_tooltip_markup (entry,
2167 GTK_ENTRY_ICON_SECONDARY,
2168 g_value_get_string (value));
2171 case PROP_IM_MODULE:
2172 g_free (priv->im_module);
2173 priv->im_module = g_value_dup_string (value);
2174 if (GTK_IS_IM_MULTICONTEXT (priv->im_context))
2175 gtk_im_multicontext_set_context_id (GTK_IM_MULTICONTEXT (priv->im_context), priv->im_module);
2178 case PROP_EDITING_CANCELED:
2179 priv->editing_canceled = g_value_get_boolean (value);
2182 case PROP_COMPLETION:
2183 gtk_entry_set_completion (entry, GTK_ENTRY_COMPLETION (g_value_get_object (value)));
2186 case PROP_INPUT_PURPOSE:
2187 gtk_entry_set_input_purpose (entry, g_value_get_enum (value));
2190 case PROP_INPUT_HINTS:
2191 gtk_entry_set_input_hints (entry, g_value_get_flags (value));
2194 case PROP_SCROLL_OFFSET:
2195 case PROP_CURSOR_POSITION:
2197 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2203 gtk_entry_get_property (GObject *object,
2208 GtkEntry *entry = GTK_ENTRY (object);
2209 GtkEntryPrivate *priv = entry->priv;
2214 g_value_set_object (value, gtk_entry_get_buffer (entry));
2217 case PROP_CURSOR_POSITION:
2218 g_value_set_int (value, priv->current_pos);
2221 case PROP_SELECTION_BOUND:
2222 g_value_set_int (value, priv->selection_bound);
2226 g_value_set_boolean (value, priv->editable);
2229 case PROP_MAX_LENGTH:
2230 g_value_set_int (value, gtk_entry_buffer_get_max_length (get_buffer (entry)));
2233 case PROP_VISIBILITY:
2234 g_value_set_boolean (value, priv->visible);
2237 case PROP_HAS_FRAME:
2238 g_value_set_boolean (value, priv->has_frame);
2241 case PROP_INNER_BORDER:
2242 g_value_set_boxed (value, gtk_entry_do_get_inner_border (entry));
2245 case PROP_INVISIBLE_CHAR:
2246 g_value_set_uint (value, priv->invisible_char);
2249 case PROP_ACTIVATES_DEFAULT:
2250 g_value_set_boolean (value, priv->activates_default);
2253 case PROP_WIDTH_CHARS:
2254 g_value_set_int (value, priv->width_chars);
2257 case PROP_SCROLL_OFFSET:
2258 g_value_set_int (value, priv->scroll_offset);
2262 g_value_set_string (value, gtk_entry_get_text (entry));
2266 g_value_set_float (value, gtk_entry_get_alignment (entry));
2269 case PROP_TRUNCATE_MULTILINE:
2270 g_value_set_boolean (value, priv->truncate_multiline);
2273 case PROP_SHADOW_TYPE:
2274 g_value_set_enum (value, priv->shadow_type);
2277 case PROP_OVERWRITE_MODE:
2278 g_value_set_boolean (value, priv->overwrite_mode);
2281 case PROP_TEXT_LENGTH:
2282 g_value_set_uint (value, gtk_entry_buffer_get_length (get_buffer (entry)));
2285 case PROP_INVISIBLE_CHAR_SET:
2286 g_value_set_boolean (value, priv->invisible_char_set);
2289 case PROP_IM_MODULE:
2290 g_value_set_string (value, priv->im_module);
2293 case PROP_CAPS_LOCK_WARNING:
2294 g_value_set_boolean (value, priv->caps_lock_warning);
2297 case PROP_PROGRESS_FRACTION:
2298 g_value_set_double (value, priv->progress_fraction);
2301 case PROP_PROGRESS_PULSE_STEP:
2302 g_value_set_double (value, priv->progress_pulse_fraction);
2305 case PROP_PLACEHOLDER_TEXT:
2306 g_value_set_string (value, gtk_entry_get_placeholder_text (entry));
2309 case PROP_PIXBUF_PRIMARY:
2310 g_value_set_object (value,
2311 gtk_entry_get_icon_pixbuf (entry,
2312 GTK_ENTRY_ICON_PRIMARY));
2315 case PROP_PIXBUF_SECONDARY:
2316 g_value_set_object (value,
2317 gtk_entry_get_icon_pixbuf (entry,
2318 GTK_ENTRY_ICON_SECONDARY));
2321 case PROP_STOCK_PRIMARY:
2322 g_value_set_string (value,
2323 gtk_entry_get_icon_stock (entry,
2324 GTK_ENTRY_ICON_PRIMARY));
2327 case PROP_STOCK_SECONDARY:
2328 g_value_set_string (value,
2329 gtk_entry_get_icon_stock (entry,
2330 GTK_ENTRY_ICON_SECONDARY));
2333 case PROP_ICON_NAME_PRIMARY:
2334 g_value_set_string (value,
2335 gtk_entry_get_icon_name (entry,
2336 GTK_ENTRY_ICON_PRIMARY));
2339 case PROP_ICON_NAME_SECONDARY:
2340 g_value_set_string (value,
2341 gtk_entry_get_icon_name (entry,
2342 GTK_ENTRY_ICON_SECONDARY));
2345 case PROP_GICON_PRIMARY:
2346 g_value_set_object (value,
2347 gtk_entry_get_icon_gicon (entry,
2348 GTK_ENTRY_ICON_PRIMARY));
2351 case PROP_GICON_SECONDARY:
2352 g_value_set_object (value,
2353 gtk_entry_get_icon_gicon (entry,
2354 GTK_ENTRY_ICON_SECONDARY));
2357 case PROP_STORAGE_TYPE_PRIMARY:
2358 g_value_set_enum (value,
2359 gtk_entry_get_icon_storage_type (entry,
2360 GTK_ENTRY_ICON_PRIMARY));
2363 case PROP_STORAGE_TYPE_SECONDARY:
2364 g_value_set_enum (value,
2365 gtk_entry_get_icon_storage_type (entry,
2366 GTK_ENTRY_ICON_SECONDARY));
2369 case PROP_ACTIVATABLE_PRIMARY:
2370 g_value_set_boolean (value,
2371 gtk_entry_get_icon_activatable (entry, GTK_ENTRY_ICON_PRIMARY));
2374 case PROP_ACTIVATABLE_SECONDARY:
2375 g_value_set_boolean (value,
2376 gtk_entry_get_icon_activatable (entry, GTK_ENTRY_ICON_SECONDARY));
2379 case PROP_SENSITIVE_PRIMARY:
2380 g_value_set_boolean (value,
2381 gtk_entry_get_icon_sensitive (entry, GTK_ENTRY_ICON_PRIMARY));
2384 case PROP_SENSITIVE_SECONDARY:
2385 g_value_set_boolean (value,
2386 gtk_entry_get_icon_sensitive (entry, GTK_ENTRY_ICON_SECONDARY));
2389 case PROP_TOOLTIP_TEXT_PRIMARY:
2390 g_value_take_string (value,
2391 gtk_entry_get_icon_tooltip_text (entry, GTK_ENTRY_ICON_PRIMARY));
2394 case PROP_TOOLTIP_TEXT_SECONDARY:
2395 g_value_take_string (value,
2396 gtk_entry_get_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY));
2399 case PROP_TOOLTIP_MARKUP_PRIMARY:
2400 g_value_take_string (value,
2401 gtk_entry_get_icon_tooltip_markup (entry, GTK_ENTRY_ICON_PRIMARY));
2404 case PROP_TOOLTIP_MARKUP_SECONDARY:
2405 g_value_take_string (value,
2406 gtk_entry_get_icon_tooltip_markup (entry, GTK_ENTRY_ICON_SECONDARY));
2409 case PROP_EDITING_CANCELED:
2410 g_value_set_boolean (value,
2411 priv->editing_canceled);
2414 case PROP_COMPLETION:
2415 g_value_set_object (value, G_OBJECT (gtk_entry_get_completion (entry)));
2418 case PROP_INPUT_PURPOSE:
2419 g_value_set_enum (value, gtk_entry_get_input_purpose (entry));
2422 case PROP_INPUT_HINTS:
2423 g_value_set_flags (value, gtk_entry_get_input_hints (entry));
2427 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2433 find_invisible_char (GtkWidget *widget)
2435 PangoLayout *layout;
2436 PangoAttrList *attr_list;
2438 gunichar invisible_chars [] = {
2440 0x25cf, /* BLACK CIRCLE */
2441 0x2022, /* BULLET */
2442 0x2731, /* HEAVY ASTERISK */
2443 0x273a /* SIXTEEN POINTED ASTERISK */
2446 gtk_widget_style_get (widget,
2447 "invisible-char", &invisible_chars[0],
2450 layout = gtk_widget_create_pango_layout (widget, NULL);
2452 attr_list = pango_attr_list_new ();
2453 pango_attr_list_insert (attr_list, pango_attr_fallback_new (FALSE));
2455 pango_layout_set_attributes (layout, attr_list);
2456 pango_attr_list_unref (attr_list);
2458 for (i = (invisible_chars[0] != 0 ? 0 : 1); i < G_N_ELEMENTS (invisible_chars); i++)
2460 gchar text[7] = { 0, };
2463 len = g_unichar_to_utf8 (invisible_chars[i], text);
2464 pango_layout_set_text (layout, text, len);
2466 count = pango_layout_get_unknown_glyphs_count (layout);
2470 g_object_unref (layout);
2471 return invisible_chars[i];
2475 g_object_unref (layout);
2481 gtk_entry_init (GtkEntry *entry)
2483 GtkStyleContext *context;
2484 GtkEntryPrivate *priv;
2486 entry->priv = G_TYPE_INSTANCE_GET_PRIVATE (entry,
2491 gtk_widget_set_can_focus (GTK_WIDGET (entry), TRUE);
2492 gtk_widget_set_has_window (GTK_WIDGET (entry), FALSE);
2494 priv->editable = TRUE;
2495 priv->visible = TRUE;
2496 priv->dnd_position = -1;
2497 priv->width_chars = -1;
2498 priv->is_cell_renderer = FALSE;
2499 priv->editing_canceled = FALSE;
2500 priv->has_frame = TRUE;
2501 priv->truncate_multiline = FALSE;
2502 priv->shadow_type = GTK_SHADOW_IN;
2504 priv->caps_lock_warning = TRUE;
2505 priv->caps_lock_warning_shown = FALSE;
2506 priv->progress_fraction = 0.0;
2507 priv->progress_pulse_fraction = 0.1;
2509 gtk_drag_dest_set (GTK_WIDGET (entry),
2510 GTK_DEST_DEFAULT_HIGHLIGHT,
2512 GDK_ACTION_COPY | GDK_ACTION_MOVE);
2513 gtk_drag_dest_add_text_targets (GTK_WIDGET (entry));
2515 /* This object is completely private. No external entity can gain a reference
2516 * to it; so we create it here and destroy it in finalize().
2518 priv->im_context = gtk_im_multicontext_new ();
2520 g_signal_connect (priv->im_context, "commit",
2521 G_CALLBACK (gtk_entry_commit_cb), entry);
2522 g_signal_connect (priv->im_context, "preedit-changed",
2523 G_CALLBACK (gtk_entry_preedit_changed_cb), entry);
2524 g_signal_connect (priv->im_context, "retrieve-surrounding",
2525 G_CALLBACK (gtk_entry_retrieve_surrounding_cb), entry);
2526 g_signal_connect (priv->im_context, "delete-surrounding",
2527 G_CALLBACK (gtk_entry_delete_surrounding_cb), entry);
2529 context = gtk_widget_get_style_context (GTK_WIDGET (entry));
2530 gtk_style_context_add_class (context, GTK_STYLE_CLASS_ENTRY);
2532 gtk_entry_update_cached_style_values (entry);
2536 gtk_entry_prepare_context_for_icon (GtkEntry *entry,
2537 GtkStyleContext *context,
2538 GtkEntryIconPosition icon_pos)
2540 GtkEntryPrivate *priv = entry->priv;
2541 EntryIconInfo *icon_info = priv->icons[icon_pos];
2543 GtkStateFlags state;
2545 widget = GTK_WIDGET (entry);
2546 state = gtk_widget_get_state_flags (widget);
2548 state &= ~(GTK_STATE_FLAG_PRELIGHT);
2550 if ((state & GTK_STATE_FLAG_INSENSITIVE) || icon_info->insensitive)
2551 state |= GTK_STATE_FLAG_INSENSITIVE;
2552 else if (icon_info->prelight)
2553 state |= GTK_STATE_FLAG_PRELIGHT;
2555 gtk_style_context_save (context);
2557 gtk_style_context_set_state (context, state);
2558 gtk_style_context_add_class (context, GTK_STYLE_CLASS_IMAGE);
2560 if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
2562 if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
2563 gtk_style_context_add_class (context, GTK_STYLE_CLASS_RIGHT);
2565 gtk_style_context_add_class (context, GTK_STYLE_CLASS_LEFT);
2569 if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
2570 gtk_style_context_add_class (context, GTK_STYLE_CLASS_LEFT);
2572 gtk_style_context_add_class (context, GTK_STYLE_CLASS_RIGHT);
2577 get_icon_width (GtkEntry *entry,
2578 GtkEntryIconPosition icon_pos)
2580 GtkEntryPrivate *priv = entry->priv;
2581 EntryIconInfo *icon_info = priv->icons[icon_pos];
2582 GtkStyleContext *context;
2589 context = gtk_widget_get_style_context (GTK_WIDGET (entry));
2590 gtk_entry_prepare_context_for_icon (entry, context, icon_pos);
2591 gtk_style_context_get_padding (context, 0, &padding);
2593 _gtk_icon_helper_get_size (icon_info->icon_helper, context,
2595 gtk_style_context_restore (context);
2598 width += padding.left + padding.right;
2604 get_icon_allocations (GtkEntry *entry,
2605 GtkAllocation *primary,
2606 GtkAllocation *secondary)
2609 GtkEntryPrivate *priv = entry->priv;
2610 gint x, y, width, height;
2612 get_text_area_size (entry, &x, &y, &width, &height);
2614 if (gtk_widget_has_focus (GTK_WIDGET (entry)) && !priv->interior_focus)
2615 y += priv->focus_width;
2618 primary->height = height;
2619 primary->width = get_icon_width (entry, GTK_ENTRY_ICON_PRIMARY);
2622 secondary->height = height;
2623 secondary->width = get_icon_width (entry, GTK_ENTRY_ICON_SECONDARY);
2625 if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
2627 primary->x = x + width - primary->width;
2633 secondary->x = x + width - secondary->width;
2639 begin_change (GtkEntry *entry)
2641 GtkEntryPrivate *priv = entry->priv;
2643 priv->change_count++;
2645 g_object_freeze_notify (G_OBJECT (entry));
2649 end_change (GtkEntry *entry)
2651 GtkEditable *editable = GTK_EDITABLE (entry);
2652 GtkEntryPrivate *priv = entry->priv;
2654 g_return_if_fail (priv->change_count > 0);
2656 g_object_thaw_notify (G_OBJECT (entry));
2658 priv->change_count--;
2660 if (priv->change_count == 0)
2662 if (priv->real_changed)
2664 g_signal_emit_by_name (editable, "changed");
2665 priv->real_changed = FALSE;
2671 emit_changed (GtkEntry *entry)
2673 GtkEditable *editable = GTK_EDITABLE (entry);
2674 GtkEntryPrivate *priv = entry->priv;
2676 if (priv->change_count == 0)
2677 g_signal_emit_by_name (editable, "changed");
2679 priv->real_changed = TRUE;
2683 gtk_entry_destroy (GtkWidget *widget)
2685 GtkEntry *entry = GTK_ENTRY (widget);
2686 GtkEntryPrivate *priv = entry->priv;
2688 priv->current_pos = priv->selection_bound = 0;
2689 _gtk_entry_reset_im_context (entry);
2690 gtk_entry_reset_layout (entry);
2692 if (priv->blink_timeout)
2694 g_source_remove (priv->blink_timeout);
2695 priv->blink_timeout = 0;
2698 if (priv->recompute_idle)
2700 g_source_remove (priv->recompute_idle);
2701 priv->recompute_idle = 0;
2704 GTK_WIDGET_CLASS (gtk_entry_parent_class)->destroy (widget);
2708 gtk_entry_dispose (GObject *object)
2710 GtkEntry *entry = GTK_ENTRY (object);
2711 GtkEntryPrivate *priv = entry->priv;
2714 gtk_entry_set_icon_from_pixbuf (entry, GTK_ENTRY_ICON_PRIMARY, NULL);
2715 gtk_entry_set_icon_tooltip_markup (entry, GTK_ENTRY_ICON_PRIMARY, NULL);
2716 gtk_entry_set_icon_from_pixbuf (entry, GTK_ENTRY_ICON_SECONDARY, NULL);
2717 gtk_entry_set_icon_tooltip_markup (entry, GTK_ENTRY_ICON_SECONDARY, NULL);
2721 buffer_disconnect_signals (entry);
2722 g_object_unref (priv->buffer);
2723 priv->buffer = NULL;
2726 keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (object)));
2727 g_signal_handlers_disconnect_by_func (keymap, keymap_state_changed, entry);
2728 g_signal_handlers_disconnect_by_func (keymap, keymap_direction_changed, entry);
2729 G_OBJECT_CLASS (gtk_entry_parent_class)->dispose (object);
2733 gtk_entry_finalize (GObject *object)
2735 GtkEntry *entry = GTK_ENTRY (object);
2736 GtkEntryPrivate *priv = entry->priv;
2737 EntryIconInfo *icon_info = NULL;
2740 for (i = 0; i < MAX_ICONS; i++)
2742 if ((icon_info = priv->icons[i]) != NULL)
2744 if (icon_info->target_list != NULL)
2746 gtk_target_list_unref (icon_info->target_list);
2747 icon_info->target_list = NULL;
2750 g_clear_object (&icon_info->icon_helper);
2752 g_slice_free (EntryIconInfo, icon_info);
2753 priv->icons[i] = NULL;
2757 gtk_entry_set_completion (entry, NULL);
2759 if (priv->cached_layout)
2760 g_object_unref (priv->cached_layout);
2762 g_object_unref (priv->im_context);
2764 if (priv->blink_timeout)
2765 g_source_remove (priv->blink_timeout);
2767 if (priv->recompute_idle)
2768 g_source_remove (priv->recompute_idle);
2770 g_free (priv->placeholder_text);
2771 g_free (priv->im_module);
2773 G_OBJECT_CLASS (gtk_entry_parent_class)->finalize (object);
2777 gtk_entry_get_display_mode (GtkEntry *entry)
2779 GtkEntryPrivate *priv = entry->priv;
2782 return DISPLAY_NORMAL;
2784 if (priv->invisible_char == 0 && priv->invisible_char_set)
2785 return DISPLAY_BLANK;
2787 return DISPLAY_INVISIBLE;
2791 _gtk_entry_get_display_text (GtkEntry *entry,
2795 GtkEntryPasswordHint *password_hint;
2796 GtkEntryPrivate *priv;
2797 gunichar invisible_char;
2808 text = gtk_entry_buffer_get_text (get_buffer (entry));
2809 length = gtk_entry_buffer_get_length (get_buffer (entry));
2813 if (start_pos > length)
2816 if (end_pos <= start_pos)
2817 return g_strdup ("");
2818 else if (priv->visible)
2820 start = g_utf8_offset_to_pointer (text, start_pos);
2821 end = g_utf8_offset_to_pointer (start, end_pos - start_pos);
2822 return g_strndup (start, end - start);
2826 str = g_string_sized_new (length * 2);
2828 /* Figure out what our invisible char is and encode it */
2829 if (!priv->invisible_char)
2830 invisible_char = priv->invisible_char_set ? ' ' : '*';
2832 invisible_char = priv->invisible_char;
2833 char_len = g_unichar_to_utf8 (invisible_char, char_str);
2836 * Add hidden characters for each character in the text
2837 * buffer. If there is a password hint, then keep that
2838 * character visible.
2841 password_hint = g_object_get_qdata (G_OBJECT (entry), quark_password_hint);
2842 for (i = start_pos; i < end_pos; ++i)
2844 if (password_hint && i == password_hint->position)
2846 start = g_utf8_offset_to_pointer (text, i);
2847 g_string_append_len (str, start, g_utf8_next_char (start) - start);
2851 g_string_append_len (str, char_str, char_len);
2855 return g_string_free (str, FALSE);
2860 update_cursors (GtkWidget *widget)
2862 GtkEntry *entry = GTK_ENTRY (widget);
2863 GtkEntryPrivate *priv = entry->priv;
2864 EntryIconInfo *icon_info = NULL;
2865 GdkDisplay *display;
2869 for (i = 0; i < MAX_ICONS; i++)
2871 if ((icon_info = priv->icons[i]) != NULL)
2873 if (!_gtk_icon_helper_get_is_empty (icon_info->icon_helper) &&
2874 icon_info->window != NULL)
2875 gdk_window_show_unraised (icon_info->window);
2877 /* The icon windows are not children of the visible entry window,
2878 * thus we can't just inherit the xterm cursor. Slight complication
2879 * here is that for the entry, insensitive => arrow cursor, but for
2880 * an icon in a sensitive entry, insensitive => xterm cursor.
2882 if (gtk_widget_is_sensitive (widget) &&
2883 (icon_info->insensitive ||
2884 (icon_info->nonactivatable && icon_info->target_list == NULL)))
2886 display = gtk_widget_get_display (widget);
2887 cursor = gdk_cursor_new_for_display (display, GDK_XTERM);
2888 gdk_window_set_cursor (icon_info->window, cursor);
2889 g_object_unref (cursor);
2893 gdk_window_set_cursor (icon_info->window, NULL);
2900 realize_icon_info (GtkWidget *widget,
2901 GtkEntryIconPosition icon_pos)
2903 GtkEntry *entry = GTK_ENTRY (widget);
2904 GtkEntryPrivate *priv = entry->priv;
2905 EntryIconInfo *icon_info = priv->icons[icon_pos];
2906 GdkWindowAttr attributes;
2907 gint attributes_mask;
2909 g_return_if_fail (icon_info != NULL);
2913 attributes.width = 1;
2914 attributes.height = 1;
2915 attributes.window_type = GDK_WINDOW_CHILD;
2916 attributes.wclass = GDK_INPUT_ONLY;
2917 attributes.event_mask = gtk_widget_get_events (widget);
2918 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
2919 GDK_BUTTON_RELEASE_MASK |
2920 GDK_BUTTON1_MOTION_MASK |
2921 GDK_BUTTON3_MOTION_MASK |
2922 GDK_POINTER_MOTION_HINT_MASK |
2923 GDK_POINTER_MOTION_MASK |
2924 GDK_ENTER_NOTIFY_MASK |
2925 GDK_LEAVE_NOTIFY_MASK);
2926 attributes_mask = GDK_WA_X | GDK_WA_Y;
2928 icon_info->window = gdk_window_new (gtk_widget_get_window (widget),
2931 gdk_window_set_user_data (icon_info->window, widget);
2933 gtk_widget_queue_resize (widget);
2936 static EntryIconInfo*
2937 construct_icon_info (GtkWidget *widget,
2938 GtkEntryIconPosition icon_pos)
2940 GtkEntry *entry = GTK_ENTRY (widget);
2941 GtkEntryPrivate *priv = entry->priv;
2942 EntryIconInfo *icon_info;
2944 g_return_val_if_fail (priv->icons[icon_pos] == NULL, NULL);
2946 icon_info = g_slice_new0 (EntryIconInfo);
2947 priv->icons[icon_pos] = icon_info;
2949 icon_info->icon_helper = _gtk_icon_helper_new ();
2950 _gtk_icon_helper_set_force_scale_pixbuf (icon_info->icon_helper, TRUE);
2952 if (gtk_widget_get_realized (widget))
2953 realize_icon_info (widget, icon_pos);
2959 gtk_entry_map (GtkWidget *widget)
2961 GtkEntry *entry = GTK_ENTRY (widget);
2962 GtkEntryPrivate *priv = entry->priv;
2963 EntryIconInfo *icon_info = NULL;
2966 GTK_WIDGET_CLASS (gtk_entry_parent_class)->map (widget);
2968 gdk_window_show (priv->text_area);
2970 for (i = 0; i < MAX_ICONS; i++)
2972 if ((icon_info = priv->icons[i]) != NULL)
2974 if (!_gtk_icon_helper_get_is_empty (icon_info->icon_helper) &&
2975 icon_info->window != NULL)
2976 gdk_window_show (icon_info->window);
2980 update_cursors (widget);
2984 gtk_entry_unmap (GtkWidget *widget)
2986 GtkEntry *entry = GTK_ENTRY (widget);
2987 GtkEntryPrivate *priv = entry->priv;
2988 EntryIconInfo *icon_info = NULL;
2991 for (i = 0; i < MAX_ICONS; i++)
2993 if ((icon_info = priv->icons[i]) != NULL)
2995 if (!_gtk_icon_helper_get_is_empty (icon_info->icon_helper) &&
2996 icon_info->window != NULL)
2997 gdk_window_hide (icon_info->window);
3001 gdk_window_hide (priv->text_area);
3003 GTK_WIDGET_CLASS (gtk_entry_parent_class)->unmap (widget);
3007 gtk_entry_realize (GtkWidget *widget)
3010 GtkEntryPrivate *priv;
3011 EntryIconInfo *icon_info;
3013 GdkWindowAttr attributes;
3014 gint attributes_mask;
3015 gint frame_x, frame_y;
3018 gtk_widget_set_realized (widget, TRUE);
3019 window = gtk_widget_get_parent_window (widget);
3020 gtk_widget_set_window (widget, window);
3021 g_object_ref (window);
3023 entry = GTK_ENTRY (widget);
3026 attributes.window_type = GDK_WINDOW_CHILD;
3027 attributes.wclass = GDK_INPUT_ONLY;
3028 attributes.event_mask = gtk_widget_get_events (widget);
3029 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
3030 GDK_BUTTON_RELEASE_MASK |
3031 GDK_BUTTON1_MOTION_MASK |
3032 GDK_BUTTON3_MOTION_MASK |
3033 GDK_POINTER_MOTION_HINT_MASK |
3034 GDK_POINTER_MOTION_MASK |
3035 GDK_ENTER_NOTIFY_MASK |
3036 GDK_LEAVE_NOTIFY_MASK);
3037 attributes_mask = GDK_WA_X | GDK_WA_Y;
3039 get_text_area_size (entry, &attributes.x, &attributes.y, &attributes.width, &attributes.height);
3041 get_frame_size (entry, TRUE, &frame_x, &frame_y, NULL, NULL);
3042 attributes.x += frame_x;
3043 attributes.y += frame_y;
3045 if (gtk_widget_is_sensitive (widget))
3047 attributes.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), GDK_XTERM);
3048 attributes_mask |= GDK_WA_CURSOR;
3051 priv->text_area = gdk_window_new (gtk_widget_get_window (widget),
3055 gdk_window_set_user_data (priv->text_area, entry);
3057 if (attributes_mask & GDK_WA_CURSOR)
3058 g_object_unref (attributes.cursor);
3060 gtk_im_context_set_client_window (priv->im_context, priv->text_area);
3062 gtk_entry_adjust_scroll (entry);
3063 gtk_entry_update_primary_selection (entry);
3066 /* If the icon positions are already setup, create their windows.
3067 * Otherwise if they don't exist yet, then construct_icon_info()
3068 * will create the windows once the widget is already realized.
3070 for (i = 0; i < MAX_ICONS; i++)
3072 if ((icon_info = priv->icons[i]) != NULL)
3074 if (icon_info->window == NULL)
3075 realize_icon_info (widget, i);
3081 gtk_entry_unrealize (GtkWidget *widget)
3083 GtkEntry *entry = GTK_ENTRY (widget);
3084 GtkEntryPrivate *priv = entry->priv;
3085 GtkClipboard *clipboard;
3086 EntryIconInfo *icon_info;
3089 gtk_entry_reset_layout (entry);
3091 gtk_im_context_set_client_window (priv->im_context, NULL);
3093 clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_PRIMARY);
3094 if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (entry))
3095 gtk_clipboard_clear (clipboard);
3097 if (priv->text_area)
3099 gdk_window_set_user_data (priv->text_area, NULL);
3100 gdk_window_destroy (priv->text_area);
3101 priv->text_area = NULL;
3104 if (priv->popup_menu)
3106 gtk_widget_destroy (priv->popup_menu);
3107 priv->popup_menu = NULL;
3110 GTK_WIDGET_CLASS (gtk_entry_parent_class)->unrealize (widget);
3112 for (i = 0; i < MAX_ICONS; i++)
3114 if ((icon_info = priv->icons[i]) != NULL)
3116 if (icon_info->window != NULL)
3118 gdk_window_destroy (icon_info->window);
3119 icon_info->window = NULL;
3126 _gtk_entry_get_borders (GtkEntry *entry,
3127 GtkBorder *border_out)
3129 GtkEntryPrivate *priv = entry->priv;
3130 GtkWidget *widget = GTK_WIDGET (entry);
3131 GtkBorder tmp = { 0, 0, 0, 0 };
3132 GtkStyleContext *context;
3134 context = gtk_widget_get_style_context (widget);
3135 gtk_style_context_get_padding (context, 0, &tmp);
3137 if (priv->has_frame)
3141 gtk_style_context_get_border (context, 0, &border);
3142 tmp.top += border.top;
3143 tmp.right += border.right;
3144 tmp.bottom += border.bottom;
3145 tmp.left += border.left;
3148 if (!priv->interior_focus)
3150 tmp.top += priv->focus_width;
3151 tmp.right += priv->focus_width;
3152 tmp.bottom += priv->focus_width;
3153 tmp.left += priv->focus_width;
3156 if (border_out != NULL)
3161 gtk_entry_get_preferred_width (GtkWidget *widget,
3165 GtkEntry *entry = GTK_ENTRY (widget);
3166 GtkEntryPrivate *priv = entry->priv;
3167 PangoFontMetrics *metrics;
3169 PangoContext *context;
3170 GtkStyleContext *style_context;
3171 GtkStateFlags state;
3172 gint icon_widths = 0;
3176 context = gtk_widget_get_pango_context (widget);
3178 style_context = gtk_widget_get_style_context (widget);
3179 state = gtk_widget_get_state_flags (widget);
3181 metrics = pango_context_get_metrics (context,
3182 gtk_style_context_get_font (style_context, state),
3183 pango_context_get_language (context));
3185 _gtk_entry_get_borders (entry, &borders);
3187 if (priv->width_chars < 0)
3188 width = MIN_ENTRY_WIDTH + borders.left + borders.right;
3191 gint char_width = pango_font_metrics_get_approximate_char_width (metrics);
3192 gint digit_width = pango_font_metrics_get_approximate_digit_width (metrics);
3193 gint char_pixels = (MAX (char_width, digit_width) + PANGO_SCALE - 1) / PANGO_SCALE;
3195 width = char_pixels * priv->width_chars + borders.left + borders.right;
3198 for (i = 0; i < MAX_ICONS; i++)
3200 icon_width = get_icon_width (entry, i);
3202 icon_widths += icon_width;
3205 if (icon_widths > width)
3206 width += icon_widths;
3208 pango_font_metrics_unref (metrics);
3215 gtk_entry_get_preferred_height (GtkWidget *widget,
3219 GtkEntry *entry = GTK_ENTRY (widget);
3220 GtkEntryPrivate *priv = entry->priv;
3221 PangoFontMetrics *metrics;
3223 GtkStyleContext *style_context;
3224 GtkStateFlags state;
3225 PangoContext *context;
3228 context = gtk_widget_get_pango_context (widget);
3230 style_context = gtk_widget_get_style_context (widget);
3231 state = gtk_widget_get_state_flags (widget);
3233 metrics = pango_context_get_metrics (context,
3234 gtk_style_context_get_font (style_context, state),
3235 pango_context_get_language (context));
3237 priv->ascent = pango_font_metrics_get_ascent (metrics);
3238 priv->descent = pango_font_metrics_get_descent (metrics);
3240 _gtk_entry_get_borders (entry, &borders);
3242 height = PANGO_PIXELS (priv->ascent + priv->descent) + borders.top + borders.bottom;
3244 pango_font_metrics_unref (metrics);
3251 place_windows (GtkEntry *entry)
3253 GtkWidget *widget = GTK_WIDGET (entry);
3254 GtkEntryPrivate *priv = entry->priv;
3255 gint x, y, width, height;
3256 gint frame_x, frame_y;
3257 GtkAllocation primary;
3258 GtkAllocation secondary;
3259 EntryIconInfo *icon_info = NULL;
3261 get_frame_size (entry, TRUE, &frame_x, &frame_y, NULL, NULL);
3262 get_text_area_size (entry, &x, &y, &width, &height);
3263 get_icon_allocations (entry, &primary, &secondary);
3265 if (gtk_widget_has_focus (widget) && !priv->interior_focus)
3266 y += priv->focus_width;
3268 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
3269 x += secondary.width;
3272 width -= primary.width + secondary.width;
3276 primary.x += frame_x;
3277 primary.y += frame_y;
3278 secondary.x += frame_x;
3279 secondary.y += frame_y;
3281 if ((icon_info = priv->icons[GTK_ENTRY_ICON_PRIMARY]) != NULL)
3282 gdk_window_move_resize (icon_info->window,
3283 primary.x, primary.y,
3284 primary.width, primary.height);
3286 if ((icon_info = priv->icons[GTK_ENTRY_ICON_SECONDARY]) != NULL)
3287 gdk_window_move_resize (icon_info->window,
3288 secondary.x, secondary.y,
3289 secondary.width, secondary.height);
3291 gdk_window_move_resize (priv->text_area, x, y, width, height);
3295 gtk_entry_get_text_area_size (GtkEntry *entry,
3301 GtkEntryPrivate *priv = entry->priv;
3302 GtkWidget *widget = GTK_WIDGET (entry);
3303 GtkAllocation allocation;
3304 GtkRequisition requisition;
3309 gtk_widget_get_preferred_size (widget, &requisition, NULL);
3310 req_height = requisition.height - gtk_widget_get_margin_top (widget) - gtk_widget_get_margin_bottom (widget);
3312 gtk_widget_get_allocation (widget, &allocation);
3313 _gtk_entry_get_borders (entry, &borders);
3315 if (gtk_widget_get_realized (widget))
3316 get_frame_size (entry, TRUE, NULL, NULL, NULL, &frame_height);
3318 frame_height = req_height;
3320 if (gtk_widget_has_focus (widget) && !priv->interior_focus)
3321 frame_height -= 2 * priv->focus_width;
3327 *y = floor ((frame_height - req_height) / 2) + borders.top;
3330 *width = allocation.width - borders.left - borders.right;
3333 *height = req_height - borders.top - borders.bottom;
3337 get_text_area_size (GtkEntry *entry,
3343 GtkEntryClass *class;
3345 g_return_if_fail (GTK_IS_ENTRY (entry));
3347 class = GTK_ENTRY_GET_CLASS (entry);
3349 if (class->get_text_area_size)
3350 class->get_text_area_size (entry, x, y, width, height);
3355 get_frame_size (GtkEntry *entry,
3356 gboolean relative_to_window,
3362 GtkEntryPrivate *priv = entry->priv;
3363 GtkAllocation allocation;
3364 GtkRequisition requisition;
3365 GtkWidget *widget = GTK_WIDGET (entry);
3368 gtk_widget_get_preferred_size (widget, &requisition, NULL);
3370 req_height = requisition.height - gtk_widget_get_margin_top (widget) - gtk_widget_get_margin_bottom (widget);
3372 gtk_widget_get_allocation (widget, &allocation);
3375 *x = relative_to_window ? allocation.x : 0;
3379 if (priv->is_cell_renderer)
3382 *y = (allocation.height - req_height) / 2;
3384 if (relative_to_window)
3389 *width = allocation.width;
3393 if (priv->is_cell_renderer)
3394 *height = allocation.height;
3396 *height = req_height;
3401 gtk_entry_size_allocate (GtkWidget *widget,
3402 GtkAllocation *allocation)
3404 GtkEntry *entry = GTK_ENTRY (widget);
3406 gtk_widget_set_allocation (widget, allocation);
3408 if (gtk_widget_get_realized (widget))
3410 GtkEntryCompletion* completion;
3412 place_windows (entry);
3413 gtk_entry_recompute (entry);
3415 completion = gtk_entry_get_completion (entry);
3416 if (completion && gtk_widget_get_mapped (completion->priv->popup_window))
3417 _gtk_entry_completion_resize_popup (completion);
3422 should_prelight (GtkEntry *entry,
3423 GtkEntryIconPosition icon_pos)
3425 GtkEntryPrivate *priv = entry->priv;
3426 EntryIconInfo *icon_info = priv->icons[icon_pos];
3432 if (icon_info->nonactivatable && icon_info->target_list == NULL)
3435 if (icon_info->pressed)
3438 gtk_widget_style_get (GTK_WIDGET (entry),
3439 "icon-prelight", &prelight,
3446 draw_icon (GtkWidget *widget,
3448 GtkEntryIconPosition icon_pos)
3450 GtkEntry *entry = GTK_ENTRY (widget);
3451 GtkEntryPrivate *priv = entry->priv;
3452 EntryIconInfo *icon_info = priv->icons[icon_pos];
3453 gint x, y, width, height, pix_width, pix_height;
3454 GtkStyleContext *context;
3460 width = gdk_window_get_width (icon_info->window);
3461 height = gdk_window_get_height (icon_info->window);
3463 /* size_allocate hasn't been called yet. These are the default values.
3465 if (width == 1 || height == 1)
3469 gtk_cairo_transform_to_window (cr, widget, icon_info->window);
3471 context = gtk_widget_get_style_context (widget);
3472 gtk_entry_prepare_context_for_icon (entry, context, icon_pos);
3473 _gtk_icon_helper_get_size (icon_info->icon_helper, context,
3474 &pix_width, &pix_height);
3475 gtk_style_context_get_padding (context, 0, &padding);
3477 x = MAX (0, padding.left);
3478 y = MAX (0, (height - pix_height) / 2);
3480 _gtk_icon_helper_draw (icon_info->icon_helper,
3484 gtk_style_context_restore (context);
3490 gtk_entry_draw_frame (GtkWidget *widget,
3491 GtkStyleContext *context,
3494 GtkEntry *entry = GTK_ENTRY (widget);
3495 GtkEntryPrivate *priv = entry->priv;
3496 gint x = 0, y = 0, width, height;
3497 gint frame_x, frame_y;
3501 get_frame_size (GTK_ENTRY (widget), FALSE, &frame_x, &frame_y, &width, &height);
3503 cairo_translate (cr, frame_x, frame_y);
3505 /* Fix a problem with some themes which assume that entry->text_area's
3506 * width equals widget->window's width
3507 * http://bugzilla.gnome.org/show_bug.cgi?id=466000 */
3508 if (GTK_IS_SPIN_BUTTON (widget))
3512 gtk_entry_get_text_area_size (GTK_ENTRY (widget), &x, NULL, &width, NULL);
3513 _gtk_entry_get_borders (GTK_ENTRY (widget), &borders);
3516 width += borders.left + borders.right;
3519 if (gtk_widget_has_focus (widget) && !priv->interior_focus)
3521 x += priv->focus_width;
3522 y += priv->focus_width;
3523 width -= 2 * priv->focus_width;
3524 height -= 2 * priv->focus_width;
3527 gtk_render_background (context, cr,
3528 x, y, width, height);
3530 if (priv->has_frame)
3531 gtk_render_frame (context, cr,
3532 x, y, width, height);
3534 gtk_entry_draw_progress (widget, context, cr);
3536 if (gtk_widget_has_visible_focus (widget) && !priv->interior_focus)
3538 x -= priv->focus_width;
3539 y -= priv->focus_width;
3540 width += 2 * priv->focus_width;
3541 height += 2 * priv->focus_width;
3543 gtk_render_focus (context, cr,
3544 0, 0, width, height);
3551 gtk_entry_prepare_context_for_progress (GtkEntry *entry,
3552 GtkStyleContext *context)
3554 GtkEntryPrivate *private = entry->priv;
3556 gtk_style_context_save (context);
3557 gtk_style_context_add_class (context, GTK_STYLE_CLASS_PROGRESSBAR);
3558 if (private->progress_pulse_mode)
3559 gtk_style_context_add_class (context, GTK_STYLE_CLASS_PULSE);
3563 get_progress_area (GtkWidget *widget,
3569 GtkEntry *entry = GTK_ENTRY (widget);
3570 GtkEntryPrivate *private = entry->priv;
3571 GtkStyleContext *context;
3572 GtkBorder margin, border, entry_borders;
3573 gint frame_width, text_area_width, text_area_height;
3575 context = gtk_widget_get_style_context (widget);
3576 _gtk_entry_get_borders (entry, &entry_borders);
3577 get_text_area_size (entry,
3579 &text_area_width, &text_area_height);
3580 get_frame_size (entry, FALSE,
3582 &frame_width, NULL);
3586 *width = text_area_width + entry_borders.left + entry_borders.right;
3587 *height = text_area_height + entry_borders.top + entry_borders.bottom;
3589 /* if the text area got resized by a subclass, subtract the left/right
3590 * border width, so that the progress bar won't extend over the resized
3593 if (frame_width > *width)
3595 gtk_style_context_get_border (context, 0, &border);
3596 if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
3598 *x = (frame_width - *width) + border.left;
3599 *width -= border.left;
3603 *width -= border.right;
3607 gtk_entry_prepare_context_for_progress (entry, context);
3608 gtk_style_context_get_margin (context, 0, &margin);
3610 gtk_style_context_restore (context);
3614 *width -= margin.left + margin.right;
3615 *height -= margin.top + margin.bottom;
3617 if (private->progress_pulse_mode)
3619 gdouble value = private->progress_pulse_current;
3621 *x += (gint) floor(value * (*width));
3622 *width = (gint) ceil(private->progress_pulse_fraction * (*width));
3624 else if (private->progress_fraction > 0)
3626 gdouble value = private->progress_fraction;
3628 if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
3632 bar_width = floor(value * (*width) + 0.5);
3633 *x += *width - bar_width;
3638 *width = (gint) floor(value * (*width) + 0.5);
3649 gtk_entry_draw_progress (GtkWidget *widget,
3650 GtkStyleContext *context,
3653 GtkEntry *entry = GTK_ENTRY (widget);
3654 gint x, y, width, height;
3656 get_progress_area (widget, &x, &y, &width, &height);
3658 if ((width <= 0) || (height <= 0))
3661 gtk_entry_prepare_context_for_progress (entry, context);
3662 gtk_render_activity (context, cr,
3663 x, y, width, height);
3665 gtk_style_context_restore (context);
3669 gtk_entry_draw (GtkWidget *widget,
3672 GtkEntry *entry = GTK_ENTRY (widget);
3673 GtkStyleContext *context;
3674 GtkEntryPrivate *priv = entry->priv;
3677 context = gtk_widget_get_style_context (widget);
3679 /* Draw entry_bg, shadow, progress and focus */
3680 gtk_entry_draw_frame (widget, context, cr);
3682 /* Draw text and cursor */
3685 gtk_cairo_transform_to_window (cr, widget, priv->text_area);
3687 if (priv->dnd_position != -1)
3688 gtk_entry_draw_cursor (GTK_ENTRY (widget), cr, CURSOR_DND);
3690 gtk_entry_draw_text (GTK_ENTRY (widget), cr);
3692 /* When no text is being displayed at all, don't show the cursor */
3693 if (gtk_entry_get_display_mode (entry) != DISPLAY_BLANK &&
3694 gtk_widget_has_focus (widget) &&
3695 priv->selection_bound == priv->current_pos && priv->cursor_visible)
3696 gtk_entry_draw_cursor (GTK_ENTRY (widget), cr, CURSOR_STANDARD);
3701 for (i = 0; i < MAX_ICONS; i++)
3703 EntryIconInfo *icon_info = priv->icons[i];
3705 if (icon_info != NULL)
3706 draw_icon (widget, cr, i);
3713 gtk_entry_enter_notify (GtkWidget *widget,
3714 GdkEventCrossing *event)
3716 GtkEntry *entry = GTK_ENTRY (widget);
3717 GtkEntryPrivate *priv = entry->priv;
3720 for (i = 0; i < MAX_ICONS; i++)
3722 EntryIconInfo *icon_info = priv->icons[i];
3724 if (icon_info != NULL && event->window == icon_info->window)
3726 if (should_prelight (entry, i))
3728 icon_info->prelight = TRUE;
3729 gtk_widget_queue_draw (widget);
3740 gtk_entry_leave_notify (GtkWidget *widget,
3741 GdkEventCrossing *event)
3743 GtkEntry *entry = GTK_ENTRY (widget);
3744 GtkEntryPrivate *priv = entry->priv;
3747 for (i = 0; i < MAX_ICONS; i++)
3749 EntryIconInfo *icon_info = priv->icons[i];
3751 if (icon_info != NULL && event->window == icon_info->window)
3753 /* a grab means that we may never see the button release */
3754 if (event->mode == GDK_CROSSING_GRAB || event->mode == GDK_CROSSING_GTK_GRAB)
3755 icon_info->pressed = FALSE;
3757 if (should_prelight (entry, i))
3759 icon_info->prelight = FALSE;
3760 gtk_widget_queue_draw (widget);
3771 gtk_entry_get_pixel_ranges (GtkEntry *entry,
3775 gint start_char, end_char;
3777 if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_char, &end_char))
3779 PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
3780 PangoLayoutLine *line = pango_layout_get_lines_readonly (layout)->data;
3781 const char *text = pango_layout_get_text (layout);
3782 gint start_index = g_utf8_offset_to_pointer (text, start_char) - text;
3783 gint end_index = g_utf8_offset_to_pointer (text, end_char) - text;
3784 gint real_n_ranges, i;
3786 pango_layout_line_get_x_ranges (line, start_index, end_index, ranges, &real_n_ranges);
3792 for (i = 0; i < real_n_ranges; ++i)
3794 r[2 * i + 1] = (r[2 * i + 1] - r[2 * i]) / PANGO_SCALE;
3795 r[2 * i] = r[2 * i] / PANGO_SCALE;
3800 *n_ranges = real_n_ranges;
3812 in_selection (GtkEntry *entry,
3817 gint retval = FALSE;
3819 gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges);
3821 for (i = 0; i < n_ranges; ++i)
3823 if (x >= ranges[2 * i] && x < ranges[2 * i] + ranges[2 * i + 1])
3835 gtk_entry_button_press (GtkWidget *widget,
3836 GdkEventButton *event)
3838 GtkEntry *entry = GTK_ENTRY (widget);
3839 GtkEditable *editable = GTK_EDITABLE (widget);
3840 GtkEntryPrivate *priv = entry->priv;
3841 EntryIconInfo *icon_info = NULL;
3843 gint sel_start, sel_end;
3846 for (i = 0; i < MAX_ICONS; i++)
3848 icon_info = priv->icons[i];
3850 if (!icon_info || icon_info->insensitive)
3853 if (event->window == icon_info->window)
3855 if (should_prelight (entry, i))
3857 icon_info->prelight = FALSE;
3858 gtk_widget_queue_draw (widget);
3861 priv->start_x = event->x;
3862 priv->start_y = event->y;
3863 icon_info->pressed = TRUE;
3865 if (!icon_info->nonactivatable)
3866 g_signal_emit (entry, signals[ICON_PRESS], 0, i, event);
3872 if (event->window != priv->text_area ||
3873 (priv->button && event->button != priv->button))
3876 gtk_entry_reset_blink_time (entry);
3878 priv->button = event->button;
3879 priv->device = gdk_event_get_device ((GdkEvent *) event);
3881 if (!gtk_widget_has_focus (widget))
3883 priv->in_click = TRUE;
3884 gtk_widget_grab_focus (widget);
3885 priv->in_click = FALSE;
3888 tmp_pos = gtk_entry_find_position (entry, event->x + priv->scroll_offset);
3890 if (gdk_event_triggers_context_menu ((GdkEvent *) event))
3892 gtk_entry_do_popup (entry, event);
3893 priv->button = 0; /* Don't wait for release, since the menu will gtk_grab_add */
3894 priv->device = NULL;
3898 else if (event->button == GDK_BUTTON_PRIMARY)
3900 gboolean have_selection = gtk_editable_get_selection_bounds (editable, &sel_start, &sel_end);
3902 priv->select_words = FALSE;
3903 priv->select_lines = FALSE;
3906 gtk_widget_get_modifier_mask (widget,
3907 GDK_MODIFIER_INTENT_EXTEND_SELECTION))
3909 _gtk_entry_reset_im_context (entry);
3911 if (!have_selection) /* select from the current position to the clicked position */
3912 sel_start = sel_end = priv->current_pos;
3914 if (tmp_pos > sel_start && tmp_pos < sel_end)
3916 /* Truncate current selection, but keep it as big as possible */
3917 if (tmp_pos - sel_start > sel_end - tmp_pos)
3918 gtk_entry_set_positions (entry, sel_start, tmp_pos);
3920 gtk_entry_set_positions (entry, tmp_pos, sel_end);
3924 gboolean extend_to_left;
3927 /* Figure out what click selects and extend current selection */
3928 switch (event->type)
3930 case GDK_BUTTON_PRESS:
3931 gtk_entry_set_positions (entry, tmp_pos, tmp_pos);
3934 case GDK_2BUTTON_PRESS:
3935 priv->select_words = TRUE;
3936 gtk_entry_select_word (entry);
3939 case GDK_3BUTTON_PRESS:
3940 priv->select_lines = TRUE;
3941 gtk_entry_select_line (entry);
3948 start = MIN (priv->current_pos, priv->selection_bound);
3949 start = MIN (sel_start, start);
3951 end = MAX (priv->current_pos, priv->selection_bound);
3952 end = MAX (sel_end, end);
3954 if (tmp_pos == sel_start || tmp_pos == sel_end)
3955 extend_to_left = (tmp_pos == start);
3957 extend_to_left = (end == sel_end);
3960 gtk_entry_set_positions (entry, start, end);
3962 gtk_entry_set_positions (entry, end, start);
3965 else /* no shift key */
3966 switch (event->type)
3968 case GDK_BUTTON_PRESS:
3969 if (in_selection (entry, event->x + priv->scroll_offset))
3971 /* Click inside the selection - we'll either start a drag, or
3972 * clear the selection
3974 priv->in_drag = TRUE;
3975 priv->drag_start_x = event->x + priv->scroll_offset;
3976 priv->drag_start_y = event->y;
3979 gtk_editable_set_position (editable, tmp_pos);
3982 case GDK_2BUTTON_PRESS:
3983 /* We ALWAYS receive a GDK_BUTTON_PRESS immediately before
3984 * receiving a GDK_2BUTTON_PRESS so we need to reset
3985 * priv->in_drag which may have been set above
3987 priv->in_drag = FALSE;
3988 priv->select_words = TRUE;
3989 gtk_entry_select_word (entry);
3992 case GDK_3BUTTON_PRESS:
3993 /* We ALWAYS receive a GDK_BUTTON_PRESS immediately before
3994 * receiving a GDK_3BUTTON_PRESS so we need to reset
3995 * priv->in_drag which may have been set above
3997 priv->in_drag = FALSE;
3998 priv->select_lines = TRUE;
3999 gtk_entry_select_line (entry);
4008 else if (event->type == GDK_BUTTON_PRESS &&
4009 event->button == GDK_BUTTON_MIDDLE &&
4010 get_middle_click_paste (entry))
4014 priv->insert_pos = tmp_pos;
4015 gtk_entry_paste (entry, GDK_SELECTION_PRIMARY);
4020 gtk_widget_error_bell (widget);
4028 gtk_entry_button_release (GtkWidget *widget,
4029 GdkEventButton *event)
4031 GtkEntry *entry = GTK_ENTRY (widget);
4032 GtkEntryPrivate *priv = entry->priv;
4033 EntryIconInfo *icon_info = NULL;
4036 for (i = 0; i < MAX_ICONS; i++)
4038 icon_info = priv->icons[i];
4040 if (!icon_info || icon_info->insensitive)
4043 if (event->window == icon_info->window)
4045 icon_info->pressed = FALSE;
4047 if (should_prelight (entry, i) &&
4048 event->x >= 0 && event->y >= 0 &&
4049 event->x < gdk_window_get_width (icon_info->window) &&
4050 event->y < gdk_window_get_height (icon_info->window))
4052 icon_info->prelight = TRUE;
4053 gtk_widget_queue_draw (widget);
4056 if (!icon_info->nonactivatable)
4057 g_signal_emit (entry, signals[ICON_RELEASE], 0, i, event);
4063 if (event->window != priv->text_area || priv->button != event->button)
4068 gint tmp_pos = gtk_entry_find_position (entry, priv->drag_start_x);
4070 gtk_editable_set_position (GTK_EDITABLE (entry), tmp_pos);
4076 priv->device = NULL;
4078 gtk_entry_update_primary_selection (entry);
4084 _gtk_entry_get_selected_text (GtkEntry *entry)
4086 GtkEditable *editable = GTK_EDITABLE (entry);
4087 gint start_text, end_text;
4090 if (gtk_editable_get_selection_bounds (editable, &start_text, &end_text))
4091 text = gtk_editable_get_chars (editable, start_text, end_text);
4097 gtk_entry_motion_notify (GtkWidget *widget,
4098 GdkEventMotion *event)
4100 GtkEntry *entry = GTK_ENTRY (widget);
4101 GtkEntryPrivate *priv = entry->priv;
4102 EntryIconInfo *icon_info = NULL;
4106 for (i = 0; i < MAX_ICONS; i++)
4108 icon_info = priv->icons[i];
4110 if (!icon_info || icon_info->insensitive)
4113 if (event->window == icon_info->window)
4115 if (icon_info->pressed &&
4116 icon_info->target_list != NULL &&
4117 gtk_drag_check_threshold (widget,
4123 icon_info->in_drag = TRUE;
4124 icon_info->pressed = FALSE;
4125 gtk_drag_begin (widget,
4126 icon_info->target_list,
4136 if (priv->mouse_cursor_obscured)
4140 cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), GDK_XTERM);
4141 gdk_window_set_cursor (priv->text_area, cursor);
4142 g_object_unref (cursor);
4143 priv->mouse_cursor_obscured = FALSE;
4146 if (event->window != priv->text_area || priv->button != GDK_BUTTON_PRIMARY)
4149 if (priv->select_lines)
4152 gdk_event_request_motions (event);
4156 if (gtk_entry_get_display_mode (entry) == DISPLAY_NORMAL &&
4157 gtk_drag_check_threshold (widget,
4158 priv->drag_start_x, priv->drag_start_y,
4159 event->x + priv->scroll_offset, event->y))
4161 GdkDragContext *context;
4162 GtkTargetList *target_list = gtk_target_list_new (NULL, 0);
4163 guint actions = priv->editable ? GDK_ACTION_COPY | GDK_ACTION_MOVE : GDK_ACTION_COPY;
4165 cairo_surface_t *surface;
4167 gtk_target_list_add_text_targets (target_list, 0);
4169 text = _gtk_entry_get_selected_text (entry);
4170 surface = _gtk_text_util_create_drag_icon (widget, text, -1);
4172 context = gtk_drag_begin (widget, target_list, actions,
4173 priv->button, (GdkEvent *)event);
4176 gtk_drag_set_icon_surface (context, surface);
4178 gtk_drag_set_icon_default (context);
4181 cairo_surface_destroy (surface);
4184 priv->in_drag = FALSE;
4186 priv->device = NULL;
4188 gtk_target_list_unref (target_list);
4195 else if (event->y >= gdk_window_get_height (priv->text_area))
4196 tmp_pos = gtk_entry_buffer_get_length (get_buffer (entry));
4198 tmp_pos = gtk_entry_find_position (entry, event->x + priv->scroll_offset);
4200 if (priv->select_words)
4203 gint old_min, old_max;
4206 min = gtk_entry_move_backward_word (entry, tmp_pos, TRUE);
4207 max = gtk_entry_move_forward_word (entry, tmp_pos, TRUE);
4209 pos = priv->current_pos;
4210 bound = priv->selection_bound;
4212 old_min = MIN(priv->current_pos, priv->selection_bound);
4213 old_max = MAX(priv->current_pos, priv->selection_bound);
4220 else if (old_max < max)
4225 else if (pos == old_min)
4227 if (priv->current_pos != min)
4232 if (priv->current_pos != max)
4236 gtk_entry_set_positions (entry, pos, bound);
4239 gtk_entry_set_positions (entry, tmp_pos, -1);
4246 set_invisible_cursor (GdkWindow *window)
4248 GdkDisplay *display;
4251 display = gdk_window_get_display (window);
4252 cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR);
4254 gdk_window_set_cursor (window, cursor);
4256 g_object_unref (cursor);
4260 gtk_entry_obscure_mouse_cursor (GtkEntry *entry)
4262 GtkEntryPrivate *priv = entry->priv;
4264 if (priv->mouse_cursor_obscured)
4267 set_invisible_cursor (priv->text_area);
4269 priv->mouse_cursor_obscured = TRUE;
4273 gtk_entry_key_press (GtkWidget *widget,
4276 GtkEntry *entry = GTK_ENTRY (widget);
4277 GtkEntryPrivate *priv = entry->priv;
4279 gtk_entry_reset_blink_time (entry);
4280 gtk_entry_pend_cursor_blink (entry);
4284 if (gtk_im_context_filter_keypress (priv->im_context, event))
4286 gtk_entry_obscure_mouse_cursor (entry);
4287 priv->need_im_reset = TRUE;
4292 if (event->keyval == GDK_KEY_Return ||
4293 event->keyval == GDK_KEY_KP_Enter ||
4294 event->keyval == GDK_KEY_ISO_Enter ||
4295 event->keyval == GDK_KEY_Escape)
4297 GtkEntryCompletion *completion = gtk_entry_get_completion (entry);
4299 if (completion && completion->priv->completion_timeout)
4301 g_source_remove (completion->priv->completion_timeout);
4302 completion->priv->completion_timeout = 0;
4305 _gtk_entry_reset_im_context (entry);
4308 if (GTK_WIDGET_CLASS (gtk_entry_parent_class)->key_press_event (widget, event))
4309 /* Activate key bindings
4313 if (!priv->editable && event->length)
4314 gtk_widget_error_bell (widget);
4320 gtk_entry_key_release (GtkWidget *widget,
4323 GtkEntry *entry = GTK_ENTRY (widget);
4324 GtkEntryPrivate *priv = entry->priv;
4328 if (gtk_im_context_filter_keypress (priv->im_context, event))
4330 priv->need_im_reset = TRUE;
4335 return GTK_WIDGET_CLASS (gtk_entry_parent_class)->key_release_event (widget, event);
4339 gtk_entry_focus_in (GtkWidget *widget,
4340 GdkEventFocus *event)
4342 GtkEntry *entry = GTK_ENTRY (widget);
4343 GtkEntryPrivate *priv = entry->priv;
4346 gtk_widget_queue_draw (widget);
4348 keymap = gdk_keymap_get_for_display (gtk_widget_get_display (widget));
4352 priv->need_im_reset = TRUE;
4353 gtk_im_context_focus_in (priv->im_context);
4354 keymap_state_changed (keymap, entry);
4355 g_signal_connect (keymap, "state-changed",
4356 G_CALLBACK (keymap_state_changed), entry);
4359 g_signal_connect (keymap, "direction-changed",
4360 G_CALLBACK (keymap_direction_changed), entry);
4362 if (gtk_entry_buffer_get_bytes (get_buffer (entry)) == 0 &&
4363 priv->placeholder_text != NULL)
4365 gtk_entry_recompute (entry);
4369 gtk_entry_reset_blink_time (entry);
4370 gtk_entry_check_cursor_blink (entry);
4377 gtk_entry_focus_out (GtkWidget *widget,
4378 GdkEventFocus *event)
4380 GtkEntry *entry = GTK_ENTRY (widget);
4381 GtkEntryPrivate *priv = entry->priv;
4382 GtkEntryCompletion *completion;
4385 gtk_widget_queue_draw (widget);
4387 keymap = gdk_keymap_get_for_display (gtk_widget_get_display (widget));
4391 priv->need_im_reset = TRUE;
4392 gtk_im_context_focus_out (priv->im_context);
4393 remove_capslock_feedback (entry);
4396 if (gtk_entry_buffer_get_bytes (get_buffer (entry)) == 0 &&
4397 priv->placeholder_text != NULL)
4399 gtk_entry_recompute (entry);
4403 gtk_entry_check_cursor_blink (entry);
4406 g_signal_handlers_disconnect_by_func (keymap, keymap_state_changed, entry);
4407 g_signal_handlers_disconnect_by_func (keymap, keymap_direction_changed, entry);
4409 completion = gtk_entry_get_completion (entry);
4411 _gtk_entry_completion_popdown (completion);
4417 gtk_entry_grab_focus (GtkWidget *widget)
4419 GtkEntry *entry = GTK_ENTRY (widget);
4420 GtkEntryPrivate *priv = entry->priv;
4421 gboolean select_on_focus;
4423 GTK_WIDGET_CLASS (gtk_entry_parent_class)->grab_focus (widget);
4425 if (priv->editable && !priv->in_click)
4427 g_object_get (gtk_widget_get_settings (widget),
4428 "gtk-entry-select-on-focus",
4432 if (select_on_focus)
4433 gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
4438 gtk_entry_direction_changed (GtkWidget *widget,
4439 GtkTextDirection previous_dir)
4441 GtkEntry *entry = GTK_ENTRY (widget);
4443 gtk_entry_recompute (entry);
4445 GTK_WIDGET_CLASS (gtk_entry_parent_class)->direction_changed (widget, previous_dir);
4449 gtk_entry_state_flags_changed (GtkWidget *widget,
4450 GtkStateFlags previous_state)
4452 GtkEntry *entry = GTK_ENTRY (widget);
4453 GtkEntryPrivate *priv = entry->priv;
4456 if (gtk_widget_get_realized (widget))
4458 if (gtk_widget_is_sensitive (widget))
4459 cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), GDK_XTERM);
4463 gdk_window_set_cursor (priv->text_area, cursor);
4466 g_object_unref (cursor);
4468 priv->mouse_cursor_obscured = FALSE;
4470 update_cursors (widget);
4473 if (!gtk_widget_is_sensitive (widget))
4475 /* Clear any selection */
4476 gtk_editable_select_region (GTK_EDITABLE (entry), priv->current_pos, priv->current_pos);
4479 gtk_entry_update_cached_style_values (entry);
4483 gtk_entry_screen_changed (GtkWidget *widget,
4484 GdkScreen *old_screen)
4486 gtk_entry_recompute (GTK_ENTRY (widget));
4489 /* GtkEditable method implementations
4492 gtk_entry_insert_text (GtkEditable *editable,
4493 const gchar *new_text,
4494 gint new_text_length,
4497 g_object_ref (editable);
4500 * The incoming text may a password or other secret. We make sure
4501 * not to copy it into temporary buffers.
4504 g_signal_emit_by_name (editable, "insert-text", new_text, new_text_length, position);
4506 g_object_unref (editable);
4510 gtk_entry_delete_text (GtkEditable *editable,
4514 g_object_ref (editable);
4516 g_signal_emit_by_name (editable, "delete-text", start_pos, end_pos);
4518 g_object_unref (editable);
4522 gtk_entry_get_chars (GtkEditable *editable,
4526 GtkEntry *entry = GTK_ENTRY (editable);
4529 gint start_index, end_index;
4531 text = gtk_entry_buffer_get_text (get_buffer (entry));
4532 text_length = gtk_entry_buffer_get_length (get_buffer (entry));
4535 end_pos = text_length;
4537 start_pos = MIN (text_length, start_pos);
4538 end_pos = MIN (text_length, end_pos);
4540 start_index = g_utf8_offset_to_pointer (text, start_pos) - text;
4541 end_index = g_utf8_offset_to_pointer (text, end_pos) - text;
4543 return g_strndup (text + start_index, end_index - start_index);
4547 gtk_entry_real_set_position (GtkEditable *editable,
4550 GtkEntry *entry = GTK_ENTRY (editable);
4551 GtkEntryPrivate *priv = entry->priv;
4555 length = gtk_entry_buffer_get_length (get_buffer (entry));
4556 if (position < 0 || position > length)
4559 if (position != priv->current_pos ||
4560 position != priv->selection_bound)
4562 _gtk_entry_reset_im_context (entry);
4563 gtk_entry_set_positions (entry, position, position);
4568 gtk_entry_get_position (GtkEditable *editable)
4570 GtkEntry *entry = GTK_ENTRY (editable);
4571 GtkEntryPrivate *priv = entry->priv;
4573 return priv->current_pos;
4577 gtk_entry_set_selection_bounds (GtkEditable *editable,
4581 GtkEntry *entry = GTK_ENTRY (editable);
4584 length = gtk_entry_buffer_get_length (get_buffer (entry));
4590 _gtk_entry_reset_im_context (entry);
4592 gtk_entry_set_positions (entry,
4594 MIN (start, length));
4596 gtk_entry_update_primary_selection (entry);
4600 gtk_entry_get_selection_bounds (GtkEditable *editable,
4604 GtkEntry *entry = GTK_ENTRY (editable);
4605 GtkEntryPrivate *priv = entry->priv;
4607 *start = priv->selection_bound;
4608 *end = priv->current_pos;
4610 return (priv->selection_bound != priv->current_pos);
4614 icon_theme_changed (GtkEntry *entry)
4616 GtkEntryPrivate *priv = entry->priv;
4619 for (i = 0; i < MAX_ICONS; i++)
4621 EntryIconInfo *icon_info = priv->icons[i];
4622 if (icon_info != NULL)
4623 _gtk_icon_helper_invalidate (icon_info->icon_helper);
4626 gtk_widget_queue_draw (GTK_WIDGET (entry));
4630 gtk_entry_update_cached_style_values (GtkEntry *entry)
4632 GtkEntryPrivate *priv = entry->priv;
4634 gboolean interior_focus;
4636 gtk_widget_style_get (GTK_WIDGET (entry),
4637 "focus-line-width", &focus_width,
4638 "interior-focus", &interior_focus,
4640 priv->focus_width = focus_width;
4641 priv->interior_focus = interior_focus;
4643 if (!priv->invisible_char_set)
4645 gunichar ch = find_invisible_char (GTK_WIDGET (entry));
4647 if (priv->invisible_char != ch)
4649 priv->invisible_char = ch;
4650 g_object_notify (G_OBJECT (entry), "invisible-char");
4656 gtk_entry_style_updated (GtkWidget *widget)
4658 GtkEntry *entry = GTK_ENTRY (widget);
4660 GTK_WIDGET_CLASS (gtk_entry_parent_class)->style_updated (widget);
4662 gtk_entry_update_cached_style_values (entry);
4664 gtk_entry_recompute (entry);
4666 icon_theme_changed (entry);
4669 /* GtkCellEditable method implementations
4672 gtk_cell_editable_entry_activated (GtkEntry *entry, gpointer data)
4674 gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (entry));
4675 gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (entry));
4679 gtk_cell_editable_key_press_event (GtkEntry *entry,
4680 GdkEventKey *key_event,
4683 GtkEntryPrivate *priv = entry->priv;
4685 if (key_event->keyval == GDK_KEY_Escape)
4687 priv->editing_canceled = TRUE;
4688 gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (entry));
4689 gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (entry));
4694 /* override focus */
4695 if (key_event->keyval == GDK_KEY_Up || key_event->keyval == GDK_KEY_Down)
4697 gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (entry));
4698 gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (entry));
4707 gtk_entry_start_editing (GtkCellEditable *cell_editable,
4710 GtkEntry *entry = GTK_ENTRY (cell_editable);
4711 GtkEntryPrivate *priv = entry->priv;
4713 priv->is_cell_renderer = TRUE;
4715 g_signal_connect (cell_editable, "activate",
4716 G_CALLBACK (gtk_cell_editable_entry_activated), NULL);
4717 g_signal_connect (cell_editable, "key-press-event",
4718 G_CALLBACK (gtk_cell_editable_key_press_event), NULL);
4722 gtk_entry_password_hint_free (GtkEntryPasswordHint *password_hint)
4724 if (password_hint->source_id)
4725 g_source_remove (password_hint->source_id);
4727 g_slice_free (GtkEntryPasswordHint, password_hint);
4732 gtk_entry_remove_password_hint (gpointer data)
4734 GtkEntryPasswordHint *password_hint = g_object_get_qdata (data, quark_password_hint);
4735 password_hint->position = -1;
4737 /* Force the string to be redrawn, but now without a visible character */
4738 gtk_entry_recompute (GTK_ENTRY (data));
4742 /* Default signal handlers
4745 gtk_entry_real_insert_text (GtkEditable *editable,
4746 const gchar *new_text,
4747 gint new_text_length,
4753 n_chars = g_utf8_strlen (new_text, new_text_length);
4756 * The actual insertion into the buffer. This will end up firing the
4757 * following signal handlers: buffer_inserted_text(), buffer_notify_display_text(),
4758 * buffer_notify_text(), buffer_notify_length()
4760 begin_change (GTK_ENTRY (editable));
4762 n_inserted = gtk_entry_buffer_insert_text (get_buffer (GTK_ENTRY (editable)), *position, new_text, n_chars);
4764 end_change (GTK_ENTRY (editable));
4766 if (n_inserted != n_chars)
4767 gtk_widget_error_bell (GTK_WIDGET (editable));
4769 *position += n_inserted;
4773 gtk_entry_real_delete_text (GtkEditable *editable,
4778 * The actual deletion from the buffer. This will end up firing the
4779 * following signal handlers: buffer_deleted_text(), buffer_notify_display_text(),
4780 * buffer_notify_text(), buffer_notify_length()
4783 begin_change (GTK_ENTRY (editable));
4785 gtk_entry_buffer_delete_text (get_buffer (GTK_ENTRY (editable)), start_pos, end_pos - start_pos);
4787 end_change (GTK_ENTRY (editable));
4790 /* GtkEntryBuffer signal handlers
4793 buffer_inserted_text (GtkEntryBuffer *buffer,
4799 GtkEntryPrivate *priv = entry->priv;
4800 guint password_hint_timeout;
4802 gint selection_bound;
4804 current_pos = priv->current_pos;
4805 if (current_pos > position)
4806 current_pos += n_chars;
4808 selection_bound = priv->selection_bound;
4809 if (selection_bound > position)
4810 selection_bound += n_chars;
4812 gtk_entry_set_positions (entry, current_pos, selection_bound);
4814 /* Calculate the password hint if it needs to be displayed. */
4815 if (n_chars == 1 && !priv->visible)
4817 g_object_get (gtk_widget_get_settings (GTK_WIDGET (entry)),
4818 "gtk-entry-password-hint-timeout", &password_hint_timeout,
4821 if (password_hint_timeout > 0)
4823 GtkEntryPasswordHint *password_hint = g_object_get_qdata (G_OBJECT (entry),
4824 quark_password_hint);
4827 password_hint = g_slice_new0 (GtkEntryPasswordHint);
4828 g_object_set_qdata_full (G_OBJECT (entry), quark_password_hint, password_hint,
4829 (GDestroyNotify)gtk_entry_password_hint_free);
4832 password_hint->position = position;
4833 if (password_hint->source_id)
4834 g_source_remove (password_hint->source_id);
4835 password_hint->source_id = gdk_threads_add_timeout (password_hint_timeout,
4836 (GSourceFunc)gtk_entry_remove_password_hint, entry);
4842 buffer_deleted_text (GtkEntryBuffer *buffer,
4847 GtkEntryPrivate *priv = entry->priv;
4848 guint end_pos = position + n_chars;
4849 gint selection_bound;
4852 current_pos = priv->current_pos;
4853 if (current_pos > position)
4854 current_pos -= MIN (current_pos, end_pos) - position;
4856 selection_bound = priv->selection_bound;
4857 if (selection_bound > position)
4858 selection_bound -= MIN (selection_bound, end_pos) - position;
4860 gtk_entry_set_positions (entry, current_pos, selection_bound);
4862 /* We might have deleted the selection */
4863 gtk_entry_update_primary_selection (entry);
4865 /* Disable the password hint if one exists. */
4868 GtkEntryPasswordHint *password_hint = g_object_get_qdata (G_OBJECT (entry),
4869 quark_password_hint);
4872 if (password_hint->source_id)
4873 g_source_remove (password_hint->source_id);
4874 password_hint->source_id = 0;
4875 password_hint->position = -1;
4881 buffer_notify_text (GtkEntryBuffer *buffer,
4885 gtk_entry_recompute (entry);
4886 emit_changed (entry);
4887 g_object_notify (G_OBJECT (entry), "text");
4891 buffer_notify_length (GtkEntryBuffer *buffer,
4895 g_object_notify (G_OBJECT (entry), "text-length");
4899 buffer_notify_max_length (GtkEntryBuffer *buffer,
4903 g_object_notify (G_OBJECT (entry), "max-length");
4907 buffer_connect_signals (GtkEntry *entry)
4909 g_signal_connect (get_buffer (entry), "inserted-text", G_CALLBACK (buffer_inserted_text), entry);
4910 g_signal_connect (get_buffer (entry), "deleted-text", G_CALLBACK (buffer_deleted_text), entry);
4911 g_signal_connect (get_buffer (entry), "notify::text", G_CALLBACK (buffer_notify_text), entry);
4912 g_signal_connect (get_buffer (entry), "notify::length", G_CALLBACK (buffer_notify_length), entry);
4913 g_signal_connect (get_buffer (entry), "notify::max-length", G_CALLBACK (buffer_notify_max_length), entry);
4917 buffer_disconnect_signals (GtkEntry *entry)
4919 g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_inserted_text, entry);
4920 g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_deleted_text, entry);
4921 g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_notify_text, entry);
4922 g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_notify_length, entry);
4923 g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_notify_max_length, entry);
4926 /* Compute the X position for an offset that corresponds to the "more important
4927 * cursor position for that offset. We use this when trying to guess to which
4928 * end of the selection we should go to when the user hits the left or
4932 get_better_cursor_x (GtkEntry *entry,
4935 GtkEntryPrivate *priv = entry->priv;
4936 GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (entry)));
4937 PangoDirection keymap_direction = gdk_keymap_get_direction (keymap);
4938 gboolean split_cursor;
4940 PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
4941 const gchar *text = pango_layout_get_text (layout);
4942 gint index = g_utf8_offset_to_pointer (text, offset) - text;
4944 PangoRectangle strong_pos, weak_pos;
4946 g_object_get (gtk_widget_get_settings (GTK_WIDGET (entry)),
4947 "gtk-split-cursor", &split_cursor,
4950 pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos);
4953 return strong_pos.x / PANGO_SCALE;
4955 return (keymap_direction == priv->resolved_dir) ? strong_pos.x / PANGO_SCALE : weak_pos.x / PANGO_SCALE;
4959 gtk_entry_move_cursor (GtkEntry *entry,
4960 GtkMovementStep step,
4962 gboolean extend_selection)
4964 GtkEntryPrivate *priv = entry->priv;
4965 gint new_pos = priv->current_pos;
4967 _gtk_entry_reset_im_context (entry);
4969 if (priv->current_pos != priv->selection_bound && !extend_selection)
4971 /* If we have a current selection and aren't extending it, move to the
4972 * start/or end of the selection as appropriate
4976 case GTK_MOVEMENT_VISUAL_POSITIONS:
4978 gint current_x = get_better_cursor_x (entry, priv->current_pos);
4979 gint bound_x = get_better_cursor_x (entry, priv->selection_bound);
4982 new_pos = current_x < bound_x ? priv->current_pos : priv->selection_bound;
4984 new_pos = current_x > bound_x ? priv->current_pos : priv->selection_bound;
4987 case GTK_MOVEMENT_LOGICAL_POSITIONS:
4988 case GTK_MOVEMENT_WORDS:
4990 new_pos = MIN (priv->current_pos, priv->selection_bound);
4992 new_pos = MAX (priv->current_pos, priv->selection_bound);
4994 case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
4995 case GTK_MOVEMENT_PARAGRAPH_ENDS:
4996 case GTK_MOVEMENT_BUFFER_ENDS:
4997 new_pos = count < 0 ? 0 : gtk_entry_buffer_get_length (get_buffer (entry));
4999 case GTK_MOVEMENT_DISPLAY_LINES:
5000 case GTK_MOVEMENT_PARAGRAPHS:
5001 case GTK_MOVEMENT_PAGES:
5002 case GTK_MOVEMENT_HORIZONTAL_PAGES:
5010 case GTK_MOVEMENT_LOGICAL_POSITIONS:
5011 new_pos = gtk_entry_move_logically (entry, new_pos, count);
5013 case GTK_MOVEMENT_VISUAL_POSITIONS:
5014 new_pos = gtk_entry_move_visually (entry, new_pos, count);
5015 if (priv->current_pos == new_pos)
5017 if (!extend_selection)
5019 if (!gtk_widget_keynav_failed (GTK_WIDGET (entry),
5021 GTK_DIR_RIGHT : GTK_DIR_LEFT))
5023 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (entry));
5026 gtk_widget_child_focus (toplevel,
5028 GTK_DIR_RIGHT : GTK_DIR_LEFT);
5033 gtk_widget_error_bell (GTK_WIDGET (entry));
5037 case GTK_MOVEMENT_WORDS:
5040 new_pos = gtk_entry_move_forward_word (entry, new_pos, FALSE);
5045 new_pos = gtk_entry_move_backward_word (entry, new_pos, FALSE);
5048 if (priv->current_pos == new_pos)
5049 gtk_widget_error_bell (GTK_WIDGET (entry));
5051 case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
5052 case GTK_MOVEMENT_PARAGRAPH_ENDS:
5053 case GTK_MOVEMENT_BUFFER_ENDS:
5054 new_pos = count < 0 ? 0 : gtk_entry_buffer_get_length (get_buffer (entry));
5055 if (priv->current_pos == new_pos)
5056 gtk_widget_error_bell (GTK_WIDGET (entry));
5058 case GTK_MOVEMENT_DISPLAY_LINES:
5059 case GTK_MOVEMENT_PARAGRAPHS:
5060 case GTK_MOVEMENT_PAGES:
5061 case GTK_MOVEMENT_HORIZONTAL_PAGES:
5066 if (extend_selection)
5067 gtk_editable_select_region (GTK_EDITABLE (entry), priv->selection_bound, new_pos);
5069 gtk_editable_set_position (GTK_EDITABLE (entry), new_pos);
5071 gtk_entry_pend_cursor_blink (entry);
5075 gtk_entry_insert_at_cursor (GtkEntry *entry,
5078 GtkEntryPrivate *priv = entry->priv;
5079 GtkEditable *editable = GTK_EDITABLE (entry);
5080 gint pos = priv->current_pos;
5084 _gtk_entry_reset_im_context (entry);
5086 gtk_editable_insert_text (editable, str, -1, &pos);
5087 gtk_editable_set_position (editable, pos);
5092 gtk_entry_delete_from_cursor (GtkEntry *entry,
5096 GtkEntryPrivate *priv = entry->priv;
5097 GtkEditable *editable = GTK_EDITABLE (entry);
5098 gint start_pos = priv->current_pos;
5099 gint end_pos = priv->current_pos;
5100 gint old_n_bytes = gtk_entry_buffer_get_bytes (get_buffer (entry));
5102 _gtk_entry_reset_im_context (entry);
5104 if (!priv->editable)
5106 gtk_widget_error_bell (GTK_WIDGET (entry));
5110 if (priv->selection_bound != priv->current_pos)
5112 gtk_editable_delete_selection (editable);
5118 case GTK_DELETE_CHARS:
5119 end_pos = gtk_entry_move_logically (entry, priv->current_pos, count);
5120 gtk_editable_delete_text (editable, MIN (start_pos, end_pos), MAX (start_pos, end_pos));
5122 case GTK_DELETE_WORDS:
5125 /* Move to end of current word, or if not on a word, end of previous word */
5126 end_pos = gtk_entry_move_backward_word (entry, end_pos, FALSE);
5127 end_pos = gtk_entry_move_forward_word (entry, end_pos, FALSE);
5131 /* Move to beginning of current word, or if not on a word, begining of next word */
5132 start_pos = gtk_entry_move_forward_word (entry, start_pos, FALSE);
5133 start_pos = gtk_entry_move_backward_word (entry, start_pos, FALSE);
5137 case GTK_DELETE_WORD_ENDS:
5140 start_pos = gtk_entry_move_backward_word (entry, start_pos, FALSE);
5145 end_pos = gtk_entry_move_forward_word (entry, end_pos, FALSE);
5148 gtk_editable_delete_text (editable, start_pos, end_pos);
5150 case GTK_DELETE_DISPLAY_LINE_ENDS:
5151 case GTK_DELETE_PARAGRAPH_ENDS:
5153 gtk_editable_delete_text (editable, 0, priv->current_pos);
5155 gtk_editable_delete_text (editable, priv->current_pos, -1);
5157 case GTK_DELETE_DISPLAY_LINES:
5158 case GTK_DELETE_PARAGRAPHS:
5159 gtk_editable_delete_text (editable, 0, -1);
5161 case GTK_DELETE_WHITESPACE:
5162 gtk_entry_delete_whitespace (entry);
5166 if (gtk_entry_buffer_get_bytes (get_buffer (entry)) == old_n_bytes)
5167 gtk_widget_error_bell (GTK_WIDGET (entry));
5169 gtk_entry_pend_cursor_blink (entry);
5173 gtk_entry_backspace (GtkEntry *entry)
5175 GtkEntryPrivate *priv = entry->priv;
5176 GtkEditable *editable = GTK_EDITABLE (entry);
5179 _gtk_entry_reset_im_context (entry);
5181 if (!priv->editable)
5183 gtk_widget_error_bell (GTK_WIDGET (entry));
5187 if (priv->selection_bound != priv->current_pos)
5189 gtk_editable_delete_selection (editable);
5193 prev_pos = gtk_entry_move_logically (entry, priv->current_pos, -1);
5195 if (prev_pos < priv->current_pos)
5197 PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
5198 PangoLogAttr *log_attrs;
5201 pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
5203 /* Deleting parts of characters */
5204 if (log_attrs[priv->current_pos].backspace_deletes_character)
5206 gchar *cluster_text;
5207 gchar *normalized_text;
5210 cluster_text = _gtk_entry_get_display_text (entry, prev_pos,
5212 normalized_text = g_utf8_normalize (cluster_text,
5213 strlen (cluster_text),
5215 len = g_utf8_strlen (normalized_text, -1);
5217 gtk_editable_delete_text (editable, prev_pos, priv->current_pos);
5220 gint pos = priv->current_pos;
5222 gtk_editable_insert_text (editable, normalized_text,
5223 g_utf8_offset_to_pointer (normalized_text, len - 1) - normalized_text,
5225 gtk_editable_set_position (editable, pos);
5228 g_free (normalized_text);
5229 g_free (cluster_text);
5233 gtk_editable_delete_text (editable, prev_pos, priv->current_pos);
5240 gtk_widget_error_bell (GTK_WIDGET (entry));
5243 gtk_entry_pend_cursor_blink (entry);
5247 gtk_entry_copy_clipboard (GtkEntry *entry)
5249 GtkEntryPrivate *priv = entry->priv;
5250 GtkEditable *editable = GTK_EDITABLE (entry);
5254 if (gtk_editable_get_selection_bounds (editable, &start, &end))
5258 gtk_widget_error_bell (GTK_WIDGET (entry));
5262 str = _gtk_entry_get_display_text (entry, start, end);
5263 gtk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (entry),
5264 GDK_SELECTION_CLIPBOARD),
5271 gtk_entry_cut_clipboard (GtkEntry *entry)
5273 GtkEntryPrivate *priv = entry->priv;
5274 GtkEditable *editable = GTK_EDITABLE (entry);
5279 gtk_widget_error_bell (GTK_WIDGET (entry));
5283 gtk_entry_copy_clipboard (entry);
5287 if (gtk_editable_get_selection_bounds (editable, &start, &end))
5288 gtk_editable_delete_text (editable, start, end);
5292 gtk_widget_error_bell (GTK_WIDGET (entry));
5297 gtk_entry_paste_clipboard (GtkEntry *entry)
5299 GtkEntryPrivate *priv = entry->priv;
5302 gtk_entry_paste (entry, GDK_SELECTION_CLIPBOARD);
5304 gtk_widget_error_bell (GTK_WIDGET (entry));
5308 gtk_entry_delete_cb (GtkEntry *entry)
5310 GtkEntryPrivate *priv = entry->priv;
5311 GtkEditable *editable = GTK_EDITABLE (entry);
5316 if (gtk_editable_get_selection_bounds (editable, &start, &end))
5317 gtk_editable_delete_text (editable, start, end);
5322 gtk_entry_toggle_overwrite (GtkEntry *entry)
5324 GtkEntryPrivate *priv = entry->priv;
5326 priv->overwrite_mode = !priv->overwrite_mode;
5327 gtk_entry_pend_cursor_blink (entry);
5328 gtk_widget_queue_draw (GTK_WIDGET (entry));
5332 gtk_entry_select_all (GtkEntry *entry)
5334 gtk_entry_select_line (entry);
5338 gtk_entry_real_activate (GtkEntry *entry)
5340 GtkEntryPrivate *priv = entry->priv;
5342 GtkWidget *default_widget, *focus_widget;
5343 GtkWidget *toplevel;
5346 widget = GTK_WIDGET (entry);
5348 if (priv->activates_default)
5350 toplevel = gtk_widget_get_toplevel (widget);
5351 if (GTK_IS_WINDOW (toplevel))
5353 window = GTK_WINDOW (toplevel);
5357 default_widget = gtk_window_get_default_widget (window);
5358 focus_widget = gtk_window_get_focus (window);
5359 if (widget != default_widget &&
5360 !(widget == focus_widget && (!default_widget || !gtk_widget_get_sensitive (default_widget))))
5361 gtk_window_activate_default (window);
5368 keymap_direction_changed (GdkKeymap *keymap,
5371 gtk_entry_recompute (entry);
5374 /* IM Context Callbacks
5378 gtk_entry_commit_cb (GtkIMContext *context,
5382 GtkEntryPrivate *priv = entry->priv;
5385 gtk_entry_enter_text (entry, str);
5389 gtk_entry_preedit_changed_cb (GtkIMContext *context,
5392 GtkEntryPrivate *priv = entry->priv;
5396 gchar *preedit_string;
5399 gtk_im_context_get_preedit_string (priv->im_context,
5400 &preedit_string, NULL,
5402 g_signal_emit (entry, signals[PREEDIT_CHANGED], 0, preedit_string);
5403 priv->preedit_length = strlen (preedit_string);
5404 cursor_pos = CLAMP (cursor_pos, 0, g_utf8_strlen (preedit_string, -1));
5405 priv->preedit_cursor = cursor_pos;
5406 g_free (preedit_string);
5408 gtk_entry_recompute (entry);
5413 gtk_entry_retrieve_surrounding_cb (GtkIMContext *context,
5416 GtkEntryPrivate *priv = entry->priv;
5419 /* XXXX ??? does this even make sense when text is not visible? Should we return FALSE? */
5420 text = _gtk_entry_get_display_text (entry, 0, -1);
5421 gtk_im_context_set_surrounding (context, text, strlen (text), /* Length in bytes */
5422 g_utf8_offset_to_pointer (text, priv->current_pos) - text);
5429 gtk_entry_delete_surrounding_cb (GtkIMContext *slave,
5434 GtkEntryPrivate *priv = entry->priv;
5437 gtk_editable_delete_text (GTK_EDITABLE (entry),
5438 priv->current_pos + offset,
5439 priv->current_pos + offset + n_chars);
5444 /* Internal functions
5447 /* Used for im_commit_cb and inserting Unicode chars */
5449 gtk_entry_enter_text (GtkEntry *entry,
5452 GtkEntryPrivate *priv = entry->priv;
5453 GtkEditable *editable = GTK_EDITABLE (entry);
5455 gboolean old_need_im_reset;
5457 old_need_im_reset = priv->need_im_reset;
5458 priv->need_im_reset = FALSE;
5460 if (gtk_editable_get_selection_bounds (editable, NULL, NULL))
5461 gtk_editable_delete_selection (editable);
5464 if (priv->overwrite_mode)
5465 gtk_entry_delete_from_cursor (entry, GTK_DELETE_CHARS, 1);
5468 tmp_pos = priv->current_pos;
5469 gtk_editable_insert_text (editable, str, strlen (str), &tmp_pos);
5470 gtk_editable_set_position (editable, tmp_pos);
5472 priv->need_im_reset = old_need_im_reset;
5475 /* All changes to priv->current_pos and priv->selection_bound
5476 * should go through this function.
5479 gtk_entry_set_positions (GtkEntry *entry,
5481 gint selection_bound)
5483 GtkEntryPrivate *priv = entry->priv;
5484 gboolean changed = FALSE;
5486 g_object_freeze_notify (G_OBJECT (entry));
5488 if (current_pos != -1 &&
5489 priv->current_pos != current_pos)
5491 priv->current_pos = current_pos;
5494 g_object_notify (G_OBJECT (entry), "cursor-position");
5497 if (selection_bound != -1 &&
5498 priv->selection_bound != selection_bound)
5500 priv->selection_bound = selection_bound;
5503 g_object_notify (G_OBJECT (entry), "selection-bound");
5506 g_object_thaw_notify (G_OBJECT (entry));
5510 gtk_entry_move_adjustments (entry);
5511 gtk_entry_recompute (entry);
5516 gtk_entry_reset_layout (GtkEntry *entry)
5518 GtkEntryPrivate *priv = entry->priv;
5520 if (priv->cached_layout)
5522 g_object_unref (priv->cached_layout);
5523 priv->cached_layout = NULL;
5528 update_im_cursor_location (GtkEntry *entry)
5530 GtkEntryPrivate *priv = entry->priv;
5533 gint strong_xoffset;
5534 gint area_width, area_height;
5536 gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &strong_x, NULL);
5537 gtk_entry_get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
5539 strong_xoffset = strong_x - priv->scroll_offset;
5540 if (strong_xoffset < 0)
5544 else if (strong_xoffset > area_width)
5546 strong_xoffset = area_width;
5548 area.x = strong_xoffset;
5551 area.height = area_height;
5553 gtk_im_context_set_cursor_location (priv->im_context, &area);
5557 recompute_idle_func (gpointer data)
5559 GtkEntry *entry = GTK_ENTRY (data);
5560 GtkEntryPrivate *priv = entry->priv;
5562 priv->recompute_idle = 0;
5564 if (gtk_widget_has_screen (GTK_WIDGET (entry)))
5566 gtk_entry_adjust_scroll (entry);
5567 gtk_widget_queue_draw (GTK_WIDGET (entry));
5569 update_im_cursor_location (entry);
5576 gtk_entry_recompute (GtkEntry *entry)
5578 GtkEntryPrivate *priv = entry->priv;
5580 gtk_entry_reset_layout (entry);
5581 gtk_entry_check_cursor_blink (entry);
5583 if (!priv->recompute_idle)
5585 priv->recompute_idle = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 15, /* between resize and redraw */
5586 recompute_idle_func, entry, NULL);
5591 gtk_entry_get_placeholder_text_color (GtkEntry *entry,
5594 GtkWidget *widget = GTK_WIDGET (entry);
5595 GtkStyleContext *context;
5596 GdkRGBA fg = { 0.5, 0.5, 0.5 };
5598 context = gtk_widget_get_style_context (widget);
5599 gtk_style_context_lookup_color (context, "placeholder_text_color", &fg);
5601 color->red = CLAMP (fg.red * 65535. + 0.5, 0, 65535);
5602 color->green = CLAMP (fg.green * 65535. + 0.5, 0, 65535);
5603 color->blue = CLAMP (fg.blue * 65535. + 0.5, 0, 65535);
5606 static inline gboolean
5607 show_placeholder_text (GtkEntry *entry)
5609 GtkEntryPrivate *priv = entry->priv;
5611 if (!gtk_widget_has_focus (GTK_WIDGET (entry)) &&
5612 gtk_entry_buffer_get_bytes (get_buffer (entry)) == 0 &&
5613 priv->placeholder_text != NULL)
5619 static PangoLayout *
5620 gtk_entry_create_layout (GtkEntry *entry,
5621 gboolean include_preedit)
5623 GtkEntryPrivate *priv = entry->priv;
5624 GtkWidget *widget = GTK_WIDGET (entry);
5625 PangoLayout *layout = gtk_widget_create_pango_layout (widget, NULL);
5626 PangoAttrList *tmp_attrs = pango_attr_list_new ();
5627 gboolean placeholder_layout = show_placeholder_text (entry);
5629 gchar *preedit_string = NULL;
5630 gint preedit_length = 0;
5631 PangoAttrList *preedit_attrs = NULL;
5636 pango_layout_set_single_paragraph_mode (layout, TRUE);
5638 display = placeholder_layout ? g_strdup (priv->placeholder_text) : _gtk_entry_get_display_text (entry, 0, -1);
5639 n_bytes = strlen (display);
5641 if (!placeholder_layout && include_preedit)
5643 gtk_im_context_get_preedit_string (priv->im_context,
5644 &preedit_string, &preedit_attrs, NULL);
5645 preedit_length = priv->preedit_length;
5647 else if (placeholder_layout)
5650 PangoAttribute *attr;
5652 gtk_entry_get_placeholder_text_color (entry, &color);
5653 attr = pango_attr_foreground_new (color.red, color.green, color.blue);
5654 attr->start_index = 0;
5655 attr->end_index = G_MAXINT;
5656 pango_attr_list_insert (tmp_attrs, attr);
5661 GString *tmp_string = g_string_new (display);
5662 gint cursor_index = g_utf8_offset_to_pointer (display, priv->current_pos) - display;
5664 g_string_insert (tmp_string, cursor_index, preedit_string);
5666 pango_layout_set_text (layout, tmp_string->str, tmp_string->len);
5668 pango_attr_list_splice (tmp_attrs, preedit_attrs,
5669 cursor_index, preedit_length);
5671 g_string_free (tmp_string, TRUE);
5675 PangoDirection pango_dir;
5677 if (gtk_entry_get_display_mode (entry) == DISPLAY_NORMAL)
5678 pango_dir = pango_find_base_dir (display, n_bytes);
5680 pango_dir = PANGO_DIRECTION_NEUTRAL;
5682 if (pango_dir == PANGO_DIRECTION_NEUTRAL)
5684 if (gtk_widget_has_focus (widget))
5686 GdkDisplay *display = gtk_widget_get_display (widget);
5687 GdkKeymap *keymap = gdk_keymap_get_for_display (display);
5688 if (gdk_keymap_get_direction (keymap) == PANGO_DIRECTION_RTL)
5689 pango_dir = PANGO_DIRECTION_RTL;
5691 pango_dir = PANGO_DIRECTION_LTR;
5695 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
5696 pango_dir = PANGO_DIRECTION_RTL;
5698 pango_dir = PANGO_DIRECTION_LTR;
5702 pango_context_set_base_dir (gtk_widget_get_pango_context (widget),
5705 priv->resolved_dir = pango_dir;
5707 pango_layout_set_text (layout, display, n_bytes);
5710 pango_layout_set_attributes (layout, tmp_attrs);
5712 g_free (preedit_string);
5716 pango_attr_list_unref (preedit_attrs);
5718 pango_attr_list_unref (tmp_attrs);
5723 static PangoLayout *
5724 gtk_entry_ensure_layout (GtkEntry *entry,
5725 gboolean include_preedit)
5727 GtkEntryPrivate *priv = entry->priv;
5729 if (priv->preedit_length > 0 &&
5730 !include_preedit != !priv->cache_includes_preedit)
5731 gtk_entry_reset_layout (entry);
5733 if (!priv->cached_layout)
5735 priv->cached_layout = gtk_entry_create_layout (entry, include_preedit);
5736 priv->cache_includes_preedit = include_preedit;
5739 return priv->cached_layout;
5743 get_layout_position (GtkEntry *entry,
5747 GtkEntryPrivate *priv = entry->priv;
5748 PangoLayout *layout;
5749 PangoRectangle logical_rect;
5750 gint area_width, area_height;
5752 PangoLayoutLine *line;
5754 layout = gtk_entry_ensure_layout (entry, TRUE);
5756 gtk_entry_get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
5757 area_height = PANGO_SCALE * area_height;
5759 line = pango_layout_get_lines_readonly (layout)->data;
5760 pango_layout_line_get_extents (line, NULL, &logical_rect);
5762 /* Align primarily for locale's ascent/descent */
5763 y_pos = ((area_height - priv->ascent - priv->descent) / 2 +
5764 priv->ascent + logical_rect.y);
5766 /* Now see if we need to adjust to fit in actual drawn string */
5767 if (logical_rect.height > area_height)
5768 y_pos = (area_height - logical_rect.height) / 2;
5771 else if (y_pos + logical_rect.height > area_height)
5772 y_pos = area_height - logical_rect.height;
5774 y_pos = y_pos / PANGO_SCALE;
5777 *x = - priv->scroll_offset;
5784 draw_text_with_color (GtkEntry *entry,
5786 GdkRGBA *default_color)
5788 GtkEntryPrivate *priv = entry->priv;
5789 PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
5792 gint start_pos, end_pos;
5794 widget = GTK_WIDGET (entry);
5798 get_layout_position (entry, &x, &y);
5800 cairo_move_to (cr, x, y);
5801 gdk_cairo_set_source_rgba (cr, default_color);
5802 pango_cairo_show_layout (cr, layout);
5804 if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos))
5808 PangoRectangle logical_rect;
5809 GdkRGBA selection_color, text_color;
5810 GtkStyleContext *context;
5811 GtkStateFlags state;
5813 context = gtk_widget_get_style_context (widget);
5814 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
5815 gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges);
5817 state = gtk_widget_get_state_flags (widget);
5818 state |= GTK_STATE_FLAG_SELECTED;
5820 gtk_style_context_get_background_color (context, state, &selection_color);
5821 gtk_style_context_get_color (context, state, &text_color);
5823 for (i = 0; i < n_ranges; ++i)
5824 cairo_rectangle (cr,
5825 - priv->scroll_offset + ranges[2 * i],
5828 logical_rect.height);
5832 gdk_cairo_set_source_rgba (cr, &selection_color);
5835 cairo_move_to (cr, x, y);
5836 gdk_cairo_set_source_rgba (cr, &text_color);
5837 pango_cairo_show_layout (cr, layout);
5845 gtk_entry_draw_text (GtkEntry *entry,
5848 GtkEntryPrivate *priv = entry->priv;
5849 GtkWidget *widget = GTK_WIDGET (entry);
5850 GtkStateFlags state = 0;
5851 GdkRGBA text_color, bar_text_color;
5852 GtkStyleContext *context;
5854 gint progress_x, progress_y, progress_width, progress_height;
5855 gint clip_width, clip_height;
5857 /* Nothing to display at all */
5858 if (gtk_entry_get_display_mode (entry) == DISPLAY_BLANK)
5861 state = gtk_widget_get_state_flags (widget);
5862 context = gtk_widget_get_style_context (widget);
5864 gtk_style_context_get_color (context, state, &text_color);
5866 /* Get foreground color for progressbars */
5867 gtk_entry_prepare_context_for_progress (entry, context);
5868 gtk_style_context_get_color (context, state, &bar_text_color);
5869 gtk_style_context_restore (context);
5871 get_progress_area (widget,
5872 &progress_x, &progress_y,
5873 &progress_width, &progress_height);
5877 clip_width = gdk_window_get_width (priv->text_area);
5878 clip_height = gdk_window_get_height (priv->text_area);
5879 cairo_rectangle (cr, 0, 0, clip_width, clip_height);
5882 /* If the color is the same, or the progress area has a zero
5883 * size, then we only need to draw once. */
5884 if (gdk_rgba_equal (&text_color, &bar_text_color) ||
5885 ((progress_width == 0) || (progress_height == 0)))
5887 draw_text_with_color (entry, cr, &text_color);
5891 int frame_x, frame_y, area_x, area_y;
5893 width = gdk_window_get_width (priv->text_area);
5894 height = gdk_window_get_height (priv->text_area);
5898 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
5899 cairo_rectangle (cr, 0, 0, width, height);
5901 /* progres area is frame-relative, we need it text-area window
5903 get_frame_size (entry, TRUE, &frame_x, &frame_y, NULL, NULL);
5904 gdk_window_get_position (priv->text_area, &area_x, &area_y);
5905 progress_x += frame_x - area_x;
5906 progress_y += frame_y - area_y;
5908 cairo_rectangle (cr, progress_x, progress_y,
5909 progress_width, progress_height);
5911 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
5913 draw_text_with_color (entry, cr, &text_color);
5918 cairo_rectangle (cr, progress_x, progress_y,
5919 progress_width, progress_height);
5922 draw_text_with_color (entry, cr, &bar_text_color);
5931 gtk_entry_draw_cursor (GtkEntry *entry,
5935 GtkEntryPrivate *priv = entry->priv;
5936 GtkWidget *widget = GTK_WIDGET (entry);
5937 GtkStyleContext *context;
5938 PangoRectangle cursor_rect;
5941 gboolean block_at_line_end;
5942 PangoLayout *layout;
5946 context = gtk_widget_get_style_context (widget);
5948 layout = gtk_entry_ensure_layout (entry, TRUE);
5949 text = pango_layout_get_text (layout);
5950 cursor_index = g_utf8_offset_to_pointer (text, priv->current_pos + priv->preedit_cursor) - text;
5951 get_layout_position (entry, &x, &y);
5953 if (!priv->overwrite_mode)
5956 block = _gtk_text_util_get_block_cursor_location (layout,
5957 cursor_index, &cursor_rect, &block_at_line_end);
5961 gtk_render_insertion_cursor (context, cr,
5963 layout, cursor_index, priv->resolved_dir);
5965 else /* overwrite_mode */
5967 GdkRGBA cursor_color;
5972 rect.x = PANGO_PIXELS (cursor_rect.x) + x;
5973 rect.y = PANGO_PIXELS (cursor_rect.y) + y;
5974 rect.width = PANGO_PIXELS (cursor_rect.width);
5975 rect.height = PANGO_PIXELS (cursor_rect.height);
5977 _gtk_style_context_get_cursor_color (context, &cursor_color, NULL);
5978 gdk_cairo_set_source_rgba (cr, &cursor_color);
5979 gdk_cairo_rectangle (cr, &rect);
5982 if (!block_at_line_end)
5984 GtkStateFlags state;
5987 state = gtk_widget_get_state_flags (widget);
5988 gtk_style_context_get_background_color (context, state, &color);
5990 gdk_cairo_rectangle (cr, &rect);
5992 cairo_move_to (cr, x, y);
5993 gdk_cairo_set_source_rgba (cr, &color);
5994 pango_cairo_show_layout (cr, layout);
6002 _gtk_entry_reset_im_context (GtkEntry *entry)
6004 GtkEntryPrivate *priv = entry->priv;
6006 if (priv->need_im_reset)
6008 priv->need_im_reset = FALSE;
6009 gtk_im_context_reset (priv->im_context);
6014 * gtk_entry_reset_im_context:
6015 * @entry: a #GtkEntry
6017 * Reset the input method context of the entry if needed.
6019 * This can be necessary in the case where modifying the buffer
6020 * would confuse on-going input method behavior.
6025 gtk_entry_reset_im_context (GtkEntry *entry)
6027 g_return_if_fail (GTK_IS_ENTRY (entry));
6029 _gtk_entry_reset_im_context (entry);
6033 * gtk_entry_im_context_filter_keypress:
6034 * @entry: a #GtkEntry
6035 * @event: (type Gdk.EventKey): the key event
6037 * Allow the #GtkEntry input method to internally handle key press
6038 * and release events. If this function returns %TRUE, then no further
6039 * processing should be done for this key event. See
6040 * gtk_im_context_filter_keypress().
6042 * Note that you are expected to call this function from your handler
6043 * when overriding key event handling. This is needed in the case when
6044 * you need to insert your own key handling between the input method
6045 * and the default key event handling of the #GtkEntry.
6046 * See gtk_text_view_reset_im_context() for an example of use.
6048 * Return value: %TRUE if the input method handled the key event.
6053 gtk_entry_im_context_filter_keypress (GtkEntry *entry,
6056 GtkEntryPrivate *priv;
6058 g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
6062 return gtk_im_context_filter_keypress (priv->im_context, event);
6066 _gtk_entry_get_im_context (GtkEntry *entry)
6068 return entry->priv->im_context;
6072 gtk_entry_find_position (GtkEntry *entry,
6075 GtkEntryPrivate *priv = entry->priv;
6076 PangoLayout *layout;
6077 PangoLayoutLine *line;
6084 layout = gtk_entry_ensure_layout (entry, TRUE);
6085 text = pango_layout_get_text (layout);
6086 cursor_index = g_utf8_offset_to_pointer (text, priv->current_pos) - text;
6088 line = pango_layout_get_lines_readonly (layout)->data;
6089 pango_layout_line_x_to_index (line, x * PANGO_SCALE, &index, &trailing);
6091 if (index >= cursor_index && priv->preedit_length)
6093 if (index >= cursor_index + priv->preedit_length)
6094 index -= priv->preedit_length;
6097 index = cursor_index;
6102 pos = g_utf8_pointer_to_offset (text, text + index);
6109 gtk_entry_get_cursor_locations (GtkEntry *entry,
6114 GtkEntryPrivate *priv = entry->priv;
6115 DisplayMode mode = gtk_entry_get_display_mode (entry);
6117 /* Nothing to display at all, so no cursor is relevant */
6118 if (mode == DISPLAY_BLANK)
6128 PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
6129 const gchar *text = pango_layout_get_text (layout);
6130 PangoRectangle strong_pos, weak_pos;
6133 if (type == CURSOR_STANDARD)
6135 index = g_utf8_offset_to_pointer (text, priv->current_pos + priv->preedit_cursor) - text;
6137 else /* type == CURSOR_DND */
6139 index = g_utf8_offset_to_pointer (text, priv->dnd_position) - text;
6141 if (priv->dnd_position > priv->current_pos)
6143 if (mode == DISPLAY_NORMAL)
6144 index += priv->preedit_length;
6147 gint preedit_len_chars = g_utf8_strlen (text, -1) - gtk_entry_buffer_get_length (get_buffer (entry));
6148 index += preedit_len_chars * g_unichar_to_utf8 (priv->invisible_char, NULL);
6153 pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos);
6156 *strong_x = strong_pos.x / PANGO_SCALE;
6159 *weak_x = weak_pos.x / PANGO_SCALE;
6164 gtk_entry_adjust_scroll (GtkEntry *entry)
6166 GtkEntryPrivate *priv = entry->priv;
6167 gint min_offset, max_offset;
6168 gint text_area_width, text_width;
6169 gint strong_x, weak_x;
6170 gint strong_xoffset, weak_xoffset;
6172 PangoLayout *layout;
6173 PangoLayoutLine *line;
6174 PangoRectangle logical_rect;
6176 if (!gtk_widget_get_realized (GTK_WIDGET (entry)))
6179 text_area_width = gdk_window_get_width (priv->text_area);
6181 if (text_area_width < 0)
6182 text_area_width = 0;
6184 layout = gtk_entry_ensure_layout (entry, TRUE);
6185 line = pango_layout_get_lines_readonly (layout)->data;
6187 pango_layout_line_get_extents (line, NULL, &logical_rect);
6189 /* Display as much text as we can */
6191 if (priv->resolved_dir == PANGO_DIRECTION_LTR)
6192 xalign = priv->xalign;
6194 xalign = 1.0 - priv->xalign;
6196 text_width = PANGO_PIXELS(logical_rect.width);
6198 if (text_width > text_area_width)
6201 max_offset = text_width - text_area_width;
6205 min_offset = (text_width - text_area_width) * xalign;
6206 max_offset = min_offset;
6209 priv->scroll_offset = CLAMP (priv->scroll_offset, min_offset, max_offset);
6211 /* And make sure cursors are on screen. Note that the cursor is
6212 * actually drawn one pixel into the INNER_BORDER space on
6213 * the right, when the scroll is at the utmost right. This
6214 * looks better to to me than confining the cursor inside the
6215 * border entirely, though it means that the cursor gets one
6216 * pixel closer to the edge of the widget on the right than
6217 * on the left. This might need changing if one changed
6218 * INNER_BORDER from 2 to 1, as one would do on a
6219 * small-screen-real-estate display.
6221 * We always make sure that the strong cursor is on screen, and
6222 * put the weak cursor on screen if possible.
6225 gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &strong_x, &weak_x);
6227 strong_xoffset = strong_x - priv->scroll_offset;
6229 if (strong_xoffset < 0)
6231 priv->scroll_offset += strong_xoffset;
6234 else if (strong_xoffset > text_area_width)
6236 priv->scroll_offset += strong_xoffset - text_area_width;
6237 strong_xoffset = text_area_width;
6240 weak_xoffset = weak_x - priv->scroll_offset;
6242 if (weak_xoffset < 0 && strong_xoffset - weak_xoffset <= text_area_width)
6244 priv->scroll_offset += weak_xoffset;
6246 else if (weak_xoffset > text_area_width &&
6247 strong_xoffset - (weak_xoffset - text_area_width) >= 0)
6249 priv->scroll_offset += weak_xoffset - text_area_width;
6252 g_object_notify (G_OBJECT (entry), "scroll-offset");
6256 gtk_entry_move_adjustments (GtkEntry *entry)
6258 GtkWidget *widget = GTK_WIDGET (entry);
6259 GtkAllocation allocation;
6260 GtkAdjustment *adjustment;
6261 PangoContext *context;
6262 PangoFontMetrics *metrics;
6263 GtkStyleContext *style_context;
6264 GtkStateFlags state;
6269 adjustment = g_object_get_qdata (G_OBJECT (entry), quark_cursor_hadjustment);
6273 gtk_widget_get_allocation (widget, &allocation);
6275 /* Cursor position, layout offset, border width, and widget allocation */
6276 gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &x, NULL);
6277 get_layout_position (entry, &layout_x, NULL);
6278 _gtk_entry_get_borders (entry, &borders);
6279 x += allocation.x + layout_x + borders.left;
6281 /* Approximate width of a char, so user can see what is ahead/behind */
6282 context = gtk_widget_get_pango_context (widget);
6283 style_context = gtk_widget_get_style_context (widget);
6284 state = gtk_widget_get_state_flags (widget);
6286 metrics = pango_context_get_metrics (context,
6287 gtk_style_context_get_font (style_context, state),
6288 pango_context_get_language (context));
6289 char_width = pango_font_metrics_get_approximate_char_width (metrics) / PANGO_SCALE;
6292 gtk_adjustment_clamp_page (adjustment,
6293 x - (char_width + 1), /* one char + one pixel before */
6294 x + (char_width + 2)); /* one char + cursor + one pixel after */
6298 gtk_entry_move_visually (GtkEntry *entry,
6302 GtkEntryPrivate *priv = entry->priv;
6304 PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
6307 text = pango_layout_get_text (layout);
6309 index = g_utf8_offset_to_pointer (text, start) - text;
6313 int new_index, new_trailing;
6314 gboolean split_cursor;
6317 g_object_get (gtk_widget_get_settings (GTK_WIDGET (entry)),
6318 "gtk-split-cursor", &split_cursor,
6325 GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (entry)));
6326 PangoDirection keymap_direction = gdk_keymap_get_direction (keymap);
6328 strong = keymap_direction == priv->resolved_dir;
6333 pango_layout_move_cursor_visually (layout, strong, index, 0, 1, &new_index, &new_trailing);
6338 pango_layout_move_cursor_visually (layout, strong, index, 0, -1, &new_index, &new_trailing);
6344 else if (new_index != G_MAXINT)
6347 while (new_trailing--)
6348 index = g_utf8_next_char (text + index) - text;
6351 return g_utf8_pointer_to_offset (text, text + index);
6355 gtk_entry_move_logically (GtkEntry *entry,
6359 gint new_pos = start;
6362 length = gtk_entry_buffer_get_length (get_buffer (entry));
6364 /* Prevent any leak of information */
6365 if (gtk_entry_get_display_mode (entry) != DISPLAY_NORMAL)
6367 new_pos = CLAMP (start + count, 0, length);
6371 PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
6372 PangoLogAttr *log_attrs;
6375 pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
6377 while (count > 0 && new_pos < length)
6381 while (new_pos < length && !log_attrs[new_pos].is_cursor_position);
6385 while (count < 0 && new_pos > 0)
6389 while (new_pos > 0 && !log_attrs[new_pos].is_cursor_position);
6401 gtk_entry_move_forward_word (GtkEntry *entry,
6403 gboolean allow_whitespace)
6405 gint new_pos = start;
6408 length = gtk_entry_buffer_get_length (get_buffer (entry));
6410 /* Prevent any leak of information */
6411 if (gtk_entry_get_display_mode (entry) != DISPLAY_NORMAL)
6415 else if (new_pos < length)
6417 PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
6418 PangoLogAttr *log_attrs;
6421 pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
6423 /* Find the next word boundary */
6425 while (new_pos < n_attrs - 1 && !(log_attrs[new_pos].is_word_end ||
6426 (log_attrs[new_pos].is_word_start && allow_whitespace)))
6437 gtk_entry_move_backward_word (GtkEntry *entry,
6439 gboolean allow_whitespace)
6441 gint new_pos = start;
6443 /* Prevent any leak of information */
6444 if (gtk_entry_get_display_mode (entry) != DISPLAY_NORMAL)
6450 PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
6451 PangoLogAttr *log_attrs;
6454 pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
6456 new_pos = start - 1;
6458 /* Find the previous word boundary */
6459 while (new_pos > 0 && !(log_attrs[new_pos].is_word_start ||
6460 (log_attrs[new_pos].is_word_end && allow_whitespace)))
6470 gtk_entry_delete_whitespace (GtkEntry *entry)
6472 GtkEntryPrivate *priv = entry->priv;
6473 PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
6474 PangoLogAttr *log_attrs;
6478 pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
6480 start = end = priv->current_pos;
6482 while (start > 0 && log_attrs[start-1].is_white)
6485 while (end < n_attrs && log_attrs[end].is_white)
6491 gtk_editable_delete_text (GTK_EDITABLE (entry), start, end);
6496 gtk_entry_select_word (GtkEntry *entry)
6498 GtkEntryPrivate *priv = entry->priv;
6499 gint start_pos = gtk_entry_move_backward_word (entry, priv->current_pos, TRUE);
6500 gint end_pos = gtk_entry_move_forward_word (entry, priv->current_pos, TRUE);
6502 gtk_editable_select_region (GTK_EDITABLE (entry), start_pos, end_pos);
6506 gtk_entry_select_line (GtkEntry *entry)
6508 gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
6512 truncate_multiline (const gchar *text)
6517 text[length] && text[length] != '\n' && text[length] != '\r';
6524 paste_received (GtkClipboard *clipboard,
6528 GtkEntry *entry = GTK_ENTRY (data);
6529 GtkEditable *editable = GTK_EDITABLE (entry);
6530 GtkEntryPrivate *priv = entry->priv;
6532 if (priv->button == GDK_BUTTON_MIDDLE)
6534 gint pos, start, end;
6535 pos = priv->insert_pos;
6536 gtk_editable_get_selection_bounds (editable, &start, &end);
6537 if (!((start <= pos && pos <= end) || (end <= pos && pos <= start)))
6538 gtk_editable_select_region (editable, pos, pos);
6543 gint pos, start, end;
6545 gboolean popup_completion;
6546 GtkEntryCompletion *completion;
6548 completion = gtk_entry_get_completion (entry);
6550 if (priv->truncate_multiline)
6551 length = truncate_multiline (text);
6553 /* only complete if the selection is at the end */
6554 popup_completion = (gtk_entry_buffer_get_length (get_buffer (entry)) ==
6555 MAX (priv->current_pos, priv->selection_bound));
6559 if (gtk_widget_get_mapped (completion->priv->popup_window))
6560 _gtk_entry_completion_popdown (completion);
6562 if (!popup_completion && completion->priv->changed_id > 0)
6563 g_signal_handler_block (entry, completion->priv->changed_id);
6566 begin_change (entry);
6567 if (gtk_editable_get_selection_bounds (editable, &start, &end))
6568 gtk_editable_delete_text (editable, start, end);
6570 pos = priv->current_pos;
6571 gtk_editable_insert_text (editable, text, length, &pos);
6572 gtk_editable_set_position (editable, pos);
6576 !popup_completion && completion->priv->changed_id > 0)
6577 g_signal_handler_unblock (entry, completion->priv->changed_id);
6580 g_object_unref (entry);
6584 gtk_entry_paste (GtkEntry *entry,
6587 g_object_ref (entry);
6588 gtk_clipboard_request_text (gtk_widget_get_clipboard (GTK_WIDGET (entry), selection),
6589 paste_received, entry);
6593 primary_get_cb (GtkClipboard *clipboard,
6594 GtkSelectionData *selection_data,
6598 GtkEntry *entry = GTK_ENTRY (data);
6601 if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start, &end))
6603 gchar *str = _gtk_entry_get_display_text (entry, start, end);
6604 gtk_selection_data_set_text (selection_data, str, -1);
6610 primary_clear_cb (GtkClipboard *clipboard,
6613 GtkEntry *entry = GTK_ENTRY (data);
6614 GtkEntryPrivate *priv = entry->priv;
6616 gtk_editable_select_region (GTK_EDITABLE (entry), priv->current_pos, priv->current_pos);
6620 gtk_entry_update_primary_selection (GtkEntry *entry)
6622 GtkTargetList *list;
6623 GtkTargetEntry *targets;
6624 GtkClipboard *clipboard;
6628 if (!gtk_widget_get_realized (GTK_WIDGET (entry)))
6631 list = gtk_target_list_new (NULL, 0);
6632 gtk_target_list_add_text_targets (list, 0);
6634 targets = gtk_target_table_new_from_list (list, &n_targets);
6636 clipboard = gtk_widget_get_clipboard (GTK_WIDGET (entry), GDK_SELECTION_PRIMARY);
6638 if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start, &end))
6640 if (!gtk_clipboard_set_with_owner (clipboard, targets, n_targets,
6641 primary_get_cb, primary_clear_cb, G_OBJECT (entry)))
6642 primary_clear_cb (clipboard, entry);
6646 if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (entry))
6647 gtk_clipboard_clear (clipboard);
6650 gtk_target_table_free (targets, n_targets);
6651 gtk_target_list_unref (list);
6655 gtk_entry_clear (GtkEntry *entry,
6656 GtkEntryIconPosition icon_pos)
6658 GtkEntryPrivate *priv = entry->priv;
6659 EntryIconInfo *icon_info = priv->icons[icon_pos];
6660 GtkImageType storage_type;
6662 if (icon_info && _gtk_icon_helper_get_is_empty (icon_info->icon_helper))
6665 g_object_freeze_notify (G_OBJECT (entry));
6667 /* Explicitly check, as the pointer may become invalidated
6668 * during destruction.
6670 if (GDK_IS_WINDOW (icon_info->window))
6671 gdk_window_hide (icon_info->window);
6673 storage_type = _gtk_icon_helper_get_storage_type (icon_info->icon_helper);
6675 switch (storage_type)
6677 case GTK_IMAGE_PIXBUF:
6678 g_object_notify (G_OBJECT (entry),
6679 icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-pixbuf" : "secondary-icon-pixbuf");
6682 case GTK_IMAGE_STOCK:
6683 g_object_notify (G_OBJECT (entry),
6684 icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-stock" : "secondary-icon-stock");
6687 case GTK_IMAGE_ICON_NAME:
6688 g_object_notify (G_OBJECT (entry),
6689 icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-name" : "secondary-icon-name");
6692 case GTK_IMAGE_GICON:
6693 g_object_notify (G_OBJECT (entry),
6694 icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-gicon" : "secondary-icon-gicon");
6698 g_assert_not_reached ();
6702 _gtk_icon_helper_clear (icon_info->icon_helper);
6704 g_object_notify (G_OBJECT (entry),
6705 icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-storage-type" : "secondary-icon-storage-type");
6707 g_object_thaw_notify (G_OBJECT (entry));
6711 gtk_entry_ensure_pixbuf (GtkEntry *entry,
6712 GtkEntryIconPosition icon_pos)
6714 GtkEntryPrivate *priv = entry->priv;
6715 EntryIconInfo *icon_info = priv->icons[icon_pos];
6716 GtkStyleContext *context;
6719 context = gtk_widget_get_style_context (GTK_WIDGET (entry));
6720 gtk_entry_prepare_context_for_icon (entry, context, icon_pos);
6722 pix = _gtk_icon_helper_ensure_pixbuf (icon_info->icon_helper,
6725 gtk_style_context_restore (context);
6736 * Creates a new entry.
6738 * Return value: a new #GtkEntry.
6741 gtk_entry_new (void)
6743 return g_object_new (GTK_TYPE_ENTRY, NULL);
6747 * gtk_entry_new_with_buffer:
6748 * @buffer: The buffer to use for the new #GtkEntry.
6750 * Creates a new entry with the specified text buffer.
6752 * Return value: a new #GtkEntry
6757 gtk_entry_new_with_buffer (GtkEntryBuffer *buffer)
6759 g_return_val_if_fail (GTK_IS_ENTRY_BUFFER (buffer), NULL);
6760 return g_object_new (GTK_TYPE_ENTRY, "buffer", buffer, NULL);
6763 static GtkEntryBuffer*
6764 get_buffer (GtkEntry *entry)
6766 GtkEntryPrivate *priv = entry->priv;
6768 if (priv->buffer == NULL)
6770 GtkEntryBuffer *buffer;
6771 buffer = gtk_entry_buffer_new (NULL, 0);
6772 gtk_entry_set_buffer (entry, buffer);
6773 g_object_unref (buffer);
6776 return priv->buffer;
6780 * gtk_entry_get_buffer:
6781 * @entry: a #GtkEntry
6783 * Get the #GtkEntryBuffer object which holds the text for
6788 * Returns: (transfer none): A #GtkEntryBuffer object.
6791 gtk_entry_get_buffer (GtkEntry *entry)
6793 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
6795 return get_buffer (entry);
6799 * gtk_entry_set_buffer:
6800 * @entry: a #GtkEntry
6801 * @buffer: a #GtkEntryBuffer
6803 * Set the #GtkEntryBuffer object which holds the text for
6809 gtk_entry_set_buffer (GtkEntry *entry,
6810 GtkEntryBuffer *buffer)
6812 GtkEntryPrivate *priv;
6815 g_return_if_fail (GTK_IS_ENTRY (entry));
6821 g_return_if_fail (GTK_IS_ENTRY_BUFFER (buffer));
6822 g_object_ref (buffer);
6827 buffer_disconnect_signals (entry);
6828 g_object_unref (priv->buffer);
6831 priv->buffer = buffer;
6834 buffer_connect_signals (entry);
6836 obj = G_OBJECT (entry);
6837 g_object_freeze_notify (obj);
6838 g_object_notify (obj, "buffer");
6839 g_object_notify (obj, "text");
6840 g_object_notify (obj, "text-length");
6841 g_object_notify (obj, "max-length");
6842 g_object_notify (obj, "visibility");
6843 g_object_notify (obj, "invisible-char");
6844 g_object_notify (obj, "invisible-char-set");
6845 g_object_thaw_notify (obj);
6847 gtk_editable_set_position (GTK_EDITABLE (entry), 0);
6848 gtk_entry_recompute (entry);
6852 * gtk_entry_get_text_area:
6853 * @entry: a #GtkEntry
6854 * @text_area: (out): Return location for the text area.
6856 * Gets the area where the entry's text is drawn. This function is
6857 * useful when drawing something to the entry in a draw callback.
6859 * If the entry is not realized, @text_area is filled with zeros.
6861 * See also gtk_entry_get_icon_area().
6866 gtk_entry_get_text_area (GtkEntry *entry,
6867 GdkRectangle *text_area)
6869 GtkEntryPrivate *priv;
6871 g_return_if_fail (GTK_IS_ENTRY (entry));
6872 g_return_if_fail (text_area != NULL);
6876 if (priv->text_area)
6878 GtkAllocation allocation;
6881 gtk_widget_get_allocation (GTK_WIDGET (entry), &allocation);
6882 gdk_window_get_position (priv->text_area, &x, &y);
6884 text_area->x = x - allocation.x;
6885 text_area->y = y - allocation.y;
6886 text_area->width = gdk_window_get_width (priv->text_area);
6887 text_area->height = gdk_window_get_height (priv->text_area);
6893 text_area->width = 0;
6894 text_area->height = 0;
6899 * gtk_entry_set_text:
6900 * @entry: a #GtkEntry
6901 * @text: the new text
6903 * Sets the text in the widget to the given
6904 * value, replacing the current contents.
6906 * See gtk_entry_buffer_set_text().
6909 gtk_entry_set_text (GtkEntry *entry,
6913 GtkEntryCompletion *completion;
6915 g_return_if_fail (GTK_IS_ENTRY (entry));
6916 g_return_if_fail (text != NULL);
6918 /* Actually setting the text will affect the cursor and selection;
6919 * if the contents don't actually change, this will look odd to the user.
6921 if (strcmp (gtk_entry_buffer_get_text (get_buffer (entry)), text) == 0)
6924 completion = gtk_entry_get_completion (entry);
6925 if (completion && completion->priv->changed_id > 0)
6926 g_signal_handler_block (entry, completion->priv->changed_id);
6928 begin_change (entry);
6929 gtk_editable_delete_text (GTK_EDITABLE (entry), 0, -1);
6931 gtk_editable_insert_text (GTK_EDITABLE (entry), text, strlen (text), &tmp_pos);
6934 if (completion && completion->priv->changed_id > 0)
6935 g_signal_handler_unblock (entry, completion->priv->changed_id);
6939 * gtk_entry_set_visibility:
6940 * @entry: a #GtkEntry
6941 * @visible: %TRUE if the contents of the entry are displayed
6944 * Sets whether the contents of the entry are visible or not.
6945 * When visibility is set to %FALSE, characters are displayed
6946 * as the invisible char, and will also appear that way when
6947 * the text in the entry widget is copied elsewhere.
6949 * By default, GTK+ picks the best invisible character available
6950 * in the current font, but it can be changed with
6951 * gtk_entry_set_invisible_char().
6954 gtk_entry_set_visibility (GtkEntry *entry,
6957 GtkEntryPrivate *priv;
6959 g_return_if_fail (GTK_IS_ENTRY (entry));
6963 visible = visible != FALSE;
6965 if (priv->visible != visible)
6967 priv->visible = visible;
6969 g_object_notify (G_OBJECT (entry), "visibility");
6970 gtk_entry_recompute (entry);
6975 * gtk_entry_get_visibility:
6976 * @entry: a #GtkEntry
6978 * Retrieves whether the text in @entry is visible. See
6979 * gtk_entry_set_visibility().
6981 * Return value: %TRUE if the text is currently visible
6984 gtk_entry_get_visibility (GtkEntry *entry)
6986 g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
6988 return entry->priv->visible;
6992 * gtk_entry_set_invisible_char:
6993 * @entry: a #GtkEntry
6994 * @ch: a Unicode character
6996 * Sets the character to use in place of the actual text when
6997 * gtk_entry_set_visibility() has been called to set text visibility
6998 * to %FALSE. i.e. this is the character used in "password mode" to
6999 * show the user how many characters have been typed. By default, GTK+
7000 * picks the best invisible char available in the current font. If you
7001 * set the invisible char to 0, then the user will get no feedback
7002 * at all; there will be no text on the screen as they type.
7005 gtk_entry_set_invisible_char (GtkEntry *entry,
7008 GtkEntryPrivate *priv;
7010 g_return_if_fail (GTK_IS_ENTRY (entry));
7014 if (!priv->invisible_char_set)
7016 priv->invisible_char_set = TRUE;
7017 g_object_notify (G_OBJECT (entry), "invisible-char-set");
7020 if (ch == priv->invisible_char)
7023 priv->invisible_char = ch;
7024 g_object_notify (G_OBJECT (entry), "invisible-char");
7025 gtk_entry_recompute (entry);
7029 * gtk_entry_get_invisible_char:
7030 * @entry: a #GtkEntry
7032 * Retrieves the character displayed in place of the real characters
7033 * for entries with visibility set to false. See gtk_entry_set_invisible_char().
7035 * Return value: the current invisible char, or 0, if the entry does not
7036 * show invisible text at all.
7039 gtk_entry_get_invisible_char (GtkEntry *entry)
7041 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
7043 return entry->priv->invisible_char;
7047 * gtk_entry_unset_invisible_char:
7048 * @entry: a #GtkEntry
7050 * Unsets the invisible char previously set with
7051 * gtk_entry_set_invisible_char(). So that the
7052 * default invisible char is used again.
7057 gtk_entry_unset_invisible_char (GtkEntry *entry)
7059 GtkEntryPrivate *priv;
7062 g_return_if_fail (GTK_IS_ENTRY (entry));
7066 if (!priv->invisible_char_set)
7069 priv->invisible_char_set = FALSE;
7070 ch = find_invisible_char (GTK_WIDGET (entry));
7072 if (priv->invisible_char != ch)
7074 priv->invisible_char = ch;
7075 g_object_notify (G_OBJECT (entry), "invisible-char");
7078 g_object_notify (G_OBJECT (entry), "invisible-char-set");
7079 gtk_entry_recompute (entry);
7083 * gtk_entry_set_overwrite_mode:
7084 * @entry: a #GtkEntry
7085 * @overwrite: new value
7087 * Sets whether the text is overwritten when typing in the #GtkEntry.
7092 gtk_entry_set_overwrite_mode (GtkEntry *entry,
7095 GtkEntryPrivate *priv = entry->priv;
7097 g_return_if_fail (GTK_IS_ENTRY (entry));
7099 if (priv->overwrite_mode == overwrite)
7102 gtk_entry_toggle_overwrite (entry);
7104 g_object_notify (G_OBJECT (entry), "overwrite-mode");
7108 * gtk_entry_get_overwrite_mode:
7109 * @entry: a #GtkEntry
7111 * Gets the value set by gtk_entry_set_overwrite_mode().
7113 * Return value: whether the text is overwritten when typing.
7118 gtk_entry_get_overwrite_mode (GtkEntry *entry)
7120 g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
7122 return entry->priv->overwrite_mode;
7126 * gtk_entry_get_text:
7127 * @entry: a #GtkEntry
7129 * Retrieves the contents of the entry widget.
7130 * See also gtk_editable_get_chars().
7132 * This is equivalent to:
7134 * <informalexample><programlisting>
7135 * gtk_entry_buffer_get_text (gtk_entry_get_buffer (entry));
7136 * </programlisting></informalexample>
7138 * Return value: a pointer to the contents of the widget as a
7139 * string. This string points to internally allocated
7140 * storage in the widget and must not be freed, modified or
7144 gtk_entry_get_text (GtkEntry *entry)
7146 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
7148 return gtk_entry_buffer_get_text (get_buffer (entry));
7152 * gtk_entry_set_max_length:
7153 * @entry: a #GtkEntry
7154 * @max: the maximum length of the entry, or 0 for no maximum.
7155 * (other than the maximum length of entries.) The value passed in will
7156 * be clamped to the range 0-65536.
7158 * Sets the maximum allowed length of the contents of the widget. If
7159 * the current contents are longer than the given length, then they
7160 * will be truncated to fit.
7162 * This is equivalent to:
7164 * <informalexample><programlisting>
7165 * gtk_entry_buffer_set_max_length (gtk_entry_get_buffer (entry), max);
7166 * </programlisting></informalexample>
7169 gtk_entry_set_max_length (GtkEntry *entry,
7172 g_return_if_fail (GTK_IS_ENTRY (entry));
7173 gtk_entry_buffer_set_max_length (get_buffer (entry), max);
7177 * gtk_entry_get_max_length:
7178 * @entry: a #GtkEntry
7180 * Retrieves the maximum allowed length of the text in
7181 * @entry. See gtk_entry_set_max_length().
7183 * This is equivalent to:
7185 * <informalexample><programlisting>
7186 * gtk_entry_buffer_get_max_length (gtk_entry_get_buffer (entry));
7187 * </programlisting></informalexample>
7189 * Return value: the maximum allowed number of characters
7190 * in #GtkEntry, or 0 if there is no maximum.
7193 gtk_entry_get_max_length (GtkEntry *entry)
7195 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
7197 return gtk_entry_buffer_get_max_length (get_buffer (entry));
7201 * gtk_entry_get_text_length:
7202 * @entry: a #GtkEntry
7204 * Retrieves the current length of the text in
7207 * This is equivalent to:
7209 * <informalexample><programlisting>
7210 * gtk_entry_buffer_get_length (gtk_entry_get_buffer (entry));
7211 * </programlisting></informalexample>
7213 * Return value: the current number of characters
7214 * in #GtkEntry, or 0 if there are none.
7219 gtk_entry_get_text_length (GtkEntry *entry)
7221 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
7223 return gtk_entry_buffer_get_length (get_buffer (entry));
7227 * gtk_entry_set_activates_default:
7228 * @entry: a #GtkEntry
7229 * @setting: %TRUE to activate window's default widget on Enter keypress
7231 * If @setting is %TRUE, pressing Enter in the @entry will activate the default
7232 * widget for the window containing the entry. This usually means that
7233 * the dialog box containing the entry will be closed, since the default
7234 * widget is usually one of the dialog buttons.
7236 * (For experts: if @setting is %TRUE, the entry calls
7237 * gtk_window_activate_default() on the window containing the entry, in
7238 * the default handler for the #GtkEntry::activate signal.)
7241 gtk_entry_set_activates_default (GtkEntry *entry,
7244 GtkEntryPrivate *priv;
7246 g_return_if_fail (GTK_IS_ENTRY (entry));
7250 setting = setting != FALSE;
7252 if (setting != priv->activates_default)
7254 priv->activates_default = setting;
7255 g_object_notify (G_OBJECT (entry), "activates-default");
7260 * gtk_entry_get_activates_default:
7261 * @entry: a #GtkEntry
7263 * Retrieves the value set by gtk_entry_set_activates_default().
7265 * Return value: %TRUE if the entry will activate the default widget
7268 gtk_entry_get_activates_default (GtkEntry *entry)
7270 g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
7272 return entry->priv->activates_default;
7276 * gtk_entry_set_width_chars:
7277 * @entry: a #GtkEntry
7278 * @n_chars: width in chars
7280 * Changes the size request of the entry to be about the right size
7281 * for @n_chars characters. Note that it changes the size
7282 * <emphasis>request</emphasis>, the size can still be affected by
7283 * how you pack the widget into containers. If @n_chars is -1, the
7284 * size reverts to the default entry size.
7287 gtk_entry_set_width_chars (GtkEntry *entry,
7290 GtkEntryPrivate *priv;
7292 g_return_if_fail (GTK_IS_ENTRY (entry));
7296 if (priv->width_chars != n_chars)
7298 priv->width_chars = n_chars;
7299 g_object_notify (G_OBJECT (entry), "width-chars");
7300 gtk_widget_queue_resize (GTK_WIDGET (entry));
7305 * gtk_entry_get_width_chars:
7306 * @entry: a #GtkEntry
7308 * Gets the value set by gtk_entry_set_width_chars().
7310 * Return value: number of chars to request space for, or negative if unset
7313 gtk_entry_get_width_chars (GtkEntry *entry)
7315 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
7317 return entry->priv->width_chars;
7321 * gtk_entry_set_has_frame:
7322 * @entry: a #GtkEntry
7323 * @setting: new value
7325 * Sets whether the entry has a beveled frame around it.
7328 gtk_entry_set_has_frame (GtkEntry *entry,
7331 GtkEntryPrivate *priv;
7333 g_return_if_fail (GTK_IS_ENTRY (entry));
7337 setting = (setting != FALSE);
7339 if (priv->has_frame == setting)
7342 gtk_widget_queue_resize (GTK_WIDGET (entry));
7343 priv->has_frame = setting;
7344 g_object_notify (G_OBJECT (entry), "has-frame");
7348 * gtk_entry_get_has_frame:
7349 * @entry: a #GtkEntry
7351 * Gets the value set by gtk_entry_set_has_frame().
7353 * Return value: whether the entry has a beveled frame
7356 gtk_entry_get_has_frame (GtkEntry *entry)
7358 g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
7360 return entry->priv->has_frame;
7364 * gtk_entry_set_inner_border:
7365 * @entry: a #GtkEntry
7366 * @border: (allow-none): a #GtkBorder, or %NULL
7368 * Sets %entry's inner-border property to %border, or clears it if %NULL
7369 * is passed. The inner-border is the area around the entry's text, but
7372 * If set, this property overrides the inner-border style property.
7373 * Overriding the style-provided border is useful when you want to do
7374 * in-place editing of some text in a canvas or list widget, where
7375 * pixel-exact positioning of the entry is important.
7379 * Deprecated: 3.4: Use the standard border and padding CSS properties (through
7380 * objects like #GtkStyleContext and #GtkCssProvider); the value set with
7381 * this function is ignored by #GtkEntry.
7384 gtk_entry_set_inner_border (GtkEntry *entry,
7385 const GtkBorder *border)
7387 g_return_if_fail (GTK_IS_ENTRY (entry));
7389 gtk_entry_do_set_inner_border (entry, border);
7393 * gtk_entry_get_inner_border:
7394 * @entry: a #GtkEntry
7396 * This function returns the entry's #GtkEntry:inner-border property. See
7397 * gtk_entry_set_inner_border() for more information.
7399 * Return value: (transfer none): the entry's #GtkBorder, or %NULL if none was set.
7403 * Deprecated: 3.4: Use the standard border and padding CSS properties (through
7404 * objects like #GtkStyleContext and #GtkCssProvider); the value returned by
7405 * this function is ignored by #GtkEntry.
7408 gtk_entry_get_inner_border (GtkEntry *entry)
7410 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
7412 return gtk_entry_do_get_inner_border (entry);
7416 * gtk_entry_get_layout:
7417 * @entry: a #GtkEntry
7419 * Gets the #PangoLayout used to display the entry.
7420 * The layout is useful to e.g. convert text positions to
7421 * pixel positions, in combination with gtk_entry_get_layout_offsets().
7422 * The returned layout is owned by the entry and must not be
7423 * modified or freed by the caller.
7425 * Keep in mind that the layout text may contain a preedit string, so
7426 * gtk_entry_layout_index_to_text_index() and
7427 * gtk_entry_text_index_to_layout_index() are needed to convert byte
7428 * indices in the layout to byte indices in the entry contents.
7430 * Return value: (transfer none): the #PangoLayout for this entry
7433 gtk_entry_get_layout (GtkEntry *entry)
7435 PangoLayout *layout;
7437 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
7439 layout = gtk_entry_ensure_layout (entry, TRUE);
7446 * gtk_entry_layout_index_to_text_index:
7447 * @entry: a #GtkEntry
7448 * @layout_index: byte index into the entry layout text
7450 * Converts from a position in the entry contents (returned
7451 * by gtk_entry_get_text()) to a position in the
7452 * entry's #PangoLayout (returned by gtk_entry_get_layout(),
7453 * with text retrieved via pango_layout_get_text()).
7455 * Return value: byte index into the entry contents
7458 gtk_entry_layout_index_to_text_index (GtkEntry *entry,
7461 GtkEntryPrivate *priv;
7462 PangoLayout *layout;
7466 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
7470 layout = gtk_entry_ensure_layout (entry, TRUE);
7471 text = pango_layout_get_text (layout);
7472 cursor_index = g_utf8_offset_to_pointer (text, priv->current_pos) - text;
7474 if (layout_index >= cursor_index && priv->preedit_length)
7476 if (layout_index >= cursor_index + priv->preedit_length)
7477 layout_index -= priv->preedit_length;
7479 layout_index = cursor_index;
7482 return layout_index;
7486 * gtk_entry_text_index_to_layout_index:
7487 * @entry: a #GtkEntry
7488 * @text_index: byte index into the entry contents
7490 * Converts from a position in the entry's #PangoLayout (returned by
7491 * gtk_entry_get_layout()) to a position in the entry contents
7492 * (returned by gtk_entry_get_text()).
7494 * Return value: byte index into the entry layout text
7497 gtk_entry_text_index_to_layout_index (GtkEntry *entry,
7500 GtkEntryPrivate *priv;
7501 PangoLayout *layout;
7505 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
7509 layout = gtk_entry_ensure_layout (entry, TRUE);
7510 text = pango_layout_get_text (layout);
7511 cursor_index = g_utf8_offset_to_pointer (text, priv->current_pos) - text;
7513 if (text_index > cursor_index)
7514 text_index += priv->preedit_length;
7520 * gtk_entry_get_layout_offsets:
7521 * @entry: a #GtkEntry
7522 * @x: (out) (allow-none): location to store X offset of layout, or %NULL
7523 * @y: (out) (allow-none): location to store Y offset of layout, or %NULL
7526 * Obtains the position of the #PangoLayout used to render text
7527 * in the entry, in widget coordinates. Useful if you want to line
7528 * up the text in an entry with some other text, e.g. when using the
7529 * entry to implement editable cells in a sheet widget.
7531 * Also useful to convert mouse events into coordinates inside the
7532 * #PangoLayout, e.g. to take some action if some part of the entry text
7535 * Note that as the user scrolls around in the entry the offsets will
7536 * change; you'll need to connect to the "notify::scroll-offset"
7537 * signal to track this. Remember when using the #PangoLayout
7538 * functions you need to convert to and from pixels using
7539 * PANGO_PIXELS() or #PANGO_SCALE.
7541 * Keep in mind that the layout text may contain a preedit string, so
7542 * gtk_entry_layout_index_to_text_index() and
7543 * gtk_entry_text_index_to_layout_index() are needed to convert byte
7544 * indices in the layout to byte indices in the entry contents.
7547 gtk_entry_get_layout_offsets (GtkEntry *entry,
7551 gint text_area_x, text_area_y;
7553 g_return_if_fail (GTK_IS_ENTRY (entry));
7555 /* this gets coords relative to text area */
7556 get_layout_position (entry, x, y);
7558 /* convert to widget coords */
7559 gtk_entry_get_text_area_size (entry, &text_area_x, &text_area_y, NULL, NULL);
7570 * gtk_entry_set_alignment:
7571 * @entry: a #GtkEntry
7572 * @xalign: The horizontal alignment, from 0 (left) to 1 (right).
7573 * Reversed for RTL layouts
7575 * Sets the alignment for the contents of the entry. This controls
7576 * the horizontal positioning of the contents when the displayed
7577 * text is shorter than the width of the entry.
7582 gtk_entry_set_alignment (GtkEntry *entry, gfloat xalign)
7584 GtkEntryPrivate *priv;
7586 g_return_if_fail (GTK_IS_ENTRY (entry));
7592 else if (xalign > 1.0)
7595 if (xalign != priv->xalign)
7597 priv->xalign = xalign;
7599 gtk_entry_recompute (entry);
7601 g_object_notify (G_OBJECT (entry), "xalign");
7606 * gtk_entry_get_alignment:
7607 * @entry: a #GtkEntry
7609 * Gets the value set by gtk_entry_set_alignment().
7611 * Return value: the alignment
7616 gtk_entry_get_alignment (GtkEntry *entry)
7618 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0.0);
7620 return entry->priv->xalign;
7624 * gtk_entry_set_icon_from_pixbuf:
7625 * @entry: a #GtkEntry
7626 * @icon_pos: Icon position
7627 * @pixbuf: (allow-none): A #GdkPixbuf, or %NULL
7629 * Sets the icon shown in the specified position using a pixbuf.
7631 * If @pixbuf is %NULL, no icon will be shown in the specified position.
7636 gtk_entry_set_icon_from_pixbuf (GtkEntry *entry,
7637 GtkEntryIconPosition icon_pos,
7640 GtkEntryPrivate *priv;
7641 EntryIconInfo *icon_info;
7643 g_return_if_fail (GTK_IS_ENTRY (entry));
7644 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
7648 if ((icon_info = priv->icons[icon_pos]) == NULL)
7649 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
7651 g_object_freeze_notify (G_OBJECT (entry));
7654 g_object_ref (pixbuf);
7656 gtk_entry_clear (entry, icon_pos);
7660 _gtk_icon_helper_set_pixbuf (icon_info->icon_helper, pixbuf);
7661 _gtk_icon_helper_set_icon_size (icon_info->icon_helper,
7662 GTK_ICON_SIZE_MENU);
7664 if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
7666 g_object_notify (G_OBJECT (entry), "primary-icon-pixbuf");
7667 g_object_notify (G_OBJECT (entry), "primary-icon-storage-type");
7671 g_object_notify (G_OBJECT (entry), "secondary-icon-pixbuf");
7672 g_object_notify (G_OBJECT (entry), "secondary-icon-storage-type");
7675 if (gtk_widget_get_mapped (GTK_WIDGET (entry)))
7676 gdk_window_show_unraised (icon_info->window);
7678 g_object_unref (pixbuf);
7681 if (gtk_widget_get_visible (GTK_WIDGET (entry)))
7682 gtk_widget_queue_resize (GTK_WIDGET (entry));
7684 g_object_thaw_notify (G_OBJECT (entry));
7688 * gtk_entry_set_icon_from_stock:
7689 * @entry: A #GtkEntry
7690 * @icon_pos: Icon position
7691 * @stock_id: (allow-none): The name of the stock item, or %NULL
7693 * Sets the icon shown in the entry at the specified position from
7696 * If @stock_id is %NULL, no icon will be shown in the specified position.
7701 gtk_entry_set_icon_from_stock (GtkEntry *entry,
7702 GtkEntryIconPosition icon_pos,
7703 const gchar *stock_id)
7705 GtkEntryPrivate *priv;
7706 EntryIconInfo *icon_info;
7709 g_return_if_fail (GTK_IS_ENTRY (entry));
7710 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
7714 if ((icon_info = priv->icons[icon_pos]) == NULL)
7715 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
7717 g_object_freeze_notify (G_OBJECT (entry));
7719 /* need to dup before clearing */
7720 new_id = g_strdup (stock_id);
7722 gtk_entry_clear (entry, icon_pos);
7726 _gtk_icon_helper_set_stock_id (icon_info->icon_helper, new_id, GTK_ICON_SIZE_MENU);
7728 if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
7730 g_object_notify (G_OBJECT (entry), "primary-icon-stock");
7731 g_object_notify (G_OBJECT (entry), "primary-icon-storage-type");
7735 g_object_notify (G_OBJECT (entry), "secondary-icon-stock");
7736 g_object_notify (G_OBJECT (entry), "secondary-icon-storage-type");
7739 if (gtk_widget_get_mapped (GTK_WIDGET (entry)))
7740 gdk_window_show_unraised (icon_info->window);
7745 if (gtk_widget_get_visible (GTK_WIDGET (entry)))
7746 gtk_widget_queue_resize (GTK_WIDGET (entry));
7748 g_object_thaw_notify (G_OBJECT (entry));
7752 * gtk_entry_set_icon_from_icon_name:
7753 * @entry: A #GtkEntry
7754 * @icon_pos: The position at which to set the icon
7755 * @icon_name: (allow-none): An icon name, or %NULL
7757 * Sets the icon shown in the entry at the specified position
7758 * from the current icon theme.
7760 * If the icon name isn't known, a "broken image" icon will be displayed
7763 * If @icon_name is %NULL, no icon will be shown in the specified position.
7768 gtk_entry_set_icon_from_icon_name (GtkEntry *entry,
7769 GtkEntryIconPosition icon_pos,
7770 const gchar *icon_name)
7772 GtkEntryPrivate *priv;
7773 EntryIconInfo *icon_info;
7776 g_return_if_fail (GTK_IS_ENTRY (entry));
7777 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
7781 if ((icon_info = priv->icons[icon_pos]) == NULL)
7782 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
7784 g_object_freeze_notify (G_OBJECT (entry));
7786 /* need to dup before clearing */
7787 new_name = g_strdup (icon_name);
7789 gtk_entry_clear (entry, icon_pos);
7791 if (new_name != NULL)
7793 _gtk_icon_helper_set_icon_name (icon_info->icon_helper, new_name, GTK_ICON_SIZE_MENU);
7795 if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
7797 g_object_notify (G_OBJECT (entry), "primary-icon-name");
7798 g_object_notify (G_OBJECT (entry), "primary-icon-storage-type");
7802 g_object_notify (G_OBJECT (entry), "secondary-icon-name");
7803 g_object_notify (G_OBJECT (entry), "secondary-icon-storage-type");
7806 if (gtk_widget_get_mapped (GTK_WIDGET (entry)))
7807 gdk_window_show_unraised (icon_info->window);
7812 if (gtk_widget_get_visible (GTK_WIDGET (entry)))
7813 gtk_widget_queue_resize (GTK_WIDGET (entry));
7815 g_object_thaw_notify (G_OBJECT (entry));
7819 * gtk_entry_set_icon_from_gicon:
7820 * @entry: A #GtkEntry
7821 * @icon_pos: The position at which to set the icon
7822 * @icon: (allow-none): The icon to set, or %NULL
7824 * Sets the icon shown in the entry at the specified position
7825 * from the current icon theme.
7826 * If the icon isn't known, a "broken image" icon will be displayed
7829 * If @icon is %NULL, no icon will be shown in the specified position.
7834 gtk_entry_set_icon_from_gicon (GtkEntry *entry,
7835 GtkEntryIconPosition icon_pos,
7838 GtkEntryPrivate *priv;
7839 EntryIconInfo *icon_info;
7841 g_return_if_fail (GTK_IS_ENTRY (entry));
7842 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
7846 if ((icon_info = priv->icons[icon_pos]) == NULL)
7847 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
7849 g_object_freeze_notify (G_OBJECT (entry));
7851 /* need to ref before clearing */
7853 g_object_ref (icon);
7855 gtk_entry_clear (entry, icon_pos);
7859 _gtk_icon_helper_set_gicon (icon_info->icon_helper, icon, GTK_ICON_SIZE_MENU);
7861 if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
7863 g_object_notify (G_OBJECT (entry), "primary-icon-gicon");
7864 g_object_notify (G_OBJECT (entry), "primary-icon-storage-type");
7868 g_object_notify (G_OBJECT (entry), "secondary-icon-gicon");
7869 g_object_notify (G_OBJECT (entry), "secondary-icon-storage-type");
7872 if (gtk_widget_get_mapped (GTK_WIDGET (entry)))
7873 gdk_window_show_unraised (icon_info->window);
7875 g_object_unref (icon);
7878 if (gtk_widget_get_visible (GTK_WIDGET (entry)))
7879 gtk_widget_queue_resize (GTK_WIDGET (entry));
7881 g_object_thaw_notify (G_OBJECT (entry));
7885 * gtk_entry_set_icon_activatable:
7886 * @entry: A #GtkEntry
7887 * @icon_pos: Icon position
7888 * @activatable: %TRUE if the icon should be activatable
7890 * Sets whether the icon is activatable.
7895 gtk_entry_set_icon_activatable (GtkEntry *entry,
7896 GtkEntryIconPosition icon_pos,
7897 gboolean activatable)
7899 GtkEntryPrivate *priv;
7900 EntryIconInfo *icon_info;
7902 g_return_if_fail (GTK_IS_ENTRY (entry));
7903 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
7907 if ((icon_info = priv->icons[icon_pos]) == NULL)
7908 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
7910 activatable = activatable != FALSE;
7912 if (icon_info->nonactivatable != !activatable)
7914 icon_info->nonactivatable = !activatable;
7916 if (gtk_widget_get_realized (GTK_WIDGET (entry)))
7917 update_cursors (GTK_WIDGET (entry));
7919 g_object_notify (G_OBJECT (entry),
7920 icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-activatable" : "secondary-icon-activatable");
7925 * gtk_entry_get_icon_activatable:
7926 * @entry: a #GtkEntry
7927 * @icon_pos: Icon position
7929 * Returns whether the icon is activatable.
7931 * Returns: %TRUE if the icon is activatable.
7936 gtk_entry_get_icon_activatable (GtkEntry *entry,
7937 GtkEntryIconPosition icon_pos)
7939 GtkEntryPrivate *priv;
7940 EntryIconInfo *icon_info;
7942 g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
7943 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), FALSE);
7946 icon_info = priv->icons[icon_pos];
7948 return (!icon_info || !icon_info->nonactivatable);
7952 * gtk_entry_get_icon_pixbuf:
7953 * @entry: A #GtkEntry
7954 * @icon_pos: Icon position
7956 * Retrieves the image used for the icon.
7958 * Unlike the other methods of setting and getting icon data, this
7959 * method will work regardless of whether the icon was set using a
7960 * #GdkPixbuf, a #GIcon, a stock item, or an icon name.
7962 * Returns: (transfer none): A #GdkPixbuf, or %NULL if no icon is
7963 * set for this position.
7968 gtk_entry_get_icon_pixbuf (GtkEntry *entry,
7969 GtkEntryIconPosition icon_pos)
7971 GtkEntryPrivate *priv;
7972 EntryIconInfo *icon_info;
7975 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
7976 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), NULL);
7980 icon_info = priv->icons[icon_pos];
7985 /* HACK: unfortunately this is transfer none, so we need to return
7986 * the icon helper's cache ref directly.
7988 pixbuf = gtk_entry_ensure_pixbuf (entry, icon_pos);
7990 g_object_unref (pixbuf);
7996 * gtk_entry_get_icon_gicon:
7997 * @entry: A #GtkEntry
7998 * @icon_pos: Icon position
8000 * Retrieves the #GIcon used for the icon, or %NULL if there is
8001 * no icon or if the icon was set by some other method (e.g., by
8002 * stock, pixbuf, or icon name).
8004 * Returns: (transfer none): A #GIcon, or %NULL if no icon is set
8005 * or if the icon is not a #GIcon
8010 gtk_entry_get_icon_gicon (GtkEntry *entry,
8011 GtkEntryIconPosition icon_pos)
8013 GtkEntryPrivate *priv;
8014 EntryIconInfo *icon_info;
8016 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
8017 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), NULL);
8020 icon_info = priv->icons[icon_pos];
8025 return _gtk_icon_helper_peek_gicon (icon_info->icon_helper);
8029 * gtk_entry_get_icon_stock:
8030 * @entry: A #GtkEntry
8031 * @icon_pos: Icon position
8033 * Retrieves the stock id used for the icon, or %NULL if there is
8034 * no icon or if the icon was set by some other method (e.g., by
8035 * pixbuf, icon name or gicon).
8037 * Returns: A stock id, or %NULL if no icon is set or if the icon
8038 * wasn't set from a stock id
8043 gtk_entry_get_icon_stock (GtkEntry *entry,
8044 GtkEntryIconPosition icon_pos)
8046 GtkEntryPrivate *priv;
8047 EntryIconInfo *icon_info;
8049 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
8050 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), NULL);
8053 icon_info = priv->icons[icon_pos];
8058 return _gtk_icon_helper_get_stock_id (icon_info->icon_helper);
8062 * gtk_entry_get_icon_name:
8063 * @entry: A #GtkEntry
8064 * @icon_pos: Icon position
8066 * Retrieves the icon name used for the icon, or %NULL if there is
8067 * no icon or if the icon was set by some other method (e.g., by
8068 * pixbuf, stock or gicon).
8070 * Returns: An icon name, or %NULL if no icon is set or if the icon
8071 * wasn't set from an icon name
8076 gtk_entry_get_icon_name (GtkEntry *entry,
8077 GtkEntryIconPosition icon_pos)
8079 GtkEntryPrivate *priv;
8080 EntryIconInfo *icon_info;
8082 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
8083 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), NULL);
8086 icon_info = priv->icons[icon_pos];
8091 return _gtk_icon_helper_get_icon_name (icon_info->icon_helper);
8095 * gtk_entry_set_icon_sensitive:
8096 * @entry: A #GtkEntry
8097 * @icon_pos: Icon position
8098 * @sensitive: Specifies whether the icon should appear
8099 * sensitive or insensitive
8101 * Sets the sensitivity for the specified icon.
8106 gtk_entry_set_icon_sensitive (GtkEntry *entry,
8107 GtkEntryIconPosition icon_pos,
8110 GtkEntryPrivate *priv;
8111 EntryIconInfo *icon_info;
8113 g_return_if_fail (GTK_IS_ENTRY (entry));
8114 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
8118 if ((icon_info = priv->icons[icon_pos]) == NULL)
8119 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
8121 if (icon_info->insensitive != !sensitive)
8123 icon_info->insensitive = !sensitive;
8125 icon_info->pressed = FALSE;
8126 icon_info->prelight = FALSE;
8128 if (gtk_widget_get_realized (GTK_WIDGET (entry)))
8129 update_cursors (GTK_WIDGET (entry));
8131 gtk_widget_queue_draw (GTK_WIDGET (entry));
8133 g_object_notify (G_OBJECT (entry),
8134 icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-sensitive" : "secondary-icon-sensitive");
8139 * gtk_entry_get_icon_sensitive:
8140 * @entry: a #GtkEntry
8141 * @icon_pos: Icon position
8143 * Returns whether the icon appears sensitive or insensitive.
8145 * Returns: %TRUE if the icon is sensitive.
8150 gtk_entry_get_icon_sensitive (GtkEntry *entry,
8151 GtkEntryIconPosition icon_pos)
8153 GtkEntryPrivate *priv;
8154 EntryIconInfo *icon_info;
8156 g_return_val_if_fail (GTK_IS_ENTRY (entry), TRUE);
8157 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), TRUE);
8161 icon_info = priv->icons[icon_pos];
8163 return (!icon_info || !icon_info->insensitive);
8168 * gtk_entry_get_icon_storage_type:
8169 * @entry: a #GtkEntry
8170 * @icon_pos: Icon position
8172 * Gets the type of representation being used by the icon
8173 * to store image data. If the icon has no image data,
8174 * the return value will be %GTK_IMAGE_EMPTY.
8176 * Return value: image representation being used
8181 gtk_entry_get_icon_storage_type (GtkEntry *entry,
8182 GtkEntryIconPosition icon_pos)
8184 GtkEntryPrivate *priv;
8185 EntryIconInfo *icon_info;
8187 g_return_val_if_fail (GTK_IS_ENTRY (entry), GTK_IMAGE_EMPTY);
8188 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), GTK_IMAGE_EMPTY);
8192 icon_info = priv->icons[icon_pos];
8195 return GTK_IMAGE_EMPTY;
8197 return _gtk_icon_helper_get_storage_type (icon_info->icon_helper);
8201 * gtk_entry_get_icon_at_pos:
8202 * @entry: a #GtkEntry
8203 * @x: the x coordinate of the position to find
8204 * @y: the y coordinate of the position to find
8206 * Finds the icon at the given position and return its index. The
8207 * position's coordinates are relative to the @entry's top left corner.
8208 * If @x, @y doesn't lie inside an icon, -1 is returned.
8209 * This function is intended for use in a #GtkWidget::query-tooltip
8212 * Returns: the index of the icon at the given position, or -1
8217 gtk_entry_get_icon_at_pos (GtkEntry *entry,
8221 GtkAllocation primary;
8222 GtkAllocation secondary;
8223 gint frame_x, frame_y;
8225 g_return_val_if_fail (GTK_IS_ENTRY (entry), -1);
8227 get_frame_size (entry, FALSE, &frame_x, &frame_y, NULL, NULL);
8231 get_icon_allocations (entry, &primary, &secondary);
8233 if (primary.x <= x && x < primary.x + primary.width &&
8234 primary.y <= y && y < primary.y + primary.height)
8235 return GTK_ENTRY_ICON_PRIMARY;
8237 if (secondary.x <= x && x < secondary.x + secondary.width &&
8238 secondary.y <= y && y < secondary.y + secondary.height)
8239 return GTK_ENTRY_ICON_SECONDARY;
8245 * gtk_entry_set_icon_drag_source:
8246 * @entry: a #GtkEntry
8247 * @icon_pos: icon position
8248 * @target_list: the targets (data formats) in which the data can be provided
8249 * @actions: a bitmask of the allowed drag actions
8251 * Sets up the icon at the given position so that GTK+ will start a drag
8252 * operation when the user clicks and drags the icon.
8254 * To handle the drag operation, you need to connect to the usual
8255 * #GtkWidget::drag-data-get (or possibly #GtkWidget::drag-data-delete)
8256 * signal, and use gtk_entry_get_current_icon_drag_source() in
8257 * your signal handler to find out if the drag was started from
8260 * By default, GTK+ uses the icon as the drag icon. You can use the
8261 * #GtkWidget::drag-begin signal to set a different icon. Note that you
8262 * have to use g_signal_connect_after() to ensure that your signal handler
8263 * gets executed after the default handler.
8268 gtk_entry_set_icon_drag_source (GtkEntry *entry,
8269 GtkEntryIconPosition icon_pos,
8270 GtkTargetList *target_list,
8271 GdkDragAction actions)
8273 GtkEntryPrivate *priv;
8274 EntryIconInfo *icon_info;
8276 g_return_if_fail (GTK_IS_ENTRY (entry));
8277 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
8281 if ((icon_info = priv->icons[icon_pos]) == NULL)
8282 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
8284 if (icon_info->target_list)
8285 gtk_target_list_unref (icon_info->target_list);
8286 icon_info->target_list = target_list;
8287 if (icon_info->target_list)
8288 gtk_target_list_ref (icon_info->target_list);
8290 icon_info->actions = actions;
8294 * gtk_entry_get_current_icon_drag_source:
8295 * @entry: a #GtkIconEntry
8297 * Returns the index of the icon which is the source of the current
8298 * DND operation, or -1.
8300 * This function is meant to be used in a #GtkWidget::drag-data-get
8303 * Returns: index of the icon which is the source of the current
8304 * DND operation, or -1.
8309 gtk_entry_get_current_icon_drag_source (GtkEntry *entry)
8311 GtkEntryPrivate *priv;
8312 EntryIconInfo *icon_info = NULL;
8315 g_return_val_if_fail (GTK_IS_ENTRY (entry), -1);
8319 for (i = 0; i < MAX_ICONS; i++)
8321 if ((icon_info = priv->icons[i]))
8323 if (icon_info->in_drag)
8332 * gtk_entry_get_icon_area:
8333 * @entry: A #GtkEntry
8334 * @icon_pos: Icon position
8335 * @icon_area: (out): Return location for the icon's area
8337 * Gets the area where entry's icon at @icon_pos is drawn.
8338 * This function is useful when drawing something to the
8339 * entry in a draw callback.
8341 * If the entry is not realized or has no icon at the given position,
8342 * @icon_area is filled with zeros.
8344 * See also gtk_entry_get_text_area()
8349 gtk_entry_get_icon_area (GtkEntry *entry,
8350 GtkEntryIconPosition icon_pos,
8351 GdkRectangle *icon_area)
8353 GtkEntryPrivate *priv;
8354 EntryIconInfo *icon_info;
8356 g_return_if_fail (GTK_IS_ENTRY (entry));
8357 g_return_if_fail (icon_area != NULL);
8361 icon_info = priv->icons[icon_pos];
8365 GtkAllocation primary;
8366 GtkAllocation secondary;
8368 get_icon_allocations (entry, &primary, &secondary);
8370 if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
8371 *icon_area = primary;
8373 *icon_area = secondary;
8379 icon_area->width = 0;
8380 icon_area->height = 0;
8385 ensure_has_tooltip (GtkEntry *entry)
8387 GtkEntryPrivate *priv;
8388 EntryIconInfo *icon_info;
8390 gboolean has_tooltip = FALSE;
8394 for (i = 0; i < MAX_ICONS; i++)
8396 if ((icon_info = priv->icons[i]) != NULL)
8398 if (icon_info->tooltip != NULL)
8406 gtk_widget_set_has_tooltip (GTK_WIDGET (entry), has_tooltip);
8410 * gtk_entry_get_icon_tooltip_text:
8411 * @entry: a #GtkEntry
8412 * @icon_pos: the icon position
8414 * Gets the contents of the tooltip on the icon at the specified
8415 * position in @entry.
8417 * Returns: the tooltip text, or %NULL. Free the returned string
8418 * with g_free() when done.
8423 gtk_entry_get_icon_tooltip_text (GtkEntry *entry,
8424 GtkEntryIconPosition icon_pos)
8426 GtkEntryPrivate *priv;
8427 EntryIconInfo *icon_info;
8430 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
8431 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), NULL);
8435 icon_info = priv->icons[icon_pos];
8440 if (icon_info->tooltip &&
8441 !pango_parse_markup (icon_info->tooltip, -1, 0, NULL, &text, NULL, NULL))
8442 g_assert (NULL == text); /* text should still be NULL in case of markup errors */
8448 * gtk_entry_set_icon_tooltip_text:
8449 * @entry: a #GtkEntry
8450 * @icon_pos: the icon position
8451 * @tooltip: (allow-none): the contents of the tooltip for the icon, or %NULL
8453 * Sets @tooltip as the contents of the tooltip for the icon
8454 * at the specified position.
8456 * Use %NULL for @tooltip to remove an existing tooltip.
8458 * See also gtk_widget_set_tooltip_text() and
8459 * gtk_entry_set_icon_tooltip_markup().
8464 gtk_entry_set_icon_tooltip_text (GtkEntry *entry,
8465 GtkEntryIconPosition icon_pos,
8466 const gchar *tooltip)
8468 GtkEntryPrivate *priv;
8469 EntryIconInfo *icon_info;
8471 g_return_if_fail (GTK_IS_ENTRY (entry));
8472 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
8476 if ((icon_info = priv->icons[icon_pos]) == NULL)
8477 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
8479 if (icon_info->tooltip)
8480 g_free (icon_info->tooltip);
8482 /* Treat an empty string as a NULL string,
8483 * because an empty string would be useless for a tooltip:
8485 if (tooltip && tooltip[0] == '\0')
8488 icon_info->tooltip = tooltip ? g_markup_escape_text (tooltip, -1) : NULL;
8490 ensure_has_tooltip (entry);
8494 * gtk_entry_get_icon_tooltip_markup:
8495 * @entry: a #GtkEntry
8496 * @icon_pos: the icon position
8498 * Gets the contents of the tooltip on the icon at the specified
8499 * position in @entry.
8501 * Returns: the tooltip text, or %NULL. Free the returned string
8502 * with g_free() when done.
8507 gtk_entry_get_icon_tooltip_markup (GtkEntry *entry,
8508 GtkEntryIconPosition icon_pos)
8510 GtkEntryPrivate *priv;
8511 EntryIconInfo *icon_info;
8513 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
8514 g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), NULL);
8518 icon_info = priv->icons[icon_pos];
8523 return g_strdup (icon_info->tooltip);
8527 * gtk_entry_set_icon_tooltip_markup:
8528 * @entry: a #GtkEntry
8529 * @icon_pos: the icon position
8530 * @tooltip: (allow-none): the contents of the tooltip for the icon, or %NULL
8532 * Sets @tooltip as the contents of the tooltip for the icon at
8533 * the specified position. @tooltip is assumed to be marked up with
8534 * the <link linkend="PangoMarkupFormat">Pango text markup language</link>.
8536 * Use %NULL for @tooltip to remove an existing tooltip.
8538 * See also gtk_widget_set_tooltip_markup() and
8539 * gtk_entry_set_icon_tooltip_text().
8544 gtk_entry_set_icon_tooltip_markup (GtkEntry *entry,
8545 GtkEntryIconPosition icon_pos,
8546 const gchar *tooltip)
8548 GtkEntryPrivate *priv;
8549 EntryIconInfo *icon_info;
8551 g_return_if_fail (GTK_IS_ENTRY (entry));
8552 g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
8556 if ((icon_info = priv->icons[icon_pos]) == NULL)
8557 icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
8559 if (icon_info->tooltip)
8560 g_free (icon_info->tooltip);
8562 /* Treat an empty string as a NULL string,
8563 * because an empty string would be useless for a tooltip:
8565 if (tooltip && tooltip[0] == '\0')
8568 icon_info->tooltip = g_strdup (tooltip);
8570 ensure_has_tooltip (entry);
8574 gtk_entry_query_tooltip (GtkWidget *widget,
8577 gboolean keyboard_tip,
8578 GtkTooltip *tooltip)
8581 GtkEntryPrivate *priv;
8582 EntryIconInfo *icon_info;
8585 entry = GTK_ENTRY (widget);
8590 icon_pos = gtk_entry_get_icon_at_pos (entry, x, y);
8593 if ((icon_info = priv->icons[icon_pos]) != NULL)
8595 if (icon_info->tooltip)
8597 gtk_tooltip_set_markup (tooltip, icon_info->tooltip);
8606 return GTK_WIDGET_CLASS (gtk_entry_parent_class)->query_tooltip (widget,
8613 /* Quick hack of a popup menu
8616 activate_cb (GtkWidget *menuitem,
8619 const gchar *signal = g_object_get_data (G_OBJECT (menuitem), "gtk-signal");
8620 g_signal_emit_by_name (entry, signal);
8625 gtk_entry_mnemonic_activate (GtkWidget *widget,
8626 gboolean group_cycling)
8628 gtk_widget_grab_focus (widget);
8633 gtk_entry_grab_notify (GtkWidget *widget,
8634 gboolean was_grabbed)
8636 GtkEntryPrivate *priv;
8638 priv = GTK_ENTRY (widget)->priv;
8641 gtk_widget_device_is_shadowed (widget, priv->device))
8643 /* Unset button so we don't expect
8644 * a button release anymore
8647 priv->device = NULL;
8648 priv->in_drag = FALSE;
8653 append_action_signal (GtkEntry *entry,
8655 const gchar *stock_id,
8656 const gchar *signal,
8659 GtkWidget *menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL);
8661 g_object_set_data (G_OBJECT (menuitem), I_("gtk-signal"), (char *)signal);
8662 g_signal_connect (menuitem, "activate",
8663 G_CALLBACK (activate_cb), entry);
8665 gtk_widget_set_sensitive (menuitem, sensitive);
8667 gtk_widget_show (menuitem);
8668 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
8672 popup_menu_detach (GtkWidget *attach_widget,
8675 GtkEntry *entry_attach = GTK_ENTRY (attach_widget);
8676 GtkEntryPrivate *priv_attach = entry_attach->priv;
8678 priv_attach->popup_menu = NULL;
8682 popup_position_func (GtkMenu *menu,
8688 GtkEntry *entry = GTK_ENTRY (user_data);
8689 GtkEntryPrivate *priv = entry->priv;
8690 GtkWidget *widget = GTK_WIDGET (entry);
8692 GtkRequisition menu_req;
8693 GdkRectangle monitor;
8695 gint monitor_num, strong_x, height;
8697 g_return_if_fail (gtk_widget_get_realized (widget));
8699 gdk_window_get_origin (priv->text_area, x, y);
8701 screen = gtk_widget_get_screen (widget);
8702 monitor_num = gdk_screen_get_monitor_at_window (screen, priv->text_area);
8703 if (monitor_num < 0)
8705 gtk_menu_set_monitor (menu, monitor_num);
8707 gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor);
8708 gtk_widget_get_preferred_size (priv->popup_menu,
8710 height = gdk_window_get_height (priv->text_area);
8711 gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &strong_x, NULL);
8712 _gtk_entry_get_borders (entry, &borders);
8714 *x += borders.left + strong_x - priv->scroll_offset;
8715 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
8716 *x -= menu_req.width;
8718 if ((*y + height + menu_req.height) <= monitor.y + monitor.height)
8720 else if ((*y - menu_req.height) >= monitor.y)
8721 *y -= menu_req.height;
8722 else if (monitor.y + monitor.height - (*y + height) > *y)
8725 *y -= menu_req.height;
8731 unichar_chosen_func (const char *text,
8734 GtkEntry *entry = GTK_ENTRY (data);
8735 GtkEntryPrivate *priv = entry->priv;
8738 gtk_entry_enter_text (entry, text);
8750 popup_targets_received (GtkClipboard *clipboard,
8751 GtkSelectionData *data,
8754 PopupInfo *info = user_data;
8755 GtkEntry *entry = info->entry;
8756 GtkEntryPrivate *info_entry_priv = entry->priv;
8758 if (gtk_widget_get_realized (GTK_WIDGET (entry)))
8761 gboolean clipboard_contains_text;
8762 GtkWidget *menuitem;
8764 gboolean show_input_method_menu;
8765 gboolean show_unicode_menu;
8767 clipboard_contains_text = gtk_selection_data_targets_include_text (data);
8768 if (info_entry_priv->popup_menu)
8769 gtk_widget_destroy (info_entry_priv->popup_menu);
8771 info_entry_priv->popup_menu = gtk_menu_new ();
8773 gtk_menu_attach_to_widget (GTK_MENU (info_entry_priv->popup_menu),
8777 mode = gtk_entry_get_display_mode (entry);
8778 append_action_signal (entry, info_entry_priv->popup_menu, GTK_STOCK_CUT, "cut-clipboard",
8779 info_entry_priv->editable && mode == DISPLAY_NORMAL &&
8780 info_entry_priv->current_pos != info_entry_priv->selection_bound);
8782 append_action_signal (entry, info_entry_priv->popup_menu, GTK_STOCK_COPY, "copy-clipboard",
8783 mode == DISPLAY_NORMAL &&
8784 info_entry_priv->current_pos != info_entry_priv->selection_bound);
8786 append_action_signal (entry, info_entry_priv->popup_menu, GTK_STOCK_PASTE, "paste-clipboard",
8787 info_entry_priv->editable && clipboard_contains_text);
8789 menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_DELETE, NULL);
8790 gtk_widget_set_sensitive (menuitem, info_entry_priv->editable && info_entry_priv->current_pos != info_entry_priv->selection_bound);
8791 g_signal_connect_swapped (menuitem, "activate",
8792 G_CALLBACK (gtk_entry_delete_cb), entry);
8793 gtk_widget_show (menuitem);
8794 gtk_menu_shell_append (GTK_MENU_SHELL (info_entry_priv->popup_menu), menuitem);
8796 menuitem = gtk_separator_menu_item_new ();
8797 gtk_widget_show (menuitem);
8798 gtk_menu_shell_append (GTK_MENU_SHELL (info_entry_priv->popup_menu), menuitem);
8800 menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_SELECT_ALL, NULL);
8801 gtk_widget_set_sensitive (menuitem, gtk_entry_buffer_get_length (info_entry_priv->buffer) > 0);
8802 g_signal_connect_swapped (menuitem, "activate",
8803 G_CALLBACK (gtk_entry_select_all), entry);
8804 gtk_widget_show (menuitem);
8805 gtk_menu_shell_append (GTK_MENU_SHELL (info_entry_priv->popup_menu), menuitem);
8807 g_object_get (gtk_widget_get_settings (GTK_WIDGET (entry)),
8808 "gtk-show-input-method-menu", &show_input_method_menu,
8809 "gtk-show-unicode-menu", &show_unicode_menu,
8812 if (show_input_method_menu || show_unicode_menu)
8814 menuitem = gtk_separator_menu_item_new ();
8815 gtk_widget_show (menuitem);
8816 gtk_menu_shell_append (GTK_MENU_SHELL (info_entry_priv->popup_menu), menuitem);
8819 if (show_input_method_menu)
8821 menuitem = gtk_menu_item_new_with_mnemonic (_("Input _Methods"));
8822 gtk_widget_set_sensitive (menuitem, info_entry_priv->editable);
8823 gtk_widget_show (menuitem);
8824 submenu = gtk_menu_new ();
8825 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
8827 gtk_menu_shell_append (GTK_MENU_SHELL (info_entry_priv->popup_menu), menuitem);
8829 gtk_im_multicontext_append_menuitems (GTK_IM_MULTICONTEXT (info_entry_priv->im_context),
8830 GTK_MENU_SHELL (submenu));
8833 if (show_unicode_menu)
8835 menuitem = gtk_menu_item_new_with_mnemonic (_("_Insert Unicode Control Character"));
8836 gtk_widget_set_sensitive (menuitem, info_entry_priv->editable);
8837 gtk_widget_show (menuitem);
8839 submenu = gtk_menu_new ();
8840 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
8841 gtk_menu_shell_append (GTK_MENU_SHELL (info_entry_priv->popup_menu), menuitem);
8843 _gtk_text_util_append_special_char_menuitems (GTK_MENU_SHELL (submenu),
8844 unichar_chosen_func,
8848 g_signal_emit (entry,
8849 signals[POPULATE_POPUP],
8851 info_entry_priv->popup_menu);
8855 gtk_menu_popup_for_device (GTK_MENU (info_entry_priv->popup_menu),
8856 info->device, NULL, NULL, NULL, NULL, NULL,
8857 info->button, info->time);
8860 gtk_menu_popup (GTK_MENU (info_entry_priv->popup_menu), NULL, NULL,
8861 popup_position_func, entry,
8862 0, gtk_get_current_event_time ());
8863 gtk_menu_shell_select_first (GTK_MENU_SHELL (info_entry_priv->popup_menu), FALSE);
8867 g_object_unref (entry);
8868 g_slice_free (PopupInfo, info);
8872 gtk_entry_do_popup (GtkEntry *entry,
8873 GdkEventButton *event)
8875 PopupInfo *info = g_slice_new (PopupInfo);
8877 /* In order to know what entries we should make sensitive, we
8878 * ask for the current targets of the clipboard, and when
8879 * we get them, then we actually pop up the menu.
8881 info->entry = g_object_ref (entry);
8885 info->button = event->button;
8886 info->time = event->time;
8887 info->device = event->device;
8892 info->time = gtk_get_current_event_time ();
8893 info->device = NULL;
8896 gtk_clipboard_request_contents (gtk_widget_get_clipboard (GTK_WIDGET (entry), GDK_SELECTION_CLIPBOARD),
8897 gdk_atom_intern_static_string ("TARGETS"),
8898 popup_targets_received,
8903 gtk_entry_popup_menu (GtkWidget *widget)
8905 gtk_entry_do_popup (GTK_ENTRY (widget), NULL);
8910 gtk_entry_drag_begin (GtkWidget *widget,
8911 GdkDragContext *context)
8913 GtkEntry *entry = GTK_ENTRY (widget);
8914 GtkEntryPrivate *priv = entry->priv;
8917 for (i = 0; i < MAX_ICONS; i++)
8919 EntryIconInfo *icon_info = priv->icons[i];
8921 if (icon_info != NULL)
8923 if (icon_info->in_drag)
8927 pix = _gtk_icon_helper_ensure_pixbuf
8928 (icon_info->icon_helper,
8929 gtk_widget_get_style_context (GTK_WIDGET (entry)));
8930 gtk_drag_set_icon_pixbuf (context, pix, -2, -2);
8932 g_object_unref (pix);
8939 gtk_entry_drag_end (GtkWidget *widget,
8940 GdkDragContext *context)
8942 GtkEntry *entry = GTK_ENTRY (widget);
8943 GtkEntryPrivate *priv = entry->priv;
8946 for (i = 0; i < MAX_ICONS; i++)
8948 EntryIconInfo *icon_info = priv->icons[i];
8950 if (icon_info != NULL)
8951 icon_info->in_drag = 0;
8956 gtk_entry_drag_leave (GtkWidget *widget,
8957 GdkDragContext *context,
8960 GtkEntry *entry = GTK_ENTRY (widget);
8961 GtkEntryPrivate *priv = entry->priv;
8963 priv->dnd_position = -1;
8964 gtk_widget_queue_draw (widget);
8968 gtk_entry_drag_drop (GtkWidget *widget,
8969 GdkDragContext *context,
8974 GtkEntry *entry = GTK_ENTRY (widget);
8975 GtkEntryPrivate *priv = entry->priv;
8976 GdkAtom target = GDK_NONE;
8979 target = gtk_drag_dest_find_target (widget, context, NULL);
8981 if (target != GDK_NONE)
8982 gtk_drag_get_data (widget, context, target, time);
8984 gtk_drag_finish (context, FALSE, FALSE, time);
8990 gtk_entry_drag_motion (GtkWidget *widget,
8991 GdkDragContext *context,
8996 GtkEntry *entry = GTK_ENTRY (widget);
8997 GtkEntryPrivate *priv = entry->priv;
8998 GtkStyleContext *style_context;
8999 GtkWidget *source_widget;
9000 GdkDragAction suggested_action;
9001 gint new_position, old_position;
9005 style_context = gtk_widget_get_style_context (widget);
9006 gtk_style_context_get_padding (style_context, 0, &padding);
9010 old_position = priv->dnd_position;
9011 new_position = gtk_entry_find_position (entry, x + priv->scroll_offset);
9013 if (priv->editable &&
9014 gtk_drag_dest_find_target (widget, context, NULL) != GDK_NONE)
9016 source_widget = gtk_drag_get_source_widget (context);
9017 suggested_action = gdk_drag_context_get_suggested_action (context);
9019 if (!gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &sel1, &sel2) ||
9020 new_position < sel1 || new_position > sel2)
9022 if (source_widget == widget)
9024 /* Default to MOVE, unless the user has
9025 * pressed ctrl or alt to affect available actions
9027 if ((gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE) != 0)
9028 suggested_action = GDK_ACTION_MOVE;
9031 priv->dnd_position = new_position;
9035 if (source_widget == widget)
9036 suggested_action = 0; /* Can't drop in selection where drag started */
9038 priv->dnd_position = -1;
9043 /* Entry not editable, or no text */
9044 suggested_action = 0;
9045 priv->dnd_position = -1;
9048 gdk_drag_status (context, suggested_action, time);
9050 if (priv->dnd_position != old_position)
9051 gtk_widget_queue_draw (widget);
9057 gtk_entry_drag_data_received (GtkWidget *widget,
9058 GdkDragContext *context,
9061 GtkSelectionData *selection_data,
9065 GtkEntry *entry = GTK_ENTRY (widget);
9066 GtkEntryPrivate *priv = entry->priv;
9067 GtkEditable *editable = GTK_EDITABLE (widget);
9068 GtkStyleContext *style_context;
9072 str = (gchar *) gtk_selection_data_get_text (selection_data);
9074 style_context = gtk_widget_get_style_context (widget);
9075 gtk_style_context_get_padding (style_context, 0, &padding);
9079 if (str && priv->editable)
9085 if (priv->truncate_multiline)
9086 length = truncate_multiline (str);
9088 new_position = gtk_entry_find_position (entry, x + priv->scroll_offset);
9090 if (!gtk_editable_get_selection_bounds (editable, &sel1, &sel2) ||
9091 new_position < sel1 || new_position > sel2)
9093 gtk_editable_insert_text (editable, str, length, &new_position);
9097 /* Replacing selection */
9098 begin_change (entry);
9099 gtk_editable_delete_text (editable, sel1, sel2);
9100 gtk_editable_insert_text (editable, str, length, &sel1);
9104 gtk_drag_finish (context, TRUE, gdk_drag_context_get_selected_action (context) == GDK_ACTION_MOVE, time);
9108 /* Drag and drop didn't happen! */
9109 gtk_drag_finish (context, FALSE, FALSE, time);
9116 gtk_entry_drag_data_get (GtkWidget *widget,
9117 GdkDragContext *context,
9118 GtkSelectionData *selection_data,
9122 GtkEntry *entry = GTK_ENTRY (widget);
9123 GtkEntryPrivate *priv = entry->priv;
9124 GtkEditable *editable = GTK_EDITABLE (widget);
9125 gint sel_start, sel_end;
9128 /* If there is an icon drag going on, exit early. */
9129 for (i = 0; i < MAX_ICONS; i++)
9131 EntryIconInfo *icon_info = priv->icons[i];
9133 if (icon_info != NULL)
9135 if (icon_info->in_drag)
9140 if (gtk_editable_get_selection_bounds (editable, &sel_start, &sel_end))
9142 gchar *str = _gtk_entry_get_display_text (GTK_ENTRY (widget), sel_start, sel_end);
9144 gtk_selection_data_set_text (selection_data, str, -1);
9152 gtk_entry_drag_data_delete (GtkWidget *widget,
9153 GdkDragContext *context)
9155 GtkEntry *entry = GTK_ENTRY (widget);
9156 GtkEntryPrivate *priv = entry->priv;
9157 GtkEditable *editable = GTK_EDITABLE (widget);
9158 gint sel_start, sel_end;
9161 /* If there is an icon drag going on, exit early. */
9162 for (i = 0; i < MAX_ICONS; i++)
9164 EntryIconInfo *icon_info = priv->icons[i];
9166 if (icon_info != NULL)
9168 if (icon_info->in_drag)
9173 if (priv->editable &&
9174 gtk_editable_get_selection_bounds (editable, &sel_start, &sel_end))
9175 gtk_editable_delete_text (editable, sel_start, sel_end);
9178 /* We display the cursor when
9180 * - the selection is empty, AND
9181 * - the widget has focus
9184 #define CURSOR_ON_MULTIPLIER 2
9185 #define CURSOR_OFF_MULTIPLIER 1
9186 #define CURSOR_PEND_MULTIPLIER 3
9187 #define CURSOR_DIVIDER 3
9190 cursor_blinks (GtkEntry *entry)
9192 GtkEntryPrivate *priv = entry->priv;
9194 if (gtk_widget_has_focus (GTK_WIDGET (entry)) &&
9196 priv->selection_bound == priv->current_pos)
9198 GtkSettings *settings;
9201 settings = gtk_widget_get_settings (GTK_WIDGET (entry));
9202 g_object_get (settings, "gtk-cursor-blink", &blink, NULL);
9211 get_middle_click_paste (GtkEntry *entry)
9213 GtkSettings *settings;
9216 settings = gtk_widget_get_settings (GTK_WIDGET (entry));
9217 g_object_get (settings, "gtk-enable-primary-paste", &paste, NULL);
9223 get_cursor_time (GtkEntry *entry)
9225 GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (entry));
9228 g_object_get (settings, "gtk-cursor-blink-time", &time, NULL);
9234 get_cursor_blink_timeout (GtkEntry *entry)
9236 GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (entry));
9239 g_object_get (settings, "gtk-cursor-blink-timeout", &timeout, NULL);
9245 show_cursor (GtkEntry *entry)
9247 GtkEntryPrivate *priv = entry->priv;
9250 if (!priv->cursor_visible)
9252 priv->cursor_visible = TRUE;
9254 widget = GTK_WIDGET (entry);
9255 if (gtk_widget_has_focus (widget) && priv->selection_bound == priv->current_pos)
9256 gtk_widget_queue_draw (widget);
9261 hide_cursor (GtkEntry *entry)
9263 GtkEntryPrivate *priv = entry->priv;
9266 if (priv->cursor_visible)
9268 priv->cursor_visible = FALSE;
9270 widget = GTK_WIDGET (entry);
9271 if (gtk_widget_has_focus (widget) && priv->selection_bound == priv->current_pos)
9272 gtk_widget_queue_draw (widget);
9280 blink_cb (gpointer data)
9283 GtkEntryPrivate *priv;
9286 entry = GTK_ENTRY (data);
9289 if (!gtk_widget_has_focus (GTK_WIDGET (entry)))
9291 g_warning ("GtkEntry - did not receive focus-out-event. If you\n"
9292 "connect a handler to this signal, it must return\n"
9293 "FALSE so the entry gets the event as well");
9295 gtk_entry_check_cursor_blink (entry);
9300 g_assert (priv->selection_bound == priv->current_pos);
9302 blink_timeout = get_cursor_blink_timeout (entry);
9303 if (priv->blink_time > 1000 * blink_timeout &&
9304 blink_timeout < G_MAXINT/1000)
9306 /* we've blinked enough without the user doing anything, stop blinking */
9307 show_cursor (entry);
9308 priv->blink_timeout = 0;
9310 else if (priv->cursor_visible)
9312 hide_cursor (entry);
9313 priv->blink_timeout = gdk_threads_add_timeout (get_cursor_time (entry) * CURSOR_OFF_MULTIPLIER / CURSOR_DIVIDER,
9319 show_cursor (entry);
9320 priv->blink_time += get_cursor_time (entry);
9321 priv->blink_timeout = gdk_threads_add_timeout (get_cursor_time (entry) * CURSOR_ON_MULTIPLIER / CURSOR_DIVIDER,
9326 /* Remove ourselves */
9331 gtk_entry_check_cursor_blink (GtkEntry *entry)
9333 GtkEntryPrivate *priv = entry->priv;
9335 if (cursor_blinks (entry))
9337 if (!priv->blink_timeout)
9339 show_cursor (entry);
9340 priv->blink_timeout = gdk_threads_add_timeout (get_cursor_time (entry) * CURSOR_ON_MULTIPLIER / CURSOR_DIVIDER,
9347 if (priv->blink_timeout)
9349 g_source_remove (priv->blink_timeout);
9350 priv->blink_timeout = 0;
9353 priv->cursor_visible = TRUE;
9358 gtk_entry_pend_cursor_blink (GtkEntry *entry)
9360 GtkEntryPrivate *priv = entry->priv;
9362 if (cursor_blinks (entry))
9364 if (priv->blink_timeout != 0)
9365 g_source_remove (priv->blink_timeout);
9367 priv->blink_timeout = gdk_threads_add_timeout (get_cursor_time (entry) * CURSOR_PEND_MULTIPLIER / CURSOR_DIVIDER,
9370 show_cursor (entry);
9375 gtk_entry_reset_blink_time (GtkEntry *entry)
9377 GtkEntryPrivate *priv = entry->priv;
9379 priv->blink_time = 0;
9385 gtk_entry_completion_timeout (gpointer data)
9387 GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (data);
9388 GtkEntryPrivate *completion_entry_priv = GTK_ENTRY (completion->priv->entry)->priv;
9390 completion->priv->completion_timeout = 0;
9392 if (completion->priv->filter_model &&
9393 g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (completion->priv->entry)), -1)
9394 >= completion->priv->minimum_key_length)
9398 GtkTreeSelection *s;
9399 gboolean popup_single;
9401 gtk_entry_completion_complete (completion);
9402 matches = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (completion->priv->filter_model), NULL);
9404 gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view)));
9406 s = gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->action_view));
9408 gtk_tree_selection_unselect_all (s);
9410 actions = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (completion->priv->actions), NULL);
9412 g_object_get (completion, "popup-single-match", &popup_single, NULL);
9413 if ((matches > (popup_single ? 0: 1)) || actions > 0)
9415 if (gtk_widget_get_visible (completion->priv->popup_window))
9416 _gtk_entry_completion_resize_popup (completion);
9418 _gtk_entry_completion_popup (completion, completion_entry_priv->completion_device);
9421 _gtk_entry_completion_popdown (completion);
9423 else if (gtk_widget_get_visible (completion->priv->popup_window))
9424 _gtk_entry_completion_popdown (completion);
9429 static inline gboolean
9430 keyval_is_cursor_move (guint keyval)
9432 if (keyval == GDK_KEY_Up || keyval == GDK_KEY_KP_Up)
9435 if (keyval == GDK_KEY_Down || keyval == GDK_KEY_KP_Down)
9438 if (keyval == GDK_KEY_Page_Up)
9441 if (keyval == GDK_KEY_Page_Down)
9448 gtk_entry_completion_key_press (GtkWidget *widget,
9452 gint matches, actions = 0;
9453 GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (user_data);
9455 if (!gtk_widget_get_mapped (completion->priv->popup_window))
9458 matches = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (completion->priv->filter_model), NULL);
9460 if (completion->priv->actions)
9461 actions = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (completion->priv->actions), NULL);
9463 if (keyval_is_cursor_move (event->keyval))
9465 GtkTreePath *path = NULL;
9467 if (event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_KP_Up)
9469 if (completion->priv->current_selected < 0)
9470 completion->priv->current_selected = matches + actions - 1;
9472 completion->priv->current_selected--;
9474 else if (event->keyval == GDK_KEY_Down || event->keyval == GDK_KEY_KP_Down)
9476 if (completion->priv->current_selected < matches + actions - 1)
9477 completion->priv->current_selected++;
9479 completion->priv->current_selected = -1;
9481 else if (event->keyval == GDK_KEY_Page_Up)
9483 if (completion->priv->current_selected < 0)
9484 completion->priv->current_selected = matches + actions - 1;
9485 else if (completion->priv->current_selected == 0)
9486 completion->priv->current_selected = -1;
9487 else if (completion->priv->current_selected < matches)
9489 completion->priv->current_selected -= PAGE_STEP;
9490 if (completion->priv->current_selected < 0)
9491 completion->priv->current_selected = 0;
9495 completion->priv->current_selected -= PAGE_STEP;
9496 if (completion->priv->current_selected < matches - 1)
9497 completion->priv->current_selected = matches - 1;
9500 else if (event->keyval == GDK_KEY_Page_Down)
9502 if (completion->priv->current_selected < 0)
9503 completion->priv->current_selected = 0;
9504 else if (completion->priv->current_selected < matches - 1)
9506 completion->priv->current_selected += PAGE_STEP;
9507 if (completion->priv->current_selected > matches - 1)
9508 completion->priv->current_selected = matches - 1;
9510 else if (completion->priv->current_selected == matches + actions - 1)
9512 completion->priv->current_selected = -1;
9516 completion->priv->current_selected += PAGE_STEP;
9517 if (completion->priv->current_selected > matches + actions - 1)
9518 completion->priv->current_selected = matches + actions - 1;
9522 if (completion->priv->current_selected < 0)
9524 gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view)));
9525 gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->action_view)));
9527 if (completion->priv->inline_selection &&
9528 completion->priv->completion_prefix)
9530 gtk_entry_set_text (GTK_ENTRY (completion->priv->entry),
9531 completion->priv->completion_prefix);
9532 gtk_editable_set_position (GTK_EDITABLE (widget), -1);
9535 else if (completion->priv->current_selected < matches)
9537 gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->action_view)));
9539 path = gtk_tree_path_new_from_indices (completion->priv->current_selected, -1);
9540 gtk_tree_view_set_cursor (GTK_TREE_VIEW (completion->priv->tree_view),
9543 if (completion->priv->inline_selection)
9547 GtkTreeIter child_iter;
9548 GtkTreeModel *model = NULL;
9549 GtkTreeSelection *sel;
9552 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view));
9553 if (!gtk_tree_selection_get_selected (sel, &model, &iter))
9556 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, &iter);
9557 model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
9559 if (completion->priv->completion_prefix == NULL)
9560 completion->priv->completion_prefix = g_strdup (gtk_entry_get_text (GTK_ENTRY (completion->priv->entry)));
9562 g_signal_emit_by_name (completion, "cursor-on-match", model,
9563 &child_iter, &entry_set);
9566 else if (completion->priv->current_selected - matches >= 0)
9568 gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view)));
9570 path = gtk_tree_path_new_from_indices (completion->priv->current_selected - matches, -1);
9571 gtk_tree_view_set_cursor (GTK_TREE_VIEW (completion->priv->action_view),
9574 if (completion->priv->inline_selection &&
9575 completion->priv->completion_prefix)
9577 gtk_entry_set_text (GTK_ENTRY (completion->priv->entry),
9578 completion->priv->completion_prefix);
9579 gtk_editable_set_position (GTK_EDITABLE (widget), -1);
9583 gtk_tree_path_free (path);
9587 else if (event->keyval == GDK_KEY_Escape ||
9588 event->keyval == GDK_KEY_Left ||
9589 event->keyval == GDK_KEY_KP_Left ||
9590 event->keyval == GDK_KEY_Right ||
9591 event->keyval == GDK_KEY_KP_Right)
9593 gboolean retval = TRUE;
9595 _gtk_entry_reset_im_context (GTK_ENTRY (widget));
9596 _gtk_entry_completion_popdown (completion);
9598 if (completion->priv->current_selected < 0)
9601 goto keypress_completion_out;
9603 else if (completion->priv->inline_selection)
9605 /* Escape rejects the tentative completion */
9606 if (event->keyval == GDK_KEY_Escape)
9608 if (completion->priv->completion_prefix)
9609 gtk_entry_set_text (GTK_ENTRY (completion->priv->entry),
9610 completion->priv->completion_prefix);
9612 gtk_entry_set_text (GTK_ENTRY (completion->priv->entry), "");
9615 /* Move the cursor to the end for Right/Esc */
9616 if (event->keyval == GDK_KEY_Right ||
9617 event->keyval == GDK_KEY_KP_Right ||
9618 event->keyval == GDK_KEY_Escape)
9619 gtk_editable_set_position (GTK_EDITABLE (widget), -1);
9620 /* Let the default keybindings run for Left, i.e. either move to the
9621 * previous character or select word if a modifier is used */
9626 keypress_completion_out:
9627 if (completion->priv->inline_selection)
9629 g_free (completion->priv->completion_prefix);
9630 completion->priv->completion_prefix = NULL;
9635 else if (event->keyval == GDK_KEY_Tab ||
9636 event->keyval == GDK_KEY_KP_Tab ||
9637 event->keyval == GDK_KEY_ISO_Left_Tab)
9639 _gtk_entry_reset_im_context (GTK_ENTRY (widget));
9640 _gtk_entry_completion_popdown (completion);
9642 g_free (completion->priv->completion_prefix);
9643 completion->priv->completion_prefix = NULL;
9647 else if (event->keyval == GDK_KEY_ISO_Enter ||
9648 event->keyval == GDK_KEY_KP_Enter ||
9649 event->keyval == GDK_KEY_Return)
9652 GtkTreeModel *model = NULL;
9653 GtkTreeModel *child_model;
9654 GtkTreeIter child_iter;
9655 GtkTreeSelection *sel;
9656 gboolean retval = TRUE;
9658 _gtk_entry_reset_im_context (GTK_ENTRY (widget));
9659 _gtk_entry_completion_popdown (completion);
9661 if (completion->priv->current_selected < matches)
9665 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view));
9666 if (gtk_tree_selection_get_selected (sel, &model, &iter))
9668 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, &iter);
9669 child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
9670 g_signal_handler_block (widget, completion->priv->changed_id);
9671 g_signal_emit_by_name (completion, "match-selected",
9672 child_model, &child_iter, &entry_set);
9673 g_signal_handler_unblock (widget, completion->priv->changed_id);
9679 gtk_tree_model_get (model, &iter,
9680 completion->priv->text_column, &str,
9683 gtk_entry_set_text (GTK_ENTRY (widget), str);
9685 /* move the cursor to the end */
9686 gtk_editable_set_position (GTK_EDITABLE (widget), -1);
9694 else if (completion->priv->current_selected - matches >= 0)
9696 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->action_view));
9697 if (gtk_tree_selection_get_selected (sel, &model, &iter))
9701 path = gtk_tree_path_new_from_indices (completion->priv->current_selected - matches, -1);
9702 g_signal_emit_by_name (completion, "action-activated",
9703 gtk_tree_path_get_indices (path)[0]);
9704 gtk_tree_path_free (path);
9710 g_free (completion->priv->completion_prefix);
9711 completion->priv->completion_prefix = NULL;
9720 gtk_entry_completion_changed (GtkWidget *widget,
9723 GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (user_data);
9724 GtkEntry *entry = GTK_ENTRY (widget);
9725 GtkEntryPrivate *priv = entry->priv;
9728 /* (re)install completion timeout */
9729 if (completion->priv->completion_timeout)
9730 g_source_remove (completion->priv->completion_timeout);
9732 if (!gtk_entry_get_text (entry))
9735 /* no need to normalize for this test */
9736 if (completion->priv->minimum_key_length > 0 &&
9737 strcmp ("", gtk_entry_get_text (entry)) == 0)
9739 if (gtk_widget_get_visible (completion->priv->popup_window))
9740 _gtk_entry_completion_popdown (completion);
9744 device = gtk_get_current_event_device ();
9746 if (device && gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
9747 device = gdk_device_get_associated_device (device);
9750 priv->completion_device = device;
9752 completion->priv->completion_timeout =
9753 gdk_threads_add_timeout (COMPLETION_TIMEOUT,
9754 gtk_entry_completion_timeout,
9759 check_completion_callback (GtkEntryCompletion *completion)
9761 completion->priv->check_completion_idle = NULL;
9763 gtk_entry_completion_complete (completion);
9764 gtk_entry_completion_insert_prefix (completion);
9770 clear_completion_callback (GtkEntry *entry,
9773 if (pspec->name == I_("cursor-position") ||
9774 pspec->name == I_("selection-bound"))
9776 GtkEntryCompletion *completion = gtk_entry_get_completion (entry);
9778 completion->priv->has_completion = FALSE;
9783 accept_completion_callback (GtkEntry *entry)
9785 GtkEntryCompletion *completion = gtk_entry_get_completion (entry);
9787 if (completion->priv->has_completion)
9788 gtk_editable_set_position (GTK_EDITABLE (entry),
9789 gtk_entry_buffer_get_length (get_buffer (entry)));
9795 completion_insert_text_callback (GtkEntry *entry,
9799 GtkEntryCompletion *completion)
9801 /* idle to update the selection based on the file list */
9802 if (completion->priv->check_completion_idle == NULL)
9804 completion->priv->check_completion_idle = g_idle_source_new ();
9805 g_source_set_priority (completion->priv->check_completion_idle, G_PRIORITY_HIGH);
9806 g_source_set_closure (completion->priv->check_completion_idle,
9807 g_cclosure_new_object (G_CALLBACK (check_completion_callback),
9808 G_OBJECT (completion)));
9809 g_source_attach (completion->priv->check_completion_idle, NULL);
9814 completion_changed (GtkEntryCompletion *completion,
9818 GtkEntry *entry = GTK_ENTRY (data);
9820 if (pspec->name == I_("popup-completion") ||
9821 pspec->name == I_("inline-completion"))
9823 disconnect_completion_signals (entry, completion);
9824 connect_completion_signals (entry, completion);
9829 disconnect_completion_signals (GtkEntry *entry,
9830 GtkEntryCompletion *completion)
9832 g_signal_handlers_disconnect_by_func (completion,
9833 G_CALLBACK (completion_changed), entry);
9834 if (completion->priv->changed_id > 0 &&
9835 g_signal_handler_is_connected (entry, completion->priv->changed_id))
9837 g_signal_handler_disconnect (entry, completion->priv->changed_id);
9838 completion->priv->changed_id = 0;
9840 g_signal_handlers_disconnect_by_func (entry,
9841 G_CALLBACK (gtk_entry_completion_key_press), completion);
9842 if (completion->priv->insert_text_id > 0 &&
9843 g_signal_handler_is_connected (entry, completion->priv->insert_text_id))
9845 g_signal_handler_disconnect (entry, completion->priv->insert_text_id);
9846 completion->priv->insert_text_id = 0;
9848 g_signal_handlers_disconnect_by_func (entry,
9849 G_CALLBACK (completion_insert_text_callback), completion);
9850 g_signal_handlers_disconnect_by_func (entry,
9851 G_CALLBACK (clear_completion_callback), completion);
9852 g_signal_handlers_disconnect_by_func (entry,
9853 G_CALLBACK (accept_completion_callback), completion);
9857 connect_completion_signals (GtkEntry *entry,
9858 GtkEntryCompletion *completion)
9860 if (completion->priv->popup_completion)
9862 completion->priv->changed_id =
9863 g_signal_connect (entry, "changed",
9864 G_CALLBACK (gtk_entry_completion_changed), completion);
9865 g_signal_connect (entry, "key-press-event",
9866 G_CALLBACK (gtk_entry_completion_key_press), completion);
9869 if (completion->priv->inline_completion)
9871 completion->priv->insert_text_id =
9872 g_signal_connect (entry, "insert-text",
9873 G_CALLBACK (completion_insert_text_callback), completion);
9874 g_signal_connect (entry, "notify",
9875 G_CALLBACK (clear_completion_callback), completion);
9876 g_signal_connect (entry, "activate",
9877 G_CALLBACK (accept_completion_callback), completion);
9878 g_signal_connect (entry, "focus-out-event",
9879 G_CALLBACK (accept_completion_callback), completion);
9882 g_signal_connect (completion, "notify",
9883 G_CALLBACK (completion_changed), entry);
9887 * gtk_entry_set_completion:
9888 * @entry: A #GtkEntry
9889 * @completion: (allow-none): The #GtkEntryCompletion or %NULL
9891 * Sets @completion to be the auxiliary completion object to use with @entry.
9892 * All further configuration of the completion mechanism is done on
9893 * @completion using the #GtkEntryCompletion API. Completion is disabled if
9894 * @completion is set to %NULL.
9899 gtk_entry_set_completion (GtkEntry *entry,
9900 GtkEntryCompletion *completion)
9902 GtkEntryCompletion *old;
9904 g_return_if_fail (GTK_IS_ENTRY (entry));
9905 g_return_if_fail (!completion || GTK_IS_ENTRY_COMPLETION (completion));
9907 old = gtk_entry_get_completion (entry);
9909 if (old == completion)
9914 if (old->priv->completion_timeout)
9916 g_source_remove (old->priv->completion_timeout);
9917 old->priv->completion_timeout = 0;
9920 if (old->priv->check_completion_idle)
9922 g_source_destroy (old->priv->check_completion_idle);
9923 old->priv->check_completion_idle = NULL;
9926 if (gtk_widget_get_mapped (old->priv->popup_window))
9927 _gtk_entry_completion_popdown (old);
9929 disconnect_completion_signals (entry, old);
9930 old->priv->entry = NULL;
9932 g_object_unref (old);
9937 g_object_set_data (G_OBJECT (entry), I_(GTK_ENTRY_COMPLETION_KEY), NULL);
9941 /* hook into the entry */
9942 g_object_ref (completion);
9944 connect_completion_signals (entry, completion);
9945 completion->priv->entry = GTK_WIDGET (entry);
9946 g_object_set_data (G_OBJECT (entry), I_(GTK_ENTRY_COMPLETION_KEY), completion);
9948 g_object_notify (G_OBJECT (entry), "completion");
9952 * gtk_entry_get_completion:
9953 * @entry: A #GtkEntry
9955 * Returns the auxiliary completion object currently in use by @entry.
9957 * Return value: (transfer none): The auxiliary completion object currently
9962 GtkEntryCompletion *
9963 gtk_entry_get_completion (GtkEntry *entry)
9965 GtkEntryCompletion *completion;
9967 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
9969 completion = GTK_ENTRY_COMPLETION (g_object_get_data (G_OBJECT (entry),
9970 GTK_ENTRY_COMPLETION_KEY));
9976 * gtk_entry_set_cursor_hadjustment:
9977 * @entry: a #GtkEntry
9978 * @adjustment: an adjustment which should be adjusted when the cursor
9979 * is moved, or %NULL
9981 * Hooks up an adjustment to the cursor position in an entry, so that when
9982 * the cursor is moved, the adjustment is scrolled to show that position.
9983 * See gtk_scrolled_window_get_hadjustment() for a typical way of obtaining
9986 * The adjustment has to be in pixel units and in the same coordinate system
9992 gtk_entry_set_cursor_hadjustment (GtkEntry *entry,
9993 GtkAdjustment *adjustment)
9995 g_return_if_fail (GTK_IS_ENTRY (entry));
9997 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
10000 g_object_ref (adjustment);
10002 g_object_set_qdata_full (G_OBJECT (entry),
10003 quark_cursor_hadjustment,
10009 * gtk_entry_get_cursor_hadjustment:
10010 * @entry: a #GtkEntry
10012 * Retrieves the horizontal cursor adjustment for the entry.
10013 * See gtk_entry_set_cursor_hadjustment().
10015 * Return value: (transfer none): the horizontal cursor adjustment, or %NULL
10016 * if none has been set.
10021 gtk_entry_get_cursor_hadjustment (GtkEntry *entry)
10023 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
10025 return g_object_get_qdata (G_OBJECT (entry), quark_cursor_hadjustment);
10029 * gtk_entry_set_progress_fraction:
10030 * @entry: a #GtkEntry
10031 * @fraction: fraction of the task that's been completed
10033 * Causes the entry's progress indicator to "fill in" the given
10034 * fraction of the bar. The fraction should be between 0.0 and 1.0,
10040 gtk_entry_set_progress_fraction (GtkEntry *entry,
10044 GtkEntryPrivate *private;
10045 gdouble old_fraction;
10046 gint x, y, width, height;
10047 gint old_x, old_y, old_width, old_height;
10049 g_return_if_fail (GTK_IS_ENTRY (entry));
10051 widget = GTK_WIDGET (entry);
10052 private = entry->priv;
10054 if (private->progress_pulse_mode)
10057 old_fraction = private->progress_fraction;
10059 if (gtk_widget_is_drawable (widget))
10060 get_progress_area (widget, &old_x, &old_y, &old_width, &old_height);
10062 fraction = CLAMP (fraction, 0.0, 1.0);
10064 private->progress_fraction = fraction;
10065 private->progress_pulse_mode = FALSE;
10066 private->progress_pulse_current = 0.0;
10068 if (gtk_widget_is_drawable (widget))
10070 get_progress_area (widget, &x, &y, &width, &height);
10072 if ((x != old_x) || (y != old_y) || (width != old_width) || (height != old_height))
10073 gtk_widget_queue_draw (widget);
10076 if (fraction != old_fraction)
10077 g_object_notify (G_OBJECT (entry), "progress-fraction");
10081 * gtk_entry_get_progress_fraction:
10082 * @entry: a #GtkEntry
10084 * Returns the current fraction of the task that's been completed.
10085 * See gtk_entry_set_progress_fraction().
10087 * Return value: a fraction from 0.0 to 1.0
10092 gtk_entry_get_progress_fraction (GtkEntry *entry)
10094 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0.0);
10096 return entry->priv->progress_fraction;
10100 * gtk_entry_set_progress_pulse_step:
10101 * @entry: a #GtkEntry
10102 * @fraction: fraction between 0.0 and 1.0
10104 * Sets the fraction of total entry width to move the progress
10105 * bouncing block for each call to gtk_entry_progress_pulse().
10110 gtk_entry_set_progress_pulse_step (GtkEntry *entry,
10113 GtkEntryPrivate *private;
10115 g_return_if_fail (GTK_IS_ENTRY (entry));
10117 private = entry->priv;
10119 fraction = CLAMP (fraction, 0.0, 1.0);
10121 if (fraction != private->progress_pulse_fraction)
10123 private->progress_pulse_fraction = fraction;
10125 gtk_widget_queue_draw (GTK_WIDGET (entry));
10127 g_object_notify (G_OBJECT (entry), "progress-pulse-step");
10132 * gtk_entry_get_progress_pulse_step:
10133 * @entry: a #GtkEntry
10135 * Retrieves the pulse step set with gtk_entry_set_progress_pulse_step().
10137 * Return value: a fraction from 0.0 to 1.0
10142 gtk_entry_get_progress_pulse_step (GtkEntry *entry)
10144 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0.0);
10146 return entry->priv->progress_pulse_fraction;
10150 * gtk_entry_progress_pulse:
10151 * @entry: a #GtkEntry
10153 * Indicates that some progress is made, but you don't know how much.
10154 * Causes the entry's progress indicator to enter "activity mode,"
10155 * where a block bounces back and forth. Each call to
10156 * gtk_entry_progress_pulse() causes the block to move by a little bit
10157 * (the amount of movement per pulse is determined by
10158 * gtk_entry_set_progress_pulse_step()).
10163 gtk_entry_progress_pulse (GtkEntry *entry)
10165 GtkEntryPrivate *private;
10167 g_return_if_fail (GTK_IS_ENTRY (entry));
10169 private = entry->priv;
10171 if (private->progress_pulse_mode)
10173 if (private->progress_pulse_way_back)
10175 private->progress_pulse_current -= private->progress_pulse_fraction;
10177 if (private->progress_pulse_current < 0.0)
10179 private->progress_pulse_current = 0.0;
10180 private->progress_pulse_way_back = FALSE;
10185 private->progress_pulse_current += private->progress_pulse_fraction;
10187 if (private->progress_pulse_current > 1.0 - private->progress_pulse_fraction)
10189 private->progress_pulse_current = 1.0 - private->progress_pulse_fraction;
10190 private->progress_pulse_way_back = TRUE;
10196 private->progress_fraction = 0.0;
10197 private->progress_pulse_mode = TRUE;
10198 private->progress_pulse_way_back = FALSE;
10199 private->progress_pulse_current = 0.0;
10202 gtk_widget_queue_draw (GTK_WIDGET (entry));
10206 * gtk_entry_set_placeholder_text:
10207 * @entry: a #GtkEntry
10208 * @text: a string to be displayed when @entry is empty an unfocused, or %NULL
10210 * Sets text to be displayed in @entry when it is empty and unfocused.
10211 * This can be used to give a visual hint of the expected contents of
10214 * Note that since the placeholder text gets removed when the entry
10215 * received focus, using this feature is a bit problematic if the entry
10216 * is given the initial focus in a window. Sometimes this can be
10217 * worked around by delaying the initial focus setting until the
10218 * first key event arrives.
10223 gtk_entry_set_placeholder_text (GtkEntry *entry,
10226 GtkEntryPrivate *priv;
10228 g_return_if_fail (GTK_IS_ENTRY (entry));
10230 priv = entry->priv;
10232 if (g_strcmp0 (priv->placeholder_text, text) == 0)
10235 g_free (priv->placeholder_text);
10236 priv->placeholder_text = g_strdup (text);
10238 gtk_entry_recompute (entry);
10240 g_object_notify (G_OBJECT (entry), "placeholder-text");
10244 * gtk_entry_get_placeholder_text:
10245 * @entry: a #GtkEntry
10247 * Retrieves the text that will be displayed when @entry is empty and unfocused
10249 * Returns: a pointer to the placeholder text as a string. This string points to internally allocated
10250 * storage in the widget and must not be freed, modified or stored.
10255 gtk_entry_get_placeholder_text (GtkEntry *entry)
10257 GtkEntryPrivate *priv;
10259 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
10261 priv = entry->priv;
10263 return priv->placeholder_text;
10266 /* Caps Lock warning for password entries */
10269 show_capslock_feedback (GtkEntry *entry,
10272 GtkEntryPrivate *priv = entry->priv;
10274 if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY)
10276 gtk_entry_set_icon_from_stock (entry, GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CAPS_LOCK_WARNING);
10277 gtk_entry_set_icon_activatable (entry, GTK_ENTRY_ICON_SECONDARY, FALSE);
10278 priv->caps_lock_warning_shown = TRUE;
10281 if (priv->caps_lock_warning_shown)
10282 gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY, text);
10284 g_warning ("Can't show Caps Lock warning, since secondary icon is set");
10288 remove_capslock_feedback (GtkEntry *entry)
10290 GtkEntryPrivate *priv = entry->priv;
10292 if (priv->caps_lock_warning_shown)
10294 gtk_entry_set_icon_from_stock (entry, GTK_ENTRY_ICON_SECONDARY, NULL);
10295 priv->caps_lock_warning_shown = FALSE;
10300 keymap_state_changed (GdkKeymap *keymap,
10303 GtkEntryPrivate *priv = entry->priv;
10306 if (gtk_entry_get_display_mode (entry) != DISPLAY_NORMAL && priv->caps_lock_warning)
10308 if (gdk_keymap_get_caps_lock_state (keymap))
10309 text = _("Caps Lock is on");
10313 show_capslock_feedback (entry, text);
10315 remove_capslock_feedback (entry);
10319 * _gtk_entry_set_is_cell_renderer:
10320 * @entry: a #GtkEntry
10321 * @is_cell_renderer: new value
10323 * This is a helper function for GtkComboBox. A GtkEntry in a GtkComboBox
10324 * is supposed to behave like a GtkCellEditable when placed in a combo box.
10326 * I.e take up its allocation and get GtkEntry->is_cell_renderer = TRUE.
10330 _gtk_entry_set_is_cell_renderer (GtkEntry *entry,
10331 gboolean is_cell_renderer)
10333 entry->priv->is_cell_renderer = is_cell_renderer;
10337 gtk_entry_set_input_purpose (GtkEntry *entry,
10338 GtkInputPurpose purpose)
10341 g_return_if_fail (GTK_IS_ENTRY (entry));
10343 if (gtk_entry_get_input_purpose (entry) != purpose)
10345 g_object_set (G_OBJECT (entry->priv->im_context),
10346 "input-purpose", purpose,
10349 g_object_notify (G_OBJECT (entry), "input-purpose");
10354 gtk_entry_get_input_purpose (GtkEntry *entry)
10356 GtkInputPurpose purpose;
10358 g_return_val_if_fail (GTK_IS_ENTRY (entry), GTK_INPUT_PURPOSE_FREE_FORM);
10360 g_object_get (G_OBJECT (entry->priv->im_context),
10361 "input-purpose", &purpose,
10368 gtk_entry_set_input_hints (GtkEntry *entry,
10369 GtkInputHints hints)
10372 g_return_if_fail (GTK_IS_ENTRY (entry));
10374 if (gtk_entry_get_input_hints (entry) != hints)
10376 g_object_set (G_OBJECT (entry->priv->im_context),
10377 "input-hints", hints,
10380 g_object_notify (G_OBJECT (entry), "input-hints");
10385 gtk_entry_get_input_hints (GtkEntry *entry)
10387 GtkInputHints hints;
10389 g_return_val_if_fail (GTK_IS_ENTRY (entry), GTK_INPUT_HINT_NONE);
10391 g_object_get (G_OBJECT (entry->priv->im_context),
10392 "input-hints", &hints,