diff options
author | Koen Kooi <koen@openembedded.org> | 2005-06-30 08:19:37 +0000 |
---|---|---|
committer | OpenEmbedded Project <openembedded-devel@lists.openembedded.org> | 2005-06-30 08:19:37 +0000 |
commit | c8e5702127e507e82e6f68a4b8c546803accea9d (patch) | |
tree | 00583491f40ecc640f2b28452af995e3a63a09d7 /packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff | |
parent | 87ec8ca4d2e2eb4d1c1e1e1a6b46a395d56805b9 (diff) |
import clean BK tree at cset 1.3670
Diffstat (limited to 'packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff')
-rw-r--r-- | packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff | 1308 |
1 files changed, 1308 insertions, 0 deletions
diff --git a/packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff b/packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff index e69de29bb2..fae911305c 100644 --- a/packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff +++ b/packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff @@ -0,0 +1,1308 @@ +--- gtk+-2.6.4/gtk/gtkentry.c 2005-02-04 17:36:02.000000000 +0200 ++++ gtk+-2.6.4/gtk/gtkentry.c 2005-04-06 16:19:36.466994536 +0300 +@@ -24,6 +24,10 @@ + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + ++ /* Modified for Nokia Oyj during 2002-2003. See CHANGES file for list ++ * of changes. ++ */ ++ + #include <config.h> + #include <string.h> + +@@ -53,6 +57,7 @@ + #include "gtktreeselection.h" + #include "gtkentryprivate.h" + #include "gtkcelllayout.h" ++#include "gtkscrolledwindow.h" + + #define GTK_ENTRY_COMPLETION_KEY "gtk-entry-completion-key" + +@@ -60,6 +65,8 @@ + #define DRAW_TIMEOUT 20 + #define INNER_BORDER 2 + #define COMPLETION_TIMEOUT 300 ++#define HILDON_EDITED_CHARACTER_MAX 8 ++#define HILDON_EDITED_CHARACTER_MS 600 /* 0.6 seconds */ + + /* Initial size of buffer, in bytes */ + #define MIN_SIZE 16 +@@ -75,6 +82,18 @@ + { + gfloat xalign; + gint insert_pos; ++ /* Hildon additions: ++ * following variables are needed ++ * for Hildon password 'preview' ++ * functionality; last inputted character ++ * is showed for defined period, before it is ++ * rendered to '*' ++ */ ++ gchar hildon_edited_character[HILDON_EDITED_CHARACTER_MAX]; ++ gboolean hildon_edited_character_timeout; ++ gint hildon_edited_character_length; ++ gboolean keep_focus; ++ gboolean menu_popped; + }; + + enum { +@@ -104,7 +123,9 @@ + PROP_WIDTH_CHARS, + PROP_SCROLL_OFFSET, + PROP_TEXT, +- PROP_XALIGN ++ PROP_XALIGN, ++ PROP_AUTOCAP, ++ PROP_INPUT_MODE + }; + + static guint signals[LAST_SIGNAL] = { 0 }; +@@ -324,6 +345,23 @@ + gint *y, + gint *width, + gint *height); ++static void gtk_entry_update_scrolled_window (GtkEntry *entry); ++static void gtk_entry_set_autocap (GtkEntry *entry, ++ gboolean autocap); ++static gboolean gtk_entry_get_autocap (GtkEntry *entry); ++static void gtk_entry_set_input_mode (GtkEntry *entry, ++ gboolean mode); ++static gint gtk_entry_get_input_mode (GtkEntry *entry); ++ ++/*Change for Hildon ++ *returns an iterator to the character at position x,y of the ++ *layout ++ *returns NULL if no iterator was found at that position ++ *Caller must call pango_layout_free_iter on the returned iterator ++ */ ++static PangoLayoutIter *get_char_at_pos( PangoLayout *layout, gint x, gint y ); ++ ++static gboolean hildon_remove_visible_character( gpointer data ); + + /* Completion */ + static gint gtk_entry_completion_timeout (gpointer data); +@@ -523,7 +561,25 @@ + P_("FALSE displays the \"invisible char\" instead of the actual text (password mode)"), + TRUE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); +- ++ ++ g_object_class_install_property (gobject_class, ++ PROP_AUTOCAP, ++ g_param_spec_boolean ("autocap", ++ P_("auto capitalization"), ++ P_("Enable autocap support"), ++ TRUE, ++ G_PARAM_READABLE | G_PARAM_WRITABLE)); ++ ++ g_object_class_install_property (gobject_class, ++ PROP_INPUT_MODE, ++ g_param_spec_int ("input_mode", ++ P_("input mode"), ++ P_("Define widget's input mode"), ++ 0, ++ 9, /* keep me updated */ ++ 0, ++ G_PARAM_READABLE | G_PARAM_WRITABLE)); ++ + g_object_class_install_property (gobject_class, + PROP_HAS_FRAME, + g_param_spec_boolean ("has_frame", +@@ -593,6 +649,40 @@ + 0.0, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + ++ gtk_widget_class_install_style_property (widget_class, ++ g_param_spec_int ("horizontal-border", ++ P_("Horizontal borders for entry"), ++ P_("Set left/right borders"), ++ 0, ++ G_MAXINT, ++ INNER_BORDER, ++ G_PARAM_READWRITE)); ++ ++ gtk_widget_class_install_style_property (widget_class, ++ g_param_spec_int ("vertical-border", ++ P_("Vertical borders for entry"), ++ P_("Set top/bottom borders"), ++ 0, ++ G_MAXINT, ++ INNER_BORDER, ++ G_PARAM_READWRITE)); ++ ++ gtk_widget_class_install_style_property (widget_class, ++ g_param_spec_int ("icon-width", ++ P_("Icon Width"), ++ P_("Size of the purpose icon."), ++ 0, ++ G_MAXINT, ++ 0, ++ G_PARAM_READWRITE)); ++ ++ gtk_widget_class_install_style_property (widget_class, ++ g_param_spec_boolean ("show-last-char", ++ P_("Show last char in invisible mode for a while"), ++ P_("Last char is shown before it is rendered to asterisk"), ++ FALSE, ++ G_PARAM_READABLE | G_PARAM_WRITABLE)); ++ + signals[POPULATE_POPUP] = + g_signal_new ("populate_popup", + G_OBJECT_CLASS_TYPE (gobject_class), +@@ -853,6 +943,22 @@ + iface->start_editing = gtk_entry_start_editing; + } + ++/* HILDON: Timed function to hide the most recently inputted character in password mode ++*/ ++static gboolean ++ hildon_remove_visible_character( gpointer data ) ++{ ++ g_return_val_if_fail (GTK_IS_WIDGET (data), FALSE); ++ ++ GtkEntry * entry = GTK_ENTRY( data ); ++ ++ /* Force the string to redrawn, but now without a visible character */ ++ gtk_entry_recompute( entry ); ++ ++ /* Return false so this timeout is not called again and destroyed */ ++ return FALSE; ++} ++ + static void + gtk_entry_set_property (GObject *object, + guint prop_id, +@@ -867,9 +973,10 @@ + { + gboolean new_value = g_value_get_boolean (value); + ++ gtk_widget_set_sensitive( GTK_WIDGET( entry ), entry->editable ); + if (new_value != entry->editable) + { +- if (!new_value) ++ if (!new_value) + { + gtk_entry_reset_im_context (entry); + if (GTK_WIDGET_HAS_FOCUS (entry)) +@@ -896,6 +1003,14 @@ + case PROP_VISIBILITY: + gtk_entry_set_visibility (entry, g_value_get_boolean (value)); + break; ++ ++ case PROP_AUTOCAP: ++ gtk_entry_set_autocap (entry, g_value_get_boolean (value)); ++ break; ++ ++ case PROP_INPUT_MODE: ++ gtk_entry_set_input_mode (entry, g_value_get_int (value)); ++ break; + + case PROP_HAS_FRAME: + gtk_entry_set_has_frame (entry, g_value_get_boolean (value)); +@@ -954,6 +1069,12 @@ + case PROP_VISIBILITY: + g_value_set_boolean (value, entry->visible); + break; ++ case PROP_AUTOCAP: ++ g_value_set_boolean (value, gtk_entry_get_autocap (entry)); ++ break; ++ case PROP_INPUT_MODE: ++ g_value_set_int (value, gtk_entry_get_input_mode (entry)); ++ break; + case PROP_HAS_FRAME: + g_value_set_boolean (value, entry->has_frame); + break; +@@ -1000,7 +1121,20 @@ + entry->width_chars = -1; + entry->is_cell_renderer = FALSE; + entry->editing_canceled = FALSE; +- entry->has_frame = TRUE; ++#ifdef HILDON_SINGLE_LINE_EDITOR ++ entry->has_frame = FALSE; ++#else ++ entry->has_frame = TRUE; ++#endif ++ ++ /* Hildon */ ++ memset( &priv->hildon_edited_character, 0x00, HILDON_EDITED_CHARACTER_MAX ); ++ priv->hildon_edited_character_length = 0; ++ priv->hildon_edited_character_timeout = FALSE; ++ ++ priv->keep_focus = FALSE; ++ priv->menu_popped = FALSE; ++ + priv->xalign = 0.0; + + gtk_drag_dest_set (GTK_WIDGET (entry), +@@ -1013,6 +1147,10 @@ + * to it; so we create it here and destroy it in finalize(). + */ + entry->im_context = gtk_im_multicontext_new (); ++ /* Set default stuff. */ ++ gtk_entry_set_autocap (entry, TRUE); ++ gtk_entry_set_input_mode (entry, 0); /* alpha-numeric-special */ ++ g_object_set (G_OBJECT (entry->im_context), "use-show-hide", TRUE, NULL); + + g_signal_connect (entry->im_context, "commit", + G_CALLBACK (gtk_entry_commit_cb), entry); +@@ -1058,7 +1196,8 @@ + gtk_entry_finalize (GObject *object) + { + GtkEntry *entry = GTK_ENTRY (object); +- ++ GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (GTK_WIDGET (entry)); ++ + gtk_entry_set_completion (entry, NULL); + + if (entry->cached_layout) +@@ -1072,6 +1211,9 @@ + if (entry->recompute_idle) + g_source_remove (entry->recompute_idle); + ++ if (priv->hildon_edited_character_timeout) ++ g_source_remove (priv->hildon_edited_character_timeout); ++ + entry->text_size = 0; + + if (entry->text) +@@ -1213,7 +1355,14 @@ + PangoFontMetrics *metrics; + gint xborder, yborder; + PangoContext *context; +- ++ gint border_x, border_y; ++ gint icon_width; ++ ++ gtk_widget_style_get (widget, ++ "horizontal-border", &border_x, ++ "vertical-border", &border_y, ++ "icon-width", &icon_width, NULL); ++ + gtk_widget_ensure_style (widget); + context = gtk_widget_get_pango_context (widget); + metrics = pango_context_get_metrics (context, +@@ -1225,21 +1374,22 @@ + + _gtk_entry_get_borders (entry, &xborder, &yborder); + +- xborder += INNER_BORDER; +- yborder += INNER_BORDER; ++ xborder += border_x<<1; ++ yborder += border_y<<1; + + if (entry->width_chars < 0) +- requisition->width = MIN_ENTRY_WIDTH + xborder * 2; ++ requisition->width = MIN_ENTRY_WIDTH + xborder; + else + { + gint char_width = pango_font_metrics_get_approximate_char_width (metrics); + gint digit_width = pango_font_metrics_get_approximate_digit_width (metrics); + gint char_pixels = (MAX (char_width, digit_width) + PANGO_SCALE - 1) / PANGO_SCALE; + +- requisition->width = char_pixels * entry->width_chars + xborder * 2; ++ requisition->width = char_pixels * entry->width_chars + xborder; + } +- +- requisition->height = PANGO_PIXELS (entry->ascent + entry->descent) + yborder * 2; ++ ++ requisition->width += icon_width; ++ requisition->height = PANGO_PIXELS (entry->ascent + entry->descent) + yborder; + + pango_font_metrics_unref (metrics); + } +@@ -1253,23 +1403,39 @@ + { + gint xborder, yborder; + GtkRequisition requisition; ++ gint icon_width; + GtkWidget *widget = GTK_WIDGET (entry); + ++ gtk_widget_style_get (widget, "icon-width", &icon_width, NULL); ++ + gtk_widget_get_child_requisition (widget, &requisition); + + _gtk_entry_get_borders (entry, &xborder, &yborder); + + if (x) +- *x = xborder; ++ *x = xborder + icon_width; + + if (y) ++ { + *y = yborder; ++ if( widget->allocation.height < requisition.height ) ++ *y += ((widget->allocation.height - requisition.height) / 2); ++ if( *y < yborder ) ++ *y = yborder; ++ } + + if (width) +- *width = GTK_WIDGET (entry)->allocation.width - xborder * 2; ++ *width = GTK_WIDGET (entry)->allocation.width - xborder * 2 - icon_width; + + if (height) +- *height = requisition.height - yborder * 2; ++ { ++ if( widget->allocation.height < requisition.height ) ++ *height = widget->allocation.height - yborder * 2; ++ else ++ *height = widget->requisition.height - yborder * 2; ++ if( *height <=0 ) ++ *height = 1; ++ } + } + + static void +@@ -1289,10 +1455,9 @@ + + if (y) + { +- if (entry->is_cell_renderer) +- *y = widget->allocation.y; +- else +- *y = widget->allocation.y + (widget->allocation.height - requisition.height) / 2; ++ *y = widget->allocation.y; ++ if( widget->allocation.height > requisition.height ) ++ *y += ((widget->allocation.height - requisition.height) / 2); + } + + if (width) +@@ -1300,10 +1465,10 @@ + + if (height) + { +- if (entry->is_cell_renderer) +- *height = widget->allocation.height; +- else ++ if( widget->allocation.height > requisition.height ) + *height = requisition.height; ++ else ++ *height = widget->allocation.height; + } + } + +@@ -1383,20 +1548,19 @@ + GdkEventExpose *event) + { + GtkEntry *entry = GTK_ENTRY (widget); ++ gint area_width, area_height; ++ ++ get_widget_window_size (entry, NULL, NULL, &area_width, &area_height); + + if (widget->window == event->window) +- gtk_entry_draw_frame (widget); ++ { ++ gtk_paint_box (widget->style, widget->window, ++ GTK_WIDGET_STATE (widget), GTK_SHADOW_NONE, ++ NULL, widget, "entry_frame", ++ 0, 0, area_width, area_height); ++ } + else if (entry->text_area == event->window) + { +- gint area_width, area_height; +- +- get_text_area_size (entry, NULL, NULL, &area_width, &area_height); +- +- gtk_paint_flat_box (widget->style, entry->text_area, +- GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE, +- NULL, widget, "entry_bg", +- 0, 0, area_width, area_height); +- + if ((entry->visible || entry->invisible_char != 0) && + GTK_WIDGET_HAS_FOCUS (widget) && + entry->selection_bound == entry->current_pos && entry->cursor_visible) +@@ -1490,16 +1654,19 @@ + return FALSE; + + entry->button = event->button; +- ++ + if (!GTK_WIDGET_HAS_FOCUS (widget)) + { + entry->in_click = TRUE; + gtk_widget_grab_focus (widget); + entry->in_click = FALSE; + } +- ++ ++ /* Hildon: we need to reset IM context so pre-edit string can be committed */ ++ gtk_entry_reset_im_context (entry); ++ + tmp_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset); +- ++ + if (event->button == 1) + { + gboolean have_selection = gtk_editable_get_selection_bounds (editable, &sel_start, &sel_end); +@@ -1509,8 +1676,6 @@ + + if (event->state & GDK_SHIFT_MASK) + { +- gtk_entry_reset_im_context (entry); +- + if (!have_selection) /* select from the current position to the clicked position */ + sel_start = sel_end = entry->current_pos; + +@@ -1575,9 +1740,20 @@ + entry->drag_start_x = event->x + entry->scroll_offset; + entry->drag_start_y = event->y + entry->scroll_offset; + } +- else +- gtk_editable_set_position (editable, tmp_pos); +- break; ++ else { ++ /* HILDON: do not move the cursor inside the textarea if invisible ++ * as per the specifications */ ++ if (!entry->visible) ++ if(tmp_pos == strlen(gtk_entry_get_text(entry))){ ++ gtk_editable_set_position( editable, entry->text_length); ++ } else { ++ gtk_editable_select_region (editable, 0, -1); ++ } ++ else ++ gtk_editable_set_position (editable, tmp_pos); ++ } ++ ++ break; + + case GDK_2BUTTON_PRESS: + /* We ALWAYS receive a GDK_BUTTON_PRESS immediately before +@@ -1614,8 +1790,16 @@ + } + else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) + { ++ /* Hildon: if we are in password mode selection and Cut & Copy should ++ be disabled. */ ++ if (!entry->visible) ++ { ++ gtk_editable_set_position (GTK_EDITABLE(entry), 0); ++ } ++ + gtk_entry_do_popup (entry, event); + entry->button = 0; /* Don't wait for release, since the menu will gtk_grab_add */ ++ priv->keep_focus = TRUE; + + return TRUE; + } +@@ -1632,11 +1816,23 @@ + if (event->window != entry->text_area || entry->button != event->button) + return FALSE; + ++ if (entry->editable) ++ gtk_im_context_show (entry->im_context); ++ + if (entry->in_drag) + { + gint tmp_pos = gtk_entry_find_position (entry, entry->drag_start_x); + +- gtk_editable_set_position (GTK_EDITABLE (entry), tmp_pos); ++ /* HILDON: If not visible, do not allow cursor to be positioned inside the string */ ++ if (!entry->visible){ ++ if(tmp_pos == strlen(gtk_entry_get_text(entry))){ ++ gtk_editable_set_position( GTK_EDITABLE(entry), entry->text_length); ++ } else { ++ gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1); ++ } ++ } else { ++ gtk_editable_set_position (GTK_EDITABLE (entry), tmp_pos); ++ } + + entry->in_drag = 0; + } +@@ -1822,6 +2018,13 @@ + } + } + ++ if (event->keyval == GDK_Return) ++ return FALSE; ++ if (event->keyval == GDK_KP_Enter) ++ g_signal_emit_by_name (G_OBJECT(gtk_widget_get_ancestor (widget, ++ GTK_TYPE_WINDOW)), "move-focus", ++ GTK_DIR_TAB_FORWARD); ++ + if (GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event)) + /* Activate key bindings + */ +@@ -1835,6 +2038,8 @@ + GdkEventKey *event) + { + GtkEntry *entry = GTK_ENTRY (widget); ++ ++ gtk_entry_update_scrolled_window( entry ); + + if (entry->editable) + { +@@ -1853,7 +2058,35 @@ + GdkEventFocus *event) + { + GtkEntry *entry = GTK_ENTRY (widget); +- ++ GtkEntryPrivate *priv; ++ ++ priv = GTK_ENTRY_GET_PRIVATE (widget); ++ /* Hildon : If the text doesn't fit the entry, upon focusing ++ * to an text field, move the caret to the end of the entry. ++ * Force the entry to recompute, otherwise it doesn't update ++ * if the cursor is currently at the end*/ ++ /* hildon : If the text has no selection and focus returned with ++ other means than pointer click, set cursor before first ++ character of the text, otherwise behave normally */ ++ ++ if (!entry->in_click) ++ { ++ /*gboolean has_selection; ++ has_selection = gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), NULL, NULL); ++ if (!has_selection) ++ { ++ gtk_editable_set_position (GTK_EDITABLE (entry), -1); ++ }*//*FIXME need a better hack here*/ ++ /* Hildon: If in SecretEditor mode highlight selection if entry got focus ++ * otherways than mouse/stylus */ ++ if (!entry->visible && priv->keep_focus) ++ { ++ gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1); ++ } ++ } ++ ++ gtk_entry_recompute (GTK_ENTRY (entry)); ++ + gtk_widget_queue_draw (widget); + + if (entry->editable) +@@ -1876,6 +2109,8 @@ + GdkEventFocus *event) + { + GtkEntry *entry = GTK_ENTRY (widget); ++ GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (widget); ++ guint tmp_pos; + GtkEntryCompletion *completion; + + gtk_widget_queue_draw (widget); +@@ -1886,6 +2121,20 @@ + gtk_im_context_focus_out (entry->im_context); + } + ++ tmp_pos = gtk_editable_get_position (GTK_EDITABLE (widget)); ++ if (priv->keep_focus){ ++ if (!entry->visible) ++ gtk_editable_set_position (GTK_EDITABLE (widget), tmp_pos); ++ priv->keep_focus = FALSE; ++ } ++ else { ++ if (priv->menu_popped) ++ priv->menu_popped = FALSE; ++ else gtk_editable_set_position (GTK_EDITABLE (widget), tmp_pos); ++ } ++ ++ gtk_widget_queue_draw(widget); ++ + gtk_entry_check_cursor_blink (entry); + + g_signal_handlers_disconnect_by_func (gdk_keymap_get_for_display (gtk_widget_get_display (widget)), +@@ -1902,7 +2151,6 @@ + static void + gtk_entry_grab_focus (GtkWidget *widget) + { +- GtkEntry *entry = GTK_ENTRY (widget); + gboolean select_on_focus; + + GTK_WIDGET_CLASS (parent_class)->grab_focus (widget); +@@ -1912,8 +2160,8 @@ + &select_on_focus, + NULL); + +- if (select_on_focus && entry->editable && !entry->in_click) +- gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1); ++/* Hildon : When focusing to an entry, it shouldn't become ++ * highlighted. */ + } + + static void +@@ -1987,7 +2235,7 @@ + + if (new_text_length > 63) + g_free (text); +- ++ gtk_entry_update_scrolled_window( entry ); + g_object_unref (editable); + } + +@@ -2074,7 +2322,7 @@ + if (end < 0) + end = entry->text_length; + +- gtk_entry_reset_im_context (entry); ++ /*gtk_entry_reset_im_context (entry);*//*FIXME tmp kludge, might break something*/ + + gtk_entry_set_positions (entry, + MIN (end, entry->text_length), +@@ -2168,13 +2416,19 @@ + { + gint index; + gint n_chars; ++ gboolean show_last_char = FALSE; + + GtkEntry *entry = GTK_ENTRY (editable); +- ++ GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (GTK_WIDGET (entry)); + if (new_text_length < 0) + new_text_length = strlen (new_text); + + n_chars = g_utf8_strlen (new_text, new_text_length); ++ ++ ++ gtk_widget_style_get (GTK_WIDGET (entry), "show-last-char", ++ &show_last_char, NULL); ++ + if (entry->text_max_length > 0 && n_chars + entry->text_length > entry->text_max_length) + { + gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (entry))); +@@ -2238,6 +2492,14 @@ + + if (entry->selection_bound > *position) + entry->selection_bound += n_chars; ++ ++ /* Hildon: store this addition IF it was only 1 char (user inputted) and we are currently in secret mode (invisible) */ ++ ++ if (show_last_char && n_chars == 1 && !entry->visible && (new_text_length < HILDON_EDITED_CHARACTER_MAX)) { ++ memset( &priv->hildon_edited_character, 0x00, HILDON_EDITED_CHARACTER_MAX ); ++ priv->hildon_edited_character_length = new_text_length; ++ memcpy( &priv->hildon_edited_character, new_text, new_text_length ); /* Guaranteed to be < total length */ ++ } + + *position += n_chars; + +@@ -2339,6 +2601,11 @@ + + gtk_entry_reset_im_context (entry); + ++ /* Hildon, if not visible set the position to the end */ ++ /* New SecretEditor specs say that with cursor should move ++ * With left/right arrows ++ */ ++ + if (entry->current_pos != entry->selection_bound && !extend_selection) + { + /* If we have a current selection and aren't extending it, move to the +@@ -2445,7 +2712,7 @@ + gint start_pos = entry->current_pos; + gint end_pos = entry->current_pos; + +- gtk_entry_reset_im_context (entry); ++ /* Hildon: code removed - backspace should not clear the word completion */ + + if (!entry->editable) + return; +@@ -2515,7 +2782,8 @@ + GtkEditable *editable = GTK_EDITABLE (entry); + gint prev_pos; + +- gtk_entry_reset_im_context (entry); ++/* gtk_entry_reset_im_context (entry); */ /*backspace should not clear ++ the word completion*/ + + if (!entry->editable || !entry->text) + return; +@@ -2883,21 +3151,28 @@ + ++i; + } + } +- ++ ++#define HILDON_EDITED_CHARACTER_MS 600 /* 0.6 seconds */ ++ + static PangoLayout * + gtk_entry_create_layout (GtkEntry *entry, + gboolean include_preedit) + { + GtkWidget *widget = GTK_WIDGET (entry); ++ GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry); + PangoLayout *layout = gtk_widget_create_pango_layout (widget, NULL); + PangoAttrList *tmp_attrs = pango_attr_list_new (); + + gchar *preedit_string = NULL; + gint preedit_length = 0; + PangoAttrList *preedit_attrs = NULL; ++ gboolean show_last_char = FALSE; + + pango_layout_set_single_paragraph_mode (layout, TRUE); + ++ gtk_widget_style_get (widget, "show-last-char", ++ &show_last_char, NULL); ++ + if (include_preedit) + { + gtk_im_context_get_preedit_string (entry->im_context, +@@ -3003,7 +3278,49 @@ + else + invisible_char = ' '; /* just pick a char */ + +- append_char (str, invisible_char, entry->text_length); ++ if (!show_last_char) ++ append_char (str, invisible_char, entry->text_length); ++ else if (show_last_char) ++ { ++ /* Hildon */ ++ if (priv->hildon_edited_character_length > 0) ++ { ++ ++ /* If we have an outstanding timeout, remove it, because the character it is set to hide ++ * is already hidden now. We do this first to prevent possible race conditions if the timout ++ * were to trigger while in here ++ */ ++ ++ if (priv->hildon_edited_character_timeout) ++ { ++ g_source_remove( priv->hildon_edited_character_timeout ); ++ priv->hildon_edited_character_timeout = FALSE; ++ } ++ ++ /* Draw the secret character length-1 times, because the last char will be visible */ ++ append_char (str, invisible_char, entry->text_length > 1 ? entry->text_length - 1 : 0); ++ ++ /* Add our visible char, the most recently inputted one */ ++ g_string_append_len (str, (char *)&priv->hildon_edited_character, priv->hildon_edited_character_length); ++ ++ /* Now remove this last inputted character, don't need it anymore */ ++ ++ memset( priv->hildon_edited_character, 0x00, HILDON_EDITED_CHARACTER_MAX ); ++ priv->hildon_edited_character_length = 0; ++ ++ priv->hildon_edited_character_timeout = g_timeout_add( HILDON_EDITED_CHARACTER_MS, (GSourceFunc) ++ hildon_remove_visible_character, entry ); ++ ++ } ++ else ++ { ++ /* No last character known. This could be for example because the application has filled ++ * in the password already. In that case we of course don't want to view it ++ */ ++ append_char (str, invisible_char, entry->text_length); ++ } ++ } ++ + pango_layout_set_text (layout, str->str, str->len); + g_string_free (str, TRUE); + } +@@ -3048,12 +3365,17 @@ + gint area_width, area_height; + gint y_pos; + PangoLayoutLine *line; +- ++ gint border_x, border_y; ++ ++ gtk_widget_style_get (GTK_WIDGET (entry), "horizontal-border", &border_x, ++ "vertical-border", &border_y, ++ NULL); ++ + layout = gtk_entry_ensure_layout (entry, TRUE); + + get_text_area_size (entry, NULL, NULL, &area_width, &area_height); + +- area_height = PANGO_SCALE * (area_height - 2 * INNER_BORDER); ++ area_height = PANGO_SCALE * (area_height - 2 * border_y); + + line = pango_layout_get_lines (layout)->data; + pango_layout_line_get_extents (line, NULL, &logical_rect); +@@ -3070,10 +3392,10 @@ + else if (y_pos + logical_rect.height > area_height) + y_pos = area_height - logical_rect.height; + +- y_pos = INNER_BORDER + y_pos / PANGO_SCALE; ++ y_pos = border_y + y_pos / PANGO_SCALE; + + if (x) +- *x = INNER_BORDER - entry->scroll_offset; ++ *x = border_x - entry->scroll_offset; + + if (y) + *y = y_pos; +@@ -3083,6 +3405,10 @@ + gtk_entry_draw_text (GtkEntry *entry) + { + GtkWidget *widget; ++ gint border_y, border_x; ++ ++ gtk_widget_style_get (GTK_WIDGET (entry), "horizontal-border", &border_x, ++ "vertical-border", &border_y, NULL); + + if (!entry->visible && entry->invisible_char == 0) + return; +@@ -3092,14 +3418,76 @@ + PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE); + gint x, y; + gint start_pos, end_pos; ++ GdkRectangle clip_rect; + + widget = GTK_WIDGET (entry); + + get_layout_position (entry, &x, &y); + ++ /* Use a clipping rectangle so that we always get enough empty space around ++ * the text. ++ */ ++ clip_rect.x = border_x; ++ clip_rect.y = 0; ++ ++ gdk_drawable_get_size (entry->text_area, &clip_rect.width, &clip_rect.height); ++ clip_rect.width -= border_x * 2; ++ ++ /*changes for Hildon ++ *Reduce the size of the clip rect, so that only full characters are displayed ++ */ ++ ++ /* NOTE: Commented out because it does not work with bidi text where ++the indexes are in random ++ * left-right or right-left order. Code causes Pango assert aborts. Because gtkentry itself ++ * is broken with regard to bidi anyway (bug #478) we ignore this requirement of the spec ++ * until gtkentry itself is fixed. (bug #477) ++ */ ++ ++ /* Better yet, let's enable this only when not in RTL mode */ ++ ++ /* Note: BUG #857. patched gtkentry crashed when pasting scalable fonts. This is pango problem ++ * and we tested patched gtkentry with pango version 1.3.2 and it appears to be fixed. Section is commented ++ out until we upgrade to new version of pango ++ if (gtk_widget_get_direction( entry ) != GTK_TEXT_DIR_RTL) ++ { ++ PangoRectangle char_rect; // used for getting character's onscreen pos ++ PangoLayoutIter *iter; // used to iterate over the text ++ ++ // get the position of the character currently at the clip border ++ iter = get_char_at_pos( layout, (clip_rect.x + clip_rect.width + entry->scroll_offset), 0 ); ++ if ( iter ) ++ { ++ // get the position of that character on the screen ++ pango_layout_iter_get_char_extents( iter, &char_rect ); ++ char_rect.x /= PANGO_SCALE; ++ char_rect.x -= entry->scroll_offset; ++ char_rect.width /= PANGO_SCALE; ++ ++ // if the ending position is > the clip rectangle, then the ++ // character is only partially visible, and we should ++ // clip the entire character. ++ ++ if ( char_rect.x + char_rect.width > clip_rect.x + clip_rect.width ) ++ { ++ clip_rect.width = char_rect.x; ++ } ++ ++ pango_layout_iter_free( iter ); ++ } ++ ++ } ++ */ ++ /******************************************************************/ ++ ++ gdk_gc_set_clip_rectangle (widget->style->text_gc [widget->state], &clip_rect); ++ + gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state], + x, y, + layout); ++ ++ gdk_gc_set_clip_rectangle (widget->style->text_gc [widget->state], NULL); ++ + + if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos)) + { +@@ -3128,7 +3516,7 @@ + { + GdkRectangle rect; + +- rect.x = INNER_BORDER - entry->scroll_offset + ranges[2 * i]; ++ rect.x = border_x - entry->scroll_offset + ranges[2 * i]; + rect.y = y; + rect.width = ranges[2 * i + 1]; + rect.height = logical_rect.height; +@@ -3177,14 +3565,18 @@ + { + GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (entry))); + PangoDirection keymap_direction = gdk_keymap_get_direction (keymap); ++ gint border_x, border_y; + ++ gtk_widget_style_get (GTK_WIDGET (entry), "horizontal-border", &border_x, ++ "vertical-border", &border_y, ++ NULL); + if (GTK_WIDGET_DRAWABLE (entry)) + { + GtkWidget *widget = GTK_WIDGET (entry); + GdkRectangle cursor_location; + gboolean split_cursor; + +- gint xoffset = INNER_BORDER - entry->scroll_offset; ++ gint xoffset = border_x - entry->scroll_offset; + gint strong_x, weak_x; + gint text_area_height; + PangoDirection dir1 = PANGO_DIRECTION_NEUTRAL; +@@ -3221,9 +3613,9 @@ + } + + cursor_location.x = xoffset + x1; +- cursor_location.y = INNER_BORDER; ++ cursor_location.y = border_y; + cursor_location.width = 0; +- cursor_location.height = text_area_height - 2 * INNER_BORDER ; ++ cursor_location.height = text_area_height - 2 * border_y; + + draw_insertion_cursor (entry, + &cursor_location, TRUE, dir1, +@@ -3249,11 +3641,8 @@ + static void + gtk_entry_reset_im_context (GtkEntry *entry) + { +- if (entry->need_im_reset) +- { +- entry->need_im_reset = 0; +- gtk_im_context_reset (entry->im_context); +- } ++ /* Hildon: We want reset to be sent more often */ ++ gtk_im_context_reset (entry->im_context); + } + + static gint +@@ -3266,8 +3655,12 @@ + gint pos; + gboolean trailing; + const gchar *text; +- gint cursor_index; +- ++ gint border_x, cursor_index; ++ ++ gtk_widget_style_get (GTK_WIDGET (entry), "horizontal-border", &border_x, ++ NULL); ++ x -= border_x; ++ + layout = gtk_entry_ensure_layout (entry, TRUE); + text = pango_layout_get_text (layout); + cursor_index = g_utf8_offset_to_pointer (text, entry->current_pos) - text; +@@ -3355,12 +3748,17 @@ + PangoLayout *layout; + PangoLayoutLine *line; + PangoRectangle logical_rect; ++ gint border_x, border_y; ++ ++ gtk_widget_style_get (GTK_WIDGET (entry), "horizontal-border", &border_x, ++ "vertical-border", &border_y, ++ NULL); + + if (!GTK_WIDGET_REALIZED (entry)) + return; + + gdk_drawable_get_size (entry->text_area, &text_area_width, NULL); +- text_area_width -= 2 * INNER_BORDER; ++ text_area_width -= 2 * border_x; + + layout = gtk_entry_ensure_layout (entry, TRUE); + line = pango_layout_get_lines (layout)->data; +@@ -3390,13 +3788,13 @@ + entry->scroll_offset = CLAMP (entry->scroll_offset, min_offset, max_offset); + + /* And make sure cursors are on screen. Note that the cursor is +- * actually drawn one pixel into the INNER_BORDER space on ++ * actually drawn one pixel into the border_x space on + * the right, when the scroll is at the utmost right. This + * looks better to to me than confining the cursor inside the + * border entirely, though it means that the cursor gets one + * pixel closer to the edge of the widget on the right than + * on the left. This might need changing if one changed +- * INNER_BORDER from 2 to 1, as one would do on a ++ * border_x from 2 to 1, as one would do on a + * small-screen-real-estate display. + * + * We always make sure that the strong cursor is on screen, and +@@ -3430,6 +3828,52 @@ + entry->scroll_offset += weak_xoffset - text_area_width; + } + ++ /*Changes for Hildon ++ * now we make it so that if a character is partially visible, ++ * then we also scroll that off the screen. ++ */ ++ ++ /* NOTE: Commented out because it does not work with bidi text where the indexes are in random ++ * left-right or right-left order. Code causes Pango assert aborts. Because gtkentry itself ++ * is broken with regard to bidi anyway (bug #478) we ignore this requirement of the spec ++ * until gtkentry itself is fixed. (bug #477) ++ */ ++ ++ /* Better yet, let's disable this (for now) only when using RTL text */ ++ ++/*Note: BUG #857. patched gtkentry crashed when pasting scalable fonts. This is pango problem ++ * and we tested patched gtkentry with pango version 1.3.2 and it appears to be fixed. Section is comment ed out until we upgrade to new version of pango ++ if (gtk_widget_get_direction( entry ) != GTK_TEXT_DIR_RTL) ++ { ++ PangoLayoutIter *iter = get_char_at_pos( layout, entry->scroll_offset, 0 ); ++ // if we found the char we were looking for ++ if ( iter ) ++ { ++ PangoRectangle char_rect; // used for getting character's onscreen pos ++ ++ // get the position of that character on the screen ++ pango_layout_iter_get_char_extents( iter, &char_rect ); ++ char_rect.x /= PANGO_SCALE; ++ ++ // if the starting position is < the current scroll offset, then the ++ // character is only partially visible, and we should scroll to the ++ // start of the next character instead ++ ++ if ( char_rect.x < entry->scroll_offset ) ++ { ++ if ( pango_layout_iter_next_char( iter ) ) ++ { ++ pango_layout_iter_get_char_extents( iter, &char_rect); ++ entry->scroll_offset = char_rect.x / PANGO_SCALE; ++ } ++ } ++ ++ pango_layout_iter_free( iter ); ++ } ++ ++ ++ }*/ ++ + g_object_notify (G_OBJECT (entry), "scroll_offset"); + } + +@@ -3552,8 +3996,9 @@ + pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs); + + /* Find the next word end */ ++ /*Hildon: cursor should seek to the start of the next word*/ + new_pos++; +- while (new_pos < n_attrs && !log_attrs[new_pos].is_word_end) ++ while (new_pos < n_attrs && !log_attrs[new_pos].is_word_start) + new_pos++; + + g_free (log_attrs); +@@ -3648,14 +4093,9 @@ + + if (entry->visible) + return gtk_editable_get_chars (GTK_EDITABLE (entry), start, end); +- else if (!entry->invisible_char) ++ /*Hildon: when not visible, no chars are public*/ ++ else + return g_strdup (""); +- else +- { +- GString *str = g_string_new (NULL); +- append_char (str, entry->invisible_char, end - start); +- return g_string_free (str, FALSE); +- } + } + + static void +@@ -3678,9 +4118,12 @@ + + if (text) + { +- gint pos, start, end; ++ gint pos, start, end, index; + GtkEntryCompletion *completion = gtk_entry_get_completion (entry); + ++ /* when pasting multiline text, ignore everything but the first line */ ++ for (index = 0; text[index] != 0 && text[index] != '\n'; index++); ++ + if (completion) + { + g_signal_handler_block (entry, completion->priv->changed_id); +@@ -3692,7 +4135,7 @@ + gtk_editable_delete_text (editable, start, end); + + pos = entry->current_pos; +- gtk_editable_insert_text (editable, text, -1, &pos); ++ gtk_editable_insert_text (editable, text, index, &pos); + gtk_editable_set_position (editable, pos); + + if (completion) +@@ -3888,6 +4331,7 @@ + { + g_return_if_fail (GTK_IS_ENTRY (entry)); + ++ g_object_set(G_OBJECT(entry->im_context), "visibility", visible, NULL); + entry->visible = visible ? TRUE : FALSE; + g_object_notify (G_OBJECT (entry), "visibility"); + gtk_entry_recompute (entry); +@@ -4569,6 +5013,7 @@ + GdkEventButton *event) + { + PopupInfo *info = g_new (PopupInfo, 1); ++ GtkEntryPrivate *priv; + + /* In order to know what entries we should make sensitive, we + * ask for the current targets of the clipboard, and when +@@ -4576,6 +5021,8 @@ + */ + info->entry = g_object_ref (entry); + ++ priv = GTK_ENTRY_GET_PRIVATE (entry); ++ + if (event) + { + info->button = event->button; +@@ -4591,6 +5038,8 @@ + gdk_atom_intern ("TARGETS", FALSE), + popup_targets_received, + info); ++ ++ priv->menu_popped = TRUE; + } + + static gboolean +@@ -5389,3 +5838,156 @@ + + return completion; + } ++ ++static PangoLayoutIter *get_char_at_pos( PangoLayout *layout, gint x, gint y ) ++{ ++ gint index = 0; /*the index of the first character */ ++ gint trailing = 0; /*not used*/ ++ PangoLayoutIter *iter; /*used to iterate over the text*/ ++ gboolean valid_char = TRUE; ++ ++ /*get the position of the character currently at the scroll offset*/ ++ pango_layout_xy_to_index( layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing ); ++ iter = pango_layout_get_iter( layout ); ++ ++ /*iterate until we get to the character at the same index*/ ++ while ( valid_char && pango_layout_iter_get_index( iter ) != index ) ++ { ++ valid_char = pango_layout_iter_next_char( iter ); ++ } ++ ++ if ( valid_char == FALSE ) ++ iter = NULL; ++ ++ return iter; ++} ++ ++static void gtk_entry_update_scrolled_window( GtkEntry *entry) ++{ ++ GtkWidget *parent; ++ GtkWidget *widget; ++ GtkWidget *direct_parent = NULL; ++ GtkScrolledWindow *sw = NULL; ++ gboolean need_update = FALSE; ++ GtkAdjustment *vadjustment; ++ gdouble value; ++ ++ widget = parent = GTK_WIDGET(entry); ++ if(parent->parent != NULL) ++ direct_parent = parent->parent; ++ while(parent && !GTK_WIDGET_TOPLEVEL(parent)) ++ { ++ if(GTK_IS_SCROLLED_WINDOW(parent)) ++ { ++ need_update = TRUE; ++ sw = GTK_SCROLLED_WINDOW(parent); ++ break; ++ } ++ parent = parent->parent; ++ } ++ ++ if(need_update) ++ { ++ gint x=0, y=0; ++ vadjustment = gtk_scrolled_window_get_vadjustment(sw); ++ value = gtk_adjustment_get_value(vadjustment); ++ ++ if(direct_parent != NULL) ++ gtk_widget_translate_coordinates( direct_parent, parent, ++ widget->allocation.x, widget->allocation.y, &x, &y ); ++ ++ if( (gdouble) y < 0 ) ++ { ++ value = value + (gdouble) y; ++ if (value < vadjustment->lower) ++ value = vadjustment->lower; ++ } ++ else if( (gdouble )y + widget->allocation.height > vadjustment->page_size) ++ { ++ value = value + (gdouble)y + widget->allocation.height ++ - vadjustment->page_size; ++ if(value > vadjustment->upper - vadjustment->page_size) ++ value = vadjustment->upper - vadjustment->page_size; ++ } ++ gtk_adjustment_set_value(vadjustment, value); ++ gtk_scrolled_window_set_vadjustment(sw, GTK_ADJUSTMENT(vadjustment)); ++ } ++} ++ ++/* ++ * gtk_entry_set_autocap: ++ * @entry: a #GtkEntry ++ * @autocap: autocap ++ * ++ * Sets autocapitalization of the widget. ++ */ ++static void ++gtk_entry_set_autocap (GtkEntry *entry, ++ gboolean autocap) ++{ ++ g_return_if_fail (GTK_IS_ENTRY (entry)); ++ ++ if (gtk_entry_get_autocap (entry) != autocap) ++ { ++ g_object_set (G_OBJECT (entry->im_context), "autocap", autocap, NULL); ++ g_object_notify (G_OBJECT (entry), "autocap"); ++ } ++} ++ ++/* ++ * gtk_entry_get_autocap: ++ * @entry: a #GtkEntry ++ * ++ * Gets autocapitalization state of the widget. ++ * ++ * Return value: a state ++ */ ++static gboolean ++gtk_entry_get_autocap (GtkEntry *entry) ++{ ++ gboolean autocap; ++ g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE); ++ ++ g_object_get (G_OBJECT (entry->im_context), "autocap", &autocap, NULL); ++ ++ return autocap; ++} ++ ++/* ++ * gtk_entry_set_input_mode: ++ * @entry: a #GtkEntry ++ * @autocap: input mode ++ * ++ * Sets autocapitalization of the widget. ++ */ ++static void ++gtk_entry_set_input_mode (GtkEntry *entry, ++ gint mode) ++{ ++ g_return_if_fail (GTK_IS_ENTRY (entry)); ++ ++ if (gtk_entry_get_input_mode (entry) != mode) ++ { ++ g_object_set (G_OBJECT (entry->im_context), "input_mode", mode, NULL); ++ g_object_notify (G_OBJECT (entry), "input_mode"); ++ } ++} ++ ++/* ++ * gtk_entry_get_input_mode: ++ * @entry: a #GtkEntry ++ * ++ * Gets input mode of the widget. ++ * ++ * Return value: input mode ++ */ ++static gint ++gtk_entry_get_input_mode (GtkEntry *entry) ++{ ++ gint mode; ++ g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE); ++ ++ g_object_get (G_OBJECT (entry->im_context), "input_mode", &mode, NULL); ++ ++ return mode; ++} |