diff options
Diffstat (limited to 'meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff')
-rw-r--r-- | meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff | 1308 |
1 files changed, 1308 insertions, 0 deletions
diff --git a/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff b/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff new file mode 100644 index 0000000000..fae911305c --- /dev/null +++ b/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff | |||
@@ -0,0 +1,1308 @@ | |||
1 | --- gtk+-2.6.4/gtk/gtkentry.c 2005-02-04 17:36:02.000000000 +0200 | ||
2 | +++ gtk+-2.6.4/gtk/gtkentry.c 2005-04-06 16:19:36.466994536 +0300 | ||
3 | @@ -24,6 +24,10 @@ | ||
4 | * GTK+ at ftp://ftp.gtk.org/pub/gtk/. | ||
5 | */ | ||
6 | |||
7 | + /* Modified for Nokia Oyj during 2002-2003. See CHANGES file for list | ||
8 | + * of changes. | ||
9 | + */ | ||
10 | + | ||
11 | #include <config.h> | ||
12 | #include <string.h> | ||
13 | |||
14 | @@ -53,6 +57,7 @@ | ||
15 | #include "gtktreeselection.h" | ||
16 | #include "gtkentryprivate.h" | ||
17 | #include "gtkcelllayout.h" | ||
18 | +#include "gtkscrolledwindow.h" | ||
19 | |||
20 | #define GTK_ENTRY_COMPLETION_KEY "gtk-entry-completion-key" | ||
21 | |||
22 | @@ -60,6 +65,8 @@ | ||
23 | #define DRAW_TIMEOUT 20 | ||
24 | #define INNER_BORDER 2 | ||
25 | #define COMPLETION_TIMEOUT 300 | ||
26 | +#define HILDON_EDITED_CHARACTER_MAX 8 | ||
27 | +#define HILDON_EDITED_CHARACTER_MS 600 /* 0.6 seconds */ | ||
28 | |||
29 | /* Initial size of buffer, in bytes */ | ||
30 | #define MIN_SIZE 16 | ||
31 | @@ -75,6 +82,18 @@ | ||
32 | { | ||
33 | gfloat xalign; | ||
34 | gint insert_pos; | ||
35 | + /* Hildon additions: | ||
36 | + * following variables are needed | ||
37 | + * for Hildon password 'preview' | ||
38 | + * functionality; last inputted character | ||
39 | + * is showed for defined period, before it is | ||
40 | + * rendered to '*' | ||
41 | + */ | ||
42 | + gchar hildon_edited_character[HILDON_EDITED_CHARACTER_MAX]; | ||
43 | + gboolean hildon_edited_character_timeout; | ||
44 | + gint hildon_edited_character_length; | ||
45 | + gboolean keep_focus; | ||
46 | + gboolean menu_popped; | ||
47 | }; | ||
48 | |||
49 | enum { | ||
50 | @@ -104,7 +123,9 @@ | ||
51 | PROP_WIDTH_CHARS, | ||
52 | PROP_SCROLL_OFFSET, | ||
53 | PROP_TEXT, | ||
54 | - PROP_XALIGN | ||
55 | + PROP_XALIGN, | ||
56 | + PROP_AUTOCAP, | ||
57 | + PROP_INPUT_MODE | ||
58 | }; | ||
59 | |||
60 | static guint signals[LAST_SIGNAL] = { 0 }; | ||
61 | @@ -324,6 +345,23 @@ | ||
62 | gint *y, | ||
63 | gint *width, | ||
64 | gint *height); | ||
65 | +static void gtk_entry_update_scrolled_window (GtkEntry *entry); | ||
66 | +static void gtk_entry_set_autocap (GtkEntry *entry, | ||
67 | + gboolean autocap); | ||
68 | +static gboolean gtk_entry_get_autocap (GtkEntry *entry); | ||
69 | +static void gtk_entry_set_input_mode (GtkEntry *entry, | ||
70 | + gboolean mode); | ||
71 | +static gint gtk_entry_get_input_mode (GtkEntry *entry); | ||
72 | + | ||
73 | +/*Change for Hildon | ||
74 | + *returns an iterator to the character at position x,y of the | ||
75 | + *layout | ||
76 | + *returns NULL if no iterator was found at that position | ||
77 | + *Caller must call pango_layout_free_iter on the returned iterator | ||
78 | + */ | ||
79 | +static PangoLayoutIter *get_char_at_pos( PangoLayout *layout, gint x, gint y ); | ||
80 | + | ||
81 | +static gboolean hildon_remove_visible_character( gpointer data ); | ||
82 | |||
83 | /* Completion */ | ||
84 | static gint gtk_entry_completion_timeout (gpointer data); | ||
85 | @@ -523,7 +561,25 @@ | ||
86 | P_("FALSE displays the \"invisible char\" instead of the actual text (password mode)"), | ||
87 | TRUE, | ||
88 | G_PARAM_READABLE | G_PARAM_WRITABLE)); | ||
89 | - | ||
90 | + | ||
91 | + g_object_class_install_property (gobject_class, | ||
92 | + PROP_AUTOCAP, | ||
93 | + g_param_spec_boolean ("autocap", | ||
94 | + P_("auto capitalization"), | ||
95 | + P_("Enable autocap support"), | ||
96 | + TRUE, | ||
97 | + G_PARAM_READABLE | G_PARAM_WRITABLE)); | ||
98 | + | ||
99 | + g_object_class_install_property (gobject_class, | ||
100 | + PROP_INPUT_MODE, | ||
101 | + g_param_spec_int ("input_mode", | ||
102 | + P_("input mode"), | ||
103 | + P_("Define widget's input mode"), | ||
104 | + 0, | ||
105 | + 9, /* keep me updated */ | ||
106 | + 0, | ||
107 | + G_PARAM_READABLE | G_PARAM_WRITABLE)); | ||
108 | + | ||
109 | g_object_class_install_property (gobject_class, | ||
110 | PROP_HAS_FRAME, | ||
111 | g_param_spec_boolean ("has_frame", | ||
112 | @@ -593,6 +649,40 @@ | ||
113 | 0.0, | ||
114 | G_PARAM_READABLE | G_PARAM_WRITABLE)); | ||
115 | |||
116 | + gtk_widget_class_install_style_property (widget_class, | ||
117 | + g_param_spec_int ("horizontal-border", | ||
118 | + P_("Horizontal borders for entry"), | ||
119 | + P_("Set left/right borders"), | ||
120 | + 0, | ||
121 | + G_MAXINT, | ||
122 | + INNER_BORDER, | ||
123 | + G_PARAM_READWRITE)); | ||
124 | + | ||
125 | + gtk_widget_class_install_style_property (widget_class, | ||
126 | + g_param_spec_int ("vertical-border", | ||
127 | + P_("Vertical borders for entry"), | ||
128 | + P_("Set top/bottom borders"), | ||
129 | + 0, | ||
130 | + G_MAXINT, | ||
131 | + INNER_BORDER, | ||
132 | + G_PARAM_READWRITE)); | ||
133 | + | ||
134 | + gtk_widget_class_install_style_property (widget_class, | ||
135 | + g_param_spec_int ("icon-width", | ||
136 | + P_("Icon Width"), | ||
137 | + P_("Size of the purpose icon."), | ||
138 | + 0, | ||
139 | + G_MAXINT, | ||
140 | + 0, | ||
141 | + G_PARAM_READWRITE)); | ||
142 | + | ||
143 | + gtk_widget_class_install_style_property (widget_class, | ||
144 | + g_param_spec_boolean ("show-last-char", | ||
145 | + P_("Show last char in invisible mode for a while"), | ||
146 | + P_("Last char is shown before it is rendered to asterisk"), | ||
147 | + FALSE, | ||
148 | + G_PARAM_READABLE | G_PARAM_WRITABLE)); | ||
149 | + | ||
150 | signals[POPULATE_POPUP] = | ||
151 | g_signal_new ("populate_popup", | ||
152 | G_OBJECT_CLASS_TYPE (gobject_class), | ||
153 | @@ -853,6 +943,22 @@ | ||
154 | iface->start_editing = gtk_entry_start_editing; | ||
155 | } | ||
156 | |||
157 | +/* HILDON: Timed function to hide the most recently inputted character in password mode | ||
158 | +*/ | ||
159 | +static gboolean | ||
160 | + hildon_remove_visible_character( gpointer data ) | ||
161 | +{ | ||
162 | + g_return_val_if_fail (GTK_IS_WIDGET (data), FALSE); | ||
163 | + | ||
164 | + GtkEntry * entry = GTK_ENTRY( data ); | ||
165 | + | ||
166 | + /* Force the string to redrawn, but now without a visible character */ | ||
167 | + gtk_entry_recompute( entry ); | ||
168 | + | ||
169 | + /* Return false so this timeout is not called again and destroyed */ | ||
170 | + return FALSE; | ||
171 | +} | ||
172 | + | ||
173 | static void | ||
174 | gtk_entry_set_property (GObject *object, | ||
175 | guint prop_id, | ||
176 | @@ -867,9 +973,10 @@ | ||
177 | { | ||
178 | gboolean new_value = g_value_get_boolean (value); | ||
179 | |||
180 | + gtk_widget_set_sensitive( GTK_WIDGET( entry ), entry->editable ); | ||
181 | if (new_value != entry->editable) | ||
182 | { | ||
183 | - if (!new_value) | ||
184 | + if (!new_value) | ||
185 | { | ||
186 | gtk_entry_reset_im_context (entry); | ||
187 | if (GTK_WIDGET_HAS_FOCUS (entry)) | ||
188 | @@ -896,6 +1003,14 @@ | ||
189 | case PROP_VISIBILITY: | ||
190 | gtk_entry_set_visibility (entry, g_value_get_boolean (value)); | ||
191 | break; | ||
192 | + | ||
193 | + case PROP_AUTOCAP: | ||
194 | + gtk_entry_set_autocap (entry, g_value_get_boolean (value)); | ||
195 | + break; | ||
196 | + | ||
197 | + case PROP_INPUT_MODE: | ||
198 | + gtk_entry_set_input_mode (entry, g_value_get_int (value)); | ||
199 | + break; | ||
200 | |||
201 | case PROP_HAS_FRAME: | ||
202 | gtk_entry_set_has_frame (entry, g_value_get_boolean (value)); | ||
203 | @@ -954,6 +1069,12 @@ | ||
204 | case PROP_VISIBILITY: | ||
205 | g_value_set_boolean (value, entry->visible); | ||
206 | break; | ||
207 | + case PROP_AUTOCAP: | ||
208 | + g_value_set_boolean (value, gtk_entry_get_autocap (entry)); | ||
209 | + break; | ||
210 | + case PROP_INPUT_MODE: | ||
211 | + g_value_set_int (value, gtk_entry_get_input_mode (entry)); | ||
212 | + break; | ||
213 | case PROP_HAS_FRAME: | ||
214 | g_value_set_boolean (value, entry->has_frame); | ||
215 | break; | ||
216 | @@ -1000,7 +1121,20 @@ | ||
217 | entry->width_chars = -1; | ||
218 | entry->is_cell_renderer = FALSE; | ||
219 | entry->editing_canceled = FALSE; | ||
220 | - entry->has_frame = TRUE; | ||
221 | +#ifdef HILDON_SINGLE_LINE_EDITOR | ||
222 | + entry->has_frame = FALSE; | ||
223 | +#else | ||
224 | + entry->has_frame = TRUE; | ||
225 | +#endif | ||
226 | + | ||
227 | + /* Hildon */ | ||
228 | + memset( &priv->hildon_edited_character, 0x00, HILDON_EDITED_CHARACTER_MAX ); | ||
229 | + priv->hildon_edited_character_length = 0; | ||
230 | + priv->hildon_edited_character_timeout = FALSE; | ||
231 | + | ||
232 | + priv->keep_focus = FALSE; | ||
233 | + priv->menu_popped = FALSE; | ||
234 | + | ||
235 | priv->xalign = 0.0; | ||
236 | |||
237 | gtk_drag_dest_set (GTK_WIDGET (entry), | ||
238 | @@ -1013,6 +1147,10 @@ | ||
239 | * to it; so we create it here and destroy it in finalize(). | ||
240 | */ | ||
241 | entry->im_context = gtk_im_multicontext_new (); | ||
242 | + /* Set default stuff. */ | ||
243 | + gtk_entry_set_autocap (entry, TRUE); | ||
244 | + gtk_entry_set_input_mode (entry, 0); /* alpha-numeric-special */ | ||
245 | + g_object_set (G_OBJECT (entry->im_context), "use-show-hide", TRUE, NULL); | ||
246 | |||
247 | g_signal_connect (entry->im_context, "commit", | ||
248 | G_CALLBACK (gtk_entry_commit_cb), entry); | ||
249 | @@ -1058,7 +1196,8 @@ | ||
250 | gtk_entry_finalize (GObject *object) | ||
251 | { | ||
252 | GtkEntry *entry = GTK_ENTRY (object); | ||
253 | - | ||
254 | + GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (GTK_WIDGET (entry)); | ||
255 | + | ||
256 | gtk_entry_set_completion (entry, NULL); | ||
257 | |||
258 | if (entry->cached_layout) | ||
259 | @@ -1072,6 +1211,9 @@ | ||
260 | if (entry->recompute_idle) | ||
261 | g_source_remove (entry->recompute_idle); | ||
262 | |||
263 | + if (priv->hildon_edited_character_timeout) | ||
264 | + g_source_remove (priv->hildon_edited_character_timeout); | ||
265 | + | ||
266 | entry->text_size = 0; | ||
267 | |||
268 | if (entry->text) | ||
269 | @@ -1213,7 +1355,14 @@ | ||
270 | PangoFontMetrics *metrics; | ||
271 | gint xborder, yborder; | ||
272 | PangoContext *context; | ||
273 | - | ||
274 | + gint border_x, border_y; | ||
275 | + gint icon_width; | ||
276 | + | ||
277 | + gtk_widget_style_get (widget, | ||
278 | + "horizontal-border", &border_x, | ||
279 | + "vertical-border", &border_y, | ||
280 | + "icon-width", &icon_width, NULL); | ||
281 | + | ||
282 | gtk_widget_ensure_style (widget); | ||
283 | context = gtk_widget_get_pango_context (widget); | ||
284 | metrics = pango_context_get_metrics (context, | ||
285 | @@ -1225,21 +1374,22 @@ | ||
286 | |||
287 | _gtk_entry_get_borders (entry, &xborder, &yborder); | ||
288 | |||
289 | - xborder += INNER_BORDER; | ||
290 | - yborder += INNER_BORDER; | ||
291 | + xborder += border_x<<1; | ||
292 | + yborder += border_y<<1; | ||
293 | |||
294 | if (entry->width_chars < 0) | ||
295 | - requisition->width = MIN_ENTRY_WIDTH + xborder * 2; | ||
296 | + requisition->width = MIN_ENTRY_WIDTH + xborder; | ||
297 | else | ||
298 | { | ||
299 | gint char_width = pango_font_metrics_get_approximate_char_width (metrics); | ||
300 | gint digit_width = pango_font_metrics_get_approximate_digit_width (metrics); | ||
301 | gint char_pixels = (MAX (char_width, digit_width) + PANGO_SCALE - 1) / PANGO_SCALE; | ||
302 | |||
303 | - requisition->width = char_pixels * entry->width_chars + xborder * 2; | ||
304 | + requisition->width = char_pixels * entry->width_chars + xborder; | ||
305 | } | ||
306 | - | ||
307 | - requisition->height = PANGO_PIXELS (entry->ascent + entry->descent) + yborder * 2; | ||
308 | + | ||
309 | + requisition->width += icon_width; | ||
310 | + requisition->height = PANGO_PIXELS (entry->ascent + entry->descent) + yborder; | ||
311 | |||
312 | pango_font_metrics_unref (metrics); | ||
313 | } | ||
314 | @@ -1253,23 +1403,39 @@ | ||
315 | { | ||
316 | gint xborder, yborder; | ||
317 | GtkRequisition requisition; | ||
318 | + gint icon_width; | ||
319 | GtkWidget *widget = GTK_WIDGET (entry); | ||
320 | |||
321 | + gtk_widget_style_get (widget, "icon-width", &icon_width, NULL); | ||
322 | + | ||
323 | gtk_widget_get_child_requisition (widget, &requisition); | ||
324 | |||
325 | _gtk_entry_get_borders (entry, &xborder, &yborder); | ||
326 | |||
327 | if (x) | ||
328 | - *x = xborder; | ||
329 | + *x = xborder + icon_width; | ||
330 | |||
331 | if (y) | ||
332 | + { | ||
333 | *y = yborder; | ||
334 | + if( widget->allocation.height < requisition.height ) | ||
335 | + *y += ((widget->allocation.height - requisition.height) / 2); | ||
336 | + if( *y < yborder ) | ||
337 | + *y = yborder; | ||
338 | + } | ||
339 | |||
340 | if (width) | ||
341 | - *width = GTK_WIDGET (entry)->allocation.width - xborder * 2; | ||
342 | + *width = GTK_WIDGET (entry)->allocation.width - xborder * 2 - icon_width; | ||
343 | |||
344 | if (height) | ||
345 | - *height = requisition.height - yborder * 2; | ||
346 | + { | ||
347 | + if( widget->allocation.height < requisition.height ) | ||
348 | + *height = widget->allocation.height - yborder * 2; | ||
349 | + else | ||
350 | + *height = widget->requisition.height - yborder * 2; | ||
351 | + if( *height <=0 ) | ||
352 | + *height = 1; | ||
353 | + } | ||
354 | } | ||
355 | |||
356 | static void | ||
357 | @@ -1289,10 +1455,9 @@ | ||
358 | |||
359 | if (y) | ||
360 | { | ||
361 | - if (entry->is_cell_renderer) | ||
362 | - *y = widget->allocation.y; | ||
363 | - else | ||
364 | - *y = widget->allocation.y + (widget->allocation.height - requisition.height) / 2; | ||
365 | + *y = widget->allocation.y; | ||
366 | + if( widget->allocation.height > requisition.height ) | ||
367 | + *y += ((widget->allocation.height - requisition.height) / 2); | ||
368 | } | ||
369 | |||
370 | if (width) | ||
371 | @@ -1300,10 +1465,10 @@ | ||
372 | |||
373 | if (height) | ||
374 | { | ||
375 | - if (entry->is_cell_renderer) | ||
376 | - *height = widget->allocation.height; | ||
377 | - else | ||
378 | + if( widget->allocation.height > requisition.height ) | ||
379 | *height = requisition.height; | ||
380 | + else | ||
381 | + *height = widget->allocation.height; | ||
382 | } | ||
383 | } | ||
384 | |||
385 | @@ -1383,20 +1548,19 @@ | ||
386 | GdkEventExpose *event) | ||
387 | { | ||
388 | GtkEntry *entry = GTK_ENTRY (widget); | ||
389 | + gint area_width, area_height; | ||
390 | + | ||
391 | + get_widget_window_size (entry, NULL, NULL, &area_width, &area_height); | ||
392 | |||
393 | if (widget->window == event->window) | ||
394 | - gtk_entry_draw_frame (widget); | ||
395 | + { | ||
396 | + gtk_paint_box (widget->style, widget->window, | ||
397 | + GTK_WIDGET_STATE (widget), GTK_SHADOW_NONE, | ||
398 | + NULL, widget, "entry_frame", | ||
399 | + 0, 0, area_width, area_height); | ||
400 | + } | ||
401 | else if (entry->text_area == event->window) | ||
402 | { | ||
403 | - gint area_width, area_height; | ||
404 | - | ||
405 | - get_text_area_size (entry, NULL, NULL, &area_width, &area_height); | ||
406 | - | ||
407 | - gtk_paint_flat_box (widget->style, entry->text_area, | ||
408 | - GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE, | ||
409 | - NULL, widget, "entry_bg", | ||
410 | - 0, 0, area_width, area_height); | ||
411 | - | ||
412 | if ((entry->visible || entry->invisible_char != 0) && | ||
413 | GTK_WIDGET_HAS_FOCUS (widget) && | ||
414 | entry->selection_bound == entry->current_pos && entry->cursor_visible) | ||
415 | @@ -1490,16 +1654,19 @@ | ||
416 | return FALSE; | ||
417 | |||
418 | entry->button = event->button; | ||
419 | - | ||
420 | + | ||
421 | if (!GTK_WIDGET_HAS_FOCUS (widget)) | ||
422 | { | ||
423 | entry->in_click = TRUE; | ||
424 | gtk_widget_grab_focus (widget); | ||
425 | entry->in_click = FALSE; | ||
426 | } | ||
427 | - | ||
428 | + | ||
429 | + /* Hildon: we need to reset IM context so pre-edit string can be committed */ | ||
430 | + gtk_entry_reset_im_context (entry); | ||
431 | + | ||
432 | tmp_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset); | ||
433 | - | ||
434 | + | ||
435 | if (event->button == 1) | ||
436 | { | ||
437 | gboolean have_selection = gtk_editable_get_selection_bounds (editable, &sel_start, &sel_end); | ||
438 | @@ -1509,8 +1676,6 @@ | ||
439 | |||
440 | if (event->state & GDK_SHIFT_MASK) | ||
441 | { | ||
442 | - gtk_entry_reset_im_context (entry); | ||
443 | - | ||
444 | if (!have_selection) /* select from the current position to the clicked position */ | ||
445 | sel_start = sel_end = entry->current_pos; | ||
446 | |||
447 | @@ -1575,9 +1740,20 @@ | ||
448 | entry->drag_start_x = event->x + entry->scroll_offset; | ||
449 | entry->drag_start_y = event->y + entry->scroll_offset; | ||
450 | } | ||
451 | - else | ||
452 | - gtk_editable_set_position (editable, tmp_pos); | ||
453 | - break; | ||
454 | + else { | ||
455 | + /* HILDON: do not move the cursor inside the textarea if invisible | ||
456 | + * as per the specifications */ | ||
457 | + if (!entry->visible) | ||
458 | + if(tmp_pos == strlen(gtk_entry_get_text(entry))){ | ||
459 | + gtk_editable_set_position( editable, entry->text_length); | ||
460 | + } else { | ||
461 | + gtk_editable_select_region (editable, 0, -1); | ||
462 | + } | ||
463 | + else | ||
464 | + gtk_editable_set_position (editable, tmp_pos); | ||
465 | + } | ||
466 | + | ||
467 | + break; | ||
468 | |||
469 | case GDK_2BUTTON_PRESS: | ||
470 | /* We ALWAYS receive a GDK_BUTTON_PRESS immediately before | ||
471 | @@ -1614,8 +1790,16 @@ | ||
472 | } | ||
473 | else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) | ||
474 | { | ||
475 | + /* Hildon: if we are in password mode selection and Cut & Copy should | ||
476 | + be disabled. */ | ||
477 | + if (!entry->visible) | ||
478 | + { | ||
479 | + gtk_editable_set_position (GTK_EDITABLE(entry), 0); | ||
480 | + } | ||
481 | + | ||
482 | gtk_entry_do_popup (entry, event); | ||
483 | entry->button = 0; /* Don't wait for release, since the menu will gtk_grab_add */ | ||
484 | + priv->keep_focus = TRUE; | ||
485 | |||
486 | return TRUE; | ||
487 | } | ||
488 | @@ -1632,11 +1816,23 @@ | ||
489 | if (event->window != entry->text_area || entry->button != event->button) | ||
490 | return FALSE; | ||
491 | |||
492 | + if (entry->editable) | ||
493 | + gtk_im_context_show (entry->im_context); | ||
494 | + | ||
495 | if (entry->in_drag) | ||
496 | { | ||
497 | gint tmp_pos = gtk_entry_find_position (entry, entry->drag_start_x); | ||
498 | |||
499 | - gtk_editable_set_position (GTK_EDITABLE (entry), tmp_pos); | ||
500 | + /* HILDON: If not visible, do not allow cursor to be positioned inside the string */ | ||
501 | + if (!entry->visible){ | ||
502 | + if(tmp_pos == strlen(gtk_entry_get_text(entry))){ | ||
503 | + gtk_editable_set_position( GTK_EDITABLE(entry), entry->text_length); | ||
504 | + } else { | ||
505 | + gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1); | ||
506 | + } | ||
507 | + } else { | ||
508 | + gtk_editable_set_position (GTK_EDITABLE (entry), tmp_pos); | ||
509 | + } | ||
510 | |||
511 | entry->in_drag = 0; | ||
512 | } | ||
513 | @@ -1822,6 +2018,13 @@ | ||
514 | } | ||
515 | } | ||
516 | |||
517 | + if (event->keyval == GDK_Return) | ||
518 | + return FALSE; | ||
519 | + if (event->keyval == GDK_KP_Enter) | ||
520 | + g_signal_emit_by_name (G_OBJECT(gtk_widget_get_ancestor (widget, | ||
521 | + GTK_TYPE_WINDOW)), "move-focus", | ||
522 | + GTK_DIR_TAB_FORWARD); | ||
523 | + | ||
524 | if (GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event)) | ||
525 | /* Activate key bindings | ||
526 | */ | ||
527 | @@ -1835,6 +2038,8 @@ | ||
528 | GdkEventKey *event) | ||
529 | { | ||
530 | GtkEntry *entry = GTK_ENTRY (widget); | ||
531 | + | ||
532 | + gtk_entry_update_scrolled_window( entry ); | ||
533 | |||
534 | if (entry->editable) | ||
535 | { | ||
536 | @@ -1853,7 +2058,35 @@ | ||
537 | GdkEventFocus *event) | ||
538 | { | ||
539 | GtkEntry *entry = GTK_ENTRY (widget); | ||
540 | - | ||
541 | + GtkEntryPrivate *priv; | ||
542 | + | ||
543 | + priv = GTK_ENTRY_GET_PRIVATE (widget); | ||
544 | + /* Hildon : If the text doesn't fit the entry, upon focusing | ||
545 | + * to an text field, move the caret to the end of the entry. | ||
546 | + * Force the entry to recompute, otherwise it doesn't update | ||
547 | + * if the cursor is currently at the end*/ | ||
548 | + /* hildon : If the text has no selection and focus returned with | ||
549 | + other means than pointer click, set cursor before first | ||
550 | + character of the text, otherwise behave normally */ | ||
551 | + | ||
552 | + if (!entry->in_click) | ||
553 | + { | ||
554 | + /*gboolean has_selection; | ||
555 | + has_selection = gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), NULL, NULL); | ||
556 | + if (!has_selection) | ||
557 | + { | ||
558 | + gtk_editable_set_position (GTK_EDITABLE (entry), -1); | ||
559 | + }*//*FIXME need a better hack here*/ | ||
560 | + /* Hildon: If in SecretEditor mode highlight selection if entry got focus | ||
561 | + * otherways than mouse/stylus */ | ||
562 | + if (!entry->visible && priv->keep_focus) | ||
563 | + { | ||
564 | + gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1); | ||
565 | + } | ||
566 | + } | ||
567 | + | ||
568 | + gtk_entry_recompute (GTK_ENTRY (entry)); | ||
569 | + | ||
570 | gtk_widget_queue_draw (widget); | ||
571 | |||
572 | if (entry->editable) | ||
573 | @@ -1876,6 +2109,8 @@ | ||
574 | GdkEventFocus *event) | ||
575 | { | ||
576 | GtkEntry *entry = GTK_ENTRY (widget); | ||
577 | + GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (widget); | ||
578 | + guint tmp_pos; | ||
579 | GtkEntryCompletion *completion; | ||
580 | |||
581 | gtk_widget_queue_draw (widget); | ||
582 | @@ -1886,6 +2121,20 @@ | ||
583 | gtk_im_context_focus_out (entry->im_context); | ||
584 | } | ||
585 | |||
586 | + tmp_pos = gtk_editable_get_position (GTK_EDITABLE (widget)); | ||
587 | + if (priv->keep_focus){ | ||
588 | + if (!entry->visible) | ||
589 | + gtk_editable_set_position (GTK_EDITABLE (widget), tmp_pos); | ||
590 | + priv->keep_focus = FALSE; | ||
591 | + } | ||
592 | + else { | ||
593 | + if (priv->menu_popped) | ||
594 | + priv->menu_popped = FALSE; | ||
595 | + else gtk_editable_set_position (GTK_EDITABLE (widget), tmp_pos); | ||
596 | + } | ||
597 | + | ||
598 | + gtk_widget_queue_draw(widget); | ||
599 | + | ||
600 | gtk_entry_check_cursor_blink (entry); | ||
601 | |||
602 | g_signal_handlers_disconnect_by_func (gdk_keymap_get_for_display (gtk_widget_get_display (widget)), | ||
603 | @@ -1902,7 +2151,6 @@ | ||
604 | static void | ||
605 | gtk_entry_grab_focus (GtkWidget *widget) | ||
606 | { | ||
607 | - GtkEntry *entry = GTK_ENTRY (widget); | ||
608 | gboolean select_on_focus; | ||
609 | |||
610 | GTK_WIDGET_CLASS (parent_class)->grab_focus (widget); | ||
611 | @@ -1912,8 +2160,8 @@ | ||
612 | &select_on_focus, | ||
613 | NULL); | ||
614 | |||
615 | - if (select_on_focus && entry->editable && !entry->in_click) | ||
616 | - gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1); | ||
617 | +/* Hildon : When focusing to an entry, it shouldn't become | ||
618 | + * highlighted. */ | ||
619 | } | ||
620 | |||
621 | static void | ||
622 | @@ -1987,7 +2235,7 @@ | ||
623 | |||
624 | if (new_text_length > 63) | ||
625 | g_free (text); | ||
626 | - | ||
627 | + gtk_entry_update_scrolled_window( entry ); | ||
628 | g_object_unref (editable); | ||
629 | } | ||
630 | |||
631 | @@ -2074,7 +2322,7 @@ | ||
632 | if (end < 0) | ||
633 | end = entry->text_length; | ||
634 | |||
635 | - gtk_entry_reset_im_context (entry); | ||
636 | + /*gtk_entry_reset_im_context (entry);*//*FIXME tmp kludge, might break something*/ | ||
637 | |||
638 | gtk_entry_set_positions (entry, | ||
639 | MIN (end, entry->text_length), | ||
640 | @@ -2168,13 +2416,19 @@ | ||
641 | { | ||
642 | gint index; | ||
643 | gint n_chars; | ||
644 | + gboolean show_last_char = FALSE; | ||
645 | |||
646 | GtkEntry *entry = GTK_ENTRY (editable); | ||
647 | - | ||
648 | + GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (GTK_WIDGET (entry)); | ||
649 | if (new_text_length < 0) | ||
650 | new_text_length = strlen (new_text); | ||
651 | |||
652 | n_chars = g_utf8_strlen (new_text, new_text_length); | ||
653 | + | ||
654 | + | ||
655 | + gtk_widget_style_get (GTK_WIDGET (entry), "show-last-char", | ||
656 | + &show_last_char, NULL); | ||
657 | + | ||
658 | if (entry->text_max_length > 0 && n_chars + entry->text_length > entry->text_max_length) | ||
659 | { | ||
660 | gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (entry))); | ||
661 | @@ -2238,6 +2492,14 @@ | ||
662 | |||
663 | if (entry->selection_bound > *position) | ||
664 | entry->selection_bound += n_chars; | ||
665 | + | ||
666 | + /* Hildon: store this addition IF it was only 1 char (user inputted) and we are currently in secret mode (invisible) */ | ||
667 | + | ||
668 | + if (show_last_char && n_chars == 1 && !entry->visible && (new_text_length < HILDON_EDITED_CHARACTER_MAX)) { | ||
669 | + memset( &priv->hildon_edited_character, 0x00, HILDON_EDITED_CHARACTER_MAX ); | ||
670 | + priv->hildon_edited_character_length = new_text_length; | ||
671 | + memcpy( &priv->hildon_edited_character, new_text, new_text_length ); /* Guaranteed to be < total length */ | ||
672 | + } | ||
673 | |||
674 | *position += n_chars; | ||
675 | |||
676 | @@ -2339,6 +2601,11 @@ | ||
677 | |||
678 | gtk_entry_reset_im_context (entry); | ||
679 | |||
680 | + /* Hildon, if not visible set the position to the end */ | ||
681 | + /* New SecretEditor specs say that with cursor should move | ||
682 | + * With left/right arrows | ||
683 | + */ | ||
684 | + | ||
685 | if (entry->current_pos != entry->selection_bound && !extend_selection) | ||
686 | { | ||
687 | /* If we have a current selection and aren't extending it, move to the | ||
688 | @@ -2445,7 +2712,7 @@ | ||
689 | gint start_pos = entry->current_pos; | ||
690 | gint end_pos = entry->current_pos; | ||
691 | |||
692 | - gtk_entry_reset_im_context (entry); | ||
693 | + /* Hildon: code removed - backspace should not clear the word completion */ | ||
694 | |||
695 | if (!entry->editable) | ||
696 | return; | ||
697 | @@ -2515,7 +2782,8 @@ | ||
698 | GtkEditable *editable = GTK_EDITABLE (entry); | ||
699 | gint prev_pos; | ||
700 | |||
701 | - gtk_entry_reset_im_context (entry); | ||
702 | +/* gtk_entry_reset_im_context (entry); */ /*backspace should not clear | ||
703 | + the word completion*/ | ||
704 | |||
705 | if (!entry->editable || !entry->text) | ||
706 | return; | ||
707 | @@ -2883,21 +3151,28 @@ | ||
708 | ++i; | ||
709 | } | ||
710 | } | ||
711 | - | ||
712 | + | ||
713 | +#define HILDON_EDITED_CHARACTER_MS 600 /* 0.6 seconds */ | ||
714 | + | ||
715 | static PangoLayout * | ||
716 | gtk_entry_create_layout (GtkEntry *entry, | ||
717 | gboolean include_preedit) | ||
718 | { | ||
719 | GtkWidget *widget = GTK_WIDGET (entry); | ||
720 | + GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry); | ||
721 | PangoLayout *layout = gtk_widget_create_pango_layout (widget, NULL); | ||
722 | PangoAttrList *tmp_attrs = pango_attr_list_new (); | ||
723 | |||
724 | gchar *preedit_string = NULL; | ||
725 | gint preedit_length = 0; | ||
726 | PangoAttrList *preedit_attrs = NULL; | ||
727 | + gboolean show_last_char = FALSE; | ||
728 | |||
729 | pango_layout_set_single_paragraph_mode (layout, TRUE); | ||
730 | |||
731 | + gtk_widget_style_get (widget, "show-last-char", | ||
732 | + &show_last_char, NULL); | ||
733 | + | ||
734 | if (include_preedit) | ||
735 | { | ||
736 | gtk_im_context_get_preedit_string (entry->im_context, | ||
737 | @@ -3003,7 +3278,49 @@ | ||
738 | else | ||
739 | invisible_char = ' '; /* just pick a char */ | ||
740 | |||
741 | - append_char (str, invisible_char, entry->text_length); | ||
742 | + if (!show_last_char) | ||
743 | + append_char (str, invisible_char, entry->text_length); | ||
744 | + else if (show_last_char) | ||
745 | + { | ||
746 | + /* Hildon */ | ||
747 | + if (priv->hildon_edited_character_length > 0) | ||
748 | + { | ||
749 | + | ||
750 | + /* If we have an outstanding timeout, remove it, because the character it is set to hide | ||
751 | + * is already hidden now. We do this first to prevent possible race conditions if the timout | ||
752 | + * were to trigger while in here | ||
753 | + */ | ||
754 | + | ||
755 | + if (priv->hildon_edited_character_timeout) | ||
756 | + { | ||
757 | + g_source_remove( priv->hildon_edited_character_timeout ); | ||
758 | + priv->hildon_edited_character_timeout = FALSE; | ||
759 | + } | ||
760 | + | ||
761 | + /* Draw the secret character length-1 times, because the last char will be visible */ | ||
762 | + append_char (str, invisible_char, entry->text_length > 1 ? entry->text_length - 1 : 0); | ||
763 | + | ||
764 | + /* Add our visible char, the most recently inputted one */ | ||
765 | + g_string_append_len (str, (char *)&priv->hildon_edited_character, priv->hildon_edited_character_length); | ||
766 | + | ||
767 | + /* Now remove this last inputted character, don't need it anymore */ | ||
768 | + | ||
769 | + memset( priv->hildon_edited_character, 0x00, HILDON_EDITED_CHARACTER_MAX ); | ||
770 | + priv->hildon_edited_character_length = 0; | ||
771 | + | ||
772 | + priv->hildon_edited_character_timeout = g_timeout_add( HILDON_EDITED_CHARACTER_MS, (GSourceFunc) | ||
773 | + hildon_remove_visible_character, entry ); | ||
774 | + | ||
775 | + } | ||
776 | + else | ||
777 | + { | ||
778 | + /* No last character known. This could be for example because the application has filled | ||
779 | + * in the password already. In that case we of course don't want to view it | ||
780 | + */ | ||
781 | + append_char (str, invisible_char, entry->text_length); | ||
782 | + } | ||
783 | + } | ||
784 | + | ||
785 | pango_layout_set_text (layout, str->str, str->len); | ||
786 | g_string_free (str, TRUE); | ||
787 | } | ||
788 | @@ -3048,12 +3365,17 @@ | ||
789 | gint area_width, area_height; | ||
790 | gint y_pos; | ||
791 | PangoLayoutLine *line; | ||
792 | - | ||
793 | + gint border_x, border_y; | ||
794 | + | ||
795 | + gtk_widget_style_get (GTK_WIDGET (entry), "horizontal-border", &border_x, | ||
796 | + "vertical-border", &border_y, | ||
797 | + NULL); | ||
798 | + | ||
799 | layout = gtk_entry_ensure_layout (entry, TRUE); | ||
800 | |||
801 | get_text_area_size (entry, NULL, NULL, &area_width, &area_height); | ||
802 | |||
803 | - area_height = PANGO_SCALE * (area_height - 2 * INNER_BORDER); | ||
804 | + area_height = PANGO_SCALE * (area_height - 2 * border_y); | ||
805 | |||
806 | line = pango_layout_get_lines (layout)->data; | ||
807 | pango_layout_line_get_extents (line, NULL, &logical_rect); | ||
808 | @@ -3070,10 +3392,10 @@ | ||
809 | else if (y_pos + logical_rect.height > area_height) | ||
810 | y_pos = area_height - logical_rect.height; | ||
811 | |||
812 | - y_pos = INNER_BORDER + y_pos / PANGO_SCALE; | ||
813 | + y_pos = border_y + y_pos / PANGO_SCALE; | ||
814 | |||
815 | if (x) | ||
816 | - *x = INNER_BORDER - entry->scroll_offset; | ||
817 | + *x = border_x - entry->scroll_offset; | ||
818 | |||
819 | if (y) | ||
820 | *y = y_pos; | ||
821 | @@ -3083,6 +3405,10 @@ | ||
822 | gtk_entry_draw_text (GtkEntry *entry) | ||
823 | { | ||
824 | GtkWidget *widget; | ||
825 | + gint border_y, border_x; | ||
826 | + | ||
827 | + gtk_widget_style_get (GTK_WIDGET (entry), "horizontal-border", &border_x, | ||
828 | + "vertical-border", &border_y, NULL); | ||
829 | |||
830 | if (!entry->visible && entry->invisible_char == 0) | ||
831 | return; | ||
832 | @@ -3092,14 +3418,76 @@ | ||
833 | PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE); | ||
834 | gint x, y; | ||
835 | gint start_pos, end_pos; | ||
836 | + GdkRectangle clip_rect; | ||
837 | |||
838 | widget = GTK_WIDGET (entry); | ||
839 | |||
840 | get_layout_position (entry, &x, &y); | ||
841 | |||
842 | + /* Use a clipping rectangle so that we always get enough empty space around | ||
843 | + * the text. | ||
844 | + */ | ||
845 | + clip_rect.x = border_x; | ||
846 | + clip_rect.y = 0; | ||
847 | + | ||
848 | + gdk_drawable_get_size (entry->text_area, &clip_rect.width, &clip_rect.height); | ||
849 | + clip_rect.width -= border_x * 2; | ||
850 | + | ||
851 | + /*changes for Hildon | ||
852 | + *Reduce the size of the clip rect, so that only full characters are displayed | ||
853 | + */ | ||
854 | + | ||
855 | + /* NOTE: Commented out because it does not work with bidi text where | ||
856 | +the indexes are in random | ||
857 | + * left-right or right-left order. Code causes Pango assert aborts. Because gtkentry itself | ||
858 | + * is broken with regard to bidi anyway (bug #478) we ignore this requirement of the spec | ||
859 | + * until gtkentry itself is fixed. (bug #477) | ||
860 | + */ | ||
861 | + | ||
862 | + /* Better yet, let's enable this only when not in RTL mode */ | ||
863 | + | ||
864 | + /* Note: BUG #857. patched gtkentry crashed when pasting scalable fonts. This is pango problem | ||
865 | + * and we tested patched gtkentry with pango version 1.3.2 and it appears to be fixed. Section is commented | ||
866 | + out until we upgrade to new version of pango | ||
867 | + if (gtk_widget_get_direction( entry ) != GTK_TEXT_DIR_RTL) | ||
868 | + { | ||
869 | + PangoRectangle char_rect; // used for getting character's onscreen pos | ||
870 | + PangoLayoutIter *iter; // used to iterate over the text | ||
871 | + | ||
872 | + // get the position of the character currently at the clip border | ||
873 | + iter = get_char_at_pos( layout, (clip_rect.x + clip_rect.width + entry->scroll_offset), 0 ); | ||
874 | + if ( iter ) | ||
875 | + { | ||
876 | + // get the position of that character on the screen | ||
877 | + pango_layout_iter_get_char_extents( iter, &char_rect ); | ||
878 | + char_rect.x /= PANGO_SCALE; | ||
879 | + char_rect.x -= entry->scroll_offset; | ||
880 | + char_rect.width /= PANGO_SCALE; | ||
881 | + | ||
882 | + // if the ending position is > the clip rectangle, then the | ||
883 | + // character is only partially visible, and we should | ||
884 | + // clip the entire character. | ||
885 | + | ||
886 | + if ( char_rect.x + char_rect.width > clip_rect.x + clip_rect.width ) | ||
887 | + { | ||
888 | + clip_rect.width = char_rect.x; | ||
889 | + } | ||
890 | + | ||
891 | + pango_layout_iter_free( iter ); | ||
892 | + } | ||
893 | + | ||
894 | + } | ||
895 | + */ | ||
896 | + /******************************************************************/ | ||
897 | + | ||
898 | + gdk_gc_set_clip_rectangle (widget->style->text_gc [widget->state], &clip_rect); | ||
899 | + | ||
900 | gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state], | ||
901 | x, y, | ||
902 | layout); | ||
903 | + | ||
904 | + gdk_gc_set_clip_rectangle (widget->style->text_gc [widget->state], NULL); | ||
905 | + | ||
906 | |||
907 | if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos)) | ||
908 | { | ||
909 | @@ -3128,7 +3516,7 @@ | ||
910 | { | ||
911 | GdkRectangle rect; | ||
912 | |||
913 | - rect.x = INNER_BORDER - entry->scroll_offset + ranges[2 * i]; | ||
914 | + rect.x = border_x - entry->scroll_offset + ranges[2 * i]; | ||
915 | rect.y = y; | ||
916 | rect.width = ranges[2 * i + 1]; | ||
917 | rect.height = logical_rect.height; | ||
918 | @@ -3177,14 +3565,18 @@ | ||
919 | { | ||
920 | GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (entry))); | ||
921 | PangoDirection keymap_direction = gdk_keymap_get_direction (keymap); | ||
922 | + gint border_x, border_y; | ||
923 | |||
924 | + gtk_widget_style_get (GTK_WIDGET (entry), "horizontal-border", &border_x, | ||
925 | + "vertical-border", &border_y, | ||
926 | + NULL); | ||
927 | if (GTK_WIDGET_DRAWABLE (entry)) | ||
928 | { | ||
929 | GtkWidget *widget = GTK_WIDGET (entry); | ||
930 | GdkRectangle cursor_location; | ||
931 | gboolean split_cursor; | ||
932 | |||
933 | - gint xoffset = INNER_BORDER - entry->scroll_offset; | ||
934 | + gint xoffset = border_x - entry->scroll_offset; | ||
935 | gint strong_x, weak_x; | ||
936 | gint text_area_height; | ||
937 | PangoDirection dir1 = PANGO_DIRECTION_NEUTRAL; | ||
938 | @@ -3221,9 +3613,9 @@ | ||
939 | } | ||
940 | |||
941 | cursor_location.x = xoffset + x1; | ||
942 | - cursor_location.y = INNER_BORDER; | ||
943 | + cursor_location.y = border_y; | ||
944 | cursor_location.width = 0; | ||
945 | - cursor_location.height = text_area_height - 2 * INNER_BORDER ; | ||
946 | + cursor_location.height = text_area_height - 2 * border_y; | ||
947 | |||
948 | draw_insertion_cursor (entry, | ||
949 | &cursor_location, TRUE, dir1, | ||
950 | @@ -3249,11 +3641,8 @@ | ||
951 | static void | ||
952 | gtk_entry_reset_im_context (GtkEntry *entry) | ||
953 | { | ||
954 | - if (entry->need_im_reset) | ||
955 | - { | ||
956 | - entry->need_im_reset = 0; | ||
957 | - gtk_im_context_reset (entry->im_context); | ||
958 | - } | ||
959 | + /* Hildon: We want reset to be sent more often */ | ||
960 | + gtk_im_context_reset (entry->im_context); | ||
961 | } | ||
962 | |||
963 | static gint | ||
964 | @@ -3266,8 +3655,12 @@ | ||
965 | gint pos; | ||
966 | gboolean trailing; | ||
967 | const gchar *text; | ||
968 | - gint cursor_index; | ||
969 | - | ||
970 | + gint border_x, cursor_index; | ||
971 | + | ||
972 | + gtk_widget_style_get (GTK_WIDGET (entry), "horizontal-border", &border_x, | ||
973 | + NULL); | ||
974 | + x -= border_x; | ||
975 | + | ||
976 | layout = gtk_entry_ensure_layout (entry, TRUE); | ||
977 | text = pango_layout_get_text (layout); | ||
978 | cursor_index = g_utf8_offset_to_pointer (text, entry->current_pos) - text; | ||
979 | @@ -3355,12 +3748,17 @@ | ||
980 | PangoLayout *layout; | ||
981 | PangoLayoutLine *line; | ||
982 | PangoRectangle logical_rect; | ||
983 | + gint border_x, border_y; | ||
984 | + | ||
985 | + gtk_widget_style_get (GTK_WIDGET (entry), "horizontal-border", &border_x, | ||
986 | + "vertical-border", &border_y, | ||
987 | + NULL); | ||
988 | |||
989 | if (!GTK_WIDGET_REALIZED (entry)) | ||
990 | return; | ||
991 | |||
992 | gdk_drawable_get_size (entry->text_area, &text_area_width, NULL); | ||
993 | - text_area_width -= 2 * INNER_BORDER; | ||
994 | + text_area_width -= 2 * border_x; | ||
995 | |||
996 | layout = gtk_entry_ensure_layout (entry, TRUE); | ||
997 | line = pango_layout_get_lines (layout)->data; | ||
998 | @@ -3390,13 +3788,13 @@ | ||
999 | entry->scroll_offset = CLAMP (entry->scroll_offset, min_offset, max_offset); | ||
1000 | |||
1001 | /* And make sure cursors are on screen. Note that the cursor is | ||
1002 | - * actually drawn one pixel into the INNER_BORDER space on | ||
1003 | + * actually drawn one pixel into the border_x space on | ||
1004 | * the right, when the scroll is at the utmost right. This | ||
1005 | * looks better to to me than confining the cursor inside the | ||
1006 | * border entirely, though it means that the cursor gets one | ||
1007 | * pixel closer to the edge of the widget on the right than | ||
1008 | * on the left. This might need changing if one changed | ||
1009 | - * INNER_BORDER from 2 to 1, as one would do on a | ||
1010 | + * border_x from 2 to 1, as one would do on a | ||
1011 | * small-screen-real-estate display. | ||
1012 | * | ||
1013 | * We always make sure that the strong cursor is on screen, and | ||
1014 | @@ -3430,6 +3828,52 @@ | ||
1015 | entry->scroll_offset += weak_xoffset - text_area_width; | ||
1016 | } | ||
1017 | |||
1018 | + /*Changes for Hildon | ||
1019 | + * now we make it so that if a character is partially visible, | ||
1020 | + * then we also scroll that off the screen. | ||
1021 | + */ | ||
1022 | + | ||
1023 | + /* NOTE: Commented out because it does not work with bidi text where the indexes are in random | ||
1024 | + * left-right or right-left order. Code causes Pango assert aborts. Because gtkentry itself | ||
1025 | + * is broken with regard to bidi anyway (bug #478) we ignore this requirement of the spec | ||
1026 | + * until gtkentry itself is fixed. (bug #477) | ||
1027 | + */ | ||
1028 | + | ||
1029 | + /* Better yet, let's disable this (for now) only when using RTL text */ | ||
1030 | + | ||
1031 | +/*Note: BUG #857. patched gtkentry crashed when pasting scalable fonts. This is pango problem | ||
1032 | + * 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 | ||
1033 | + if (gtk_widget_get_direction( entry ) != GTK_TEXT_DIR_RTL) | ||
1034 | + { | ||
1035 | + PangoLayoutIter *iter = get_char_at_pos( layout, entry->scroll_offset, 0 ); | ||
1036 | + // if we found the char we were looking for | ||
1037 | + if ( iter ) | ||
1038 | + { | ||
1039 | + PangoRectangle char_rect; // used for getting character's onscreen pos | ||
1040 | + | ||
1041 | + // get the position of that character on the screen | ||
1042 | + pango_layout_iter_get_char_extents( iter, &char_rect ); | ||
1043 | + char_rect.x /= PANGO_SCALE; | ||
1044 | + | ||
1045 | + // if the starting position is < the current scroll offset, then the | ||
1046 | + // character is only partially visible, and we should scroll to the | ||
1047 | + // start of the next character instead | ||
1048 | + | ||
1049 | + if ( char_rect.x < entry->scroll_offset ) | ||
1050 | + { | ||
1051 | + if ( pango_layout_iter_next_char( iter ) ) | ||
1052 | + { | ||
1053 | + pango_layout_iter_get_char_extents( iter, &char_rect); | ||
1054 | + entry->scroll_offset = char_rect.x / PANGO_SCALE; | ||
1055 | + } | ||
1056 | + } | ||
1057 | + | ||
1058 | + pango_layout_iter_free( iter ); | ||
1059 | + } | ||
1060 | + | ||
1061 | + | ||
1062 | + }*/ | ||
1063 | + | ||
1064 | g_object_notify (G_OBJECT (entry), "scroll_offset"); | ||
1065 | } | ||
1066 | |||
1067 | @@ -3552,8 +3996,9 @@ | ||
1068 | pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs); | ||
1069 | |||
1070 | /* Find the next word end */ | ||
1071 | + /*Hildon: cursor should seek to the start of the next word*/ | ||
1072 | new_pos++; | ||
1073 | - while (new_pos < n_attrs && !log_attrs[new_pos].is_word_end) | ||
1074 | + while (new_pos < n_attrs && !log_attrs[new_pos].is_word_start) | ||
1075 | new_pos++; | ||
1076 | |||
1077 | g_free (log_attrs); | ||
1078 | @@ -3648,14 +4093,9 @@ | ||
1079 | |||
1080 | if (entry->visible) | ||
1081 | return gtk_editable_get_chars (GTK_EDITABLE (entry), start, end); | ||
1082 | - else if (!entry->invisible_char) | ||
1083 | + /*Hildon: when not visible, no chars are public*/ | ||
1084 | + else | ||
1085 | return g_strdup (""); | ||
1086 | - else | ||
1087 | - { | ||
1088 | - GString *str = g_string_new (NULL); | ||
1089 | - append_char (str, entry->invisible_char, end - start); | ||
1090 | - return g_string_free (str, FALSE); | ||
1091 | - } | ||
1092 | } | ||
1093 | |||
1094 | static void | ||
1095 | @@ -3678,9 +4118,12 @@ | ||
1096 | |||
1097 | if (text) | ||
1098 | { | ||
1099 | - gint pos, start, end; | ||
1100 | + gint pos, start, end, index; | ||
1101 | GtkEntryCompletion *completion = gtk_entry_get_completion (entry); | ||
1102 | |||
1103 | + /* when pasting multiline text, ignore everything but the first line */ | ||
1104 | + for (index = 0; text[index] != 0 && text[index] != '\n'; index++); | ||
1105 | + | ||
1106 | if (completion) | ||
1107 | { | ||
1108 | g_signal_handler_block (entry, completion->priv->changed_id); | ||
1109 | @@ -3692,7 +4135,7 @@ | ||
1110 | gtk_editable_delete_text (editable, start, end); | ||
1111 | |||
1112 | pos = entry->current_pos; | ||
1113 | - gtk_editable_insert_text (editable, text, -1, &pos); | ||
1114 | + gtk_editable_insert_text (editable, text, index, &pos); | ||
1115 | gtk_editable_set_position (editable, pos); | ||
1116 | |||
1117 | if (completion) | ||
1118 | @@ -3888,6 +4331,7 @@ | ||
1119 | { | ||
1120 | g_return_if_fail (GTK_IS_ENTRY (entry)); | ||
1121 | |||
1122 | + g_object_set(G_OBJECT(entry->im_context), "visibility", visible, NULL); | ||
1123 | entry->visible = visible ? TRUE : FALSE; | ||
1124 | g_object_notify (G_OBJECT (entry), "visibility"); | ||
1125 | gtk_entry_recompute (entry); | ||
1126 | @@ -4569,6 +5013,7 @@ | ||
1127 | GdkEventButton *event) | ||
1128 | { | ||
1129 | PopupInfo *info = g_new (PopupInfo, 1); | ||
1130 | + GtkEntryPrivate *priv; | ||
1131 | |||
1132 | /* In order to know what entries we should make sensitive, we | ||
1133 | * ask for the current targets of the clipboard, and when | ||
1134 | @@ -4576,6 +5021,8 @@ | ||
1135 | */ | ||
1136 | info->entry = g_object_ref (entry); | ||
1137 | |||
1138 | + priv = GTK_ENTRY_GET_PRIVATE (entry); | ||
1139 | + | ||
1140 | if (event) | ||
1141 | { | ||
1142 | info->button = event->button; | ||
1143 | @@ -4591,6 +5038,8 @@ | ||
1144 | gdk_atom_intern ("TARGETS", FALSE), | ||
1145 | popup_targets_received, | ||
1146 | info); | ||
1147 | + | ||
1148 | + priv->menu_popped = TRUE; | ||
1149 | } | ||
1150 | |||
1151 | static gboolean | ||
1152 | @@ -5389,3 +5838,156 @@ | ||
1153 | |||
1154 | return completion; | ||
1155 | } | ||
1156 | + | ||
1157 | +static PangoLayoutIter *get_char_at_pos( PangoLayout *layout, gint x, gint y ) | ||
1158 | +{ | ||
1159 | + gint index = 0; /*the index of the first character */ | ||
1160 | + gint trailing = 0; /*not used*/ | ||
1161 | + PangoLayoutIter *iter; /*used to iterate over the text*/ | ||
1162 | + gboolean valid_char = TRUE; | ||
1163 | + | ||
1164 | + /*get the position of the character currently at the scroll offset*/ | ||
1165 | + pango_layout_xy_to_index( layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing ); | ||
1166 | + iter = pango_layout_get_iter( layout ); | ||
1167 | + | ||
1168 | + /*iterate until we get to the character at the same index*/ | ||
1169 | + while ( valid_char && pango_layout_iter_get_index( iter ) != index ) | ||
1170 | + { | ||
1171 | + valid_char = pango_layout_iter_next_char( iter ); | ||
1172 | + } | ||
1173 | + | ||
1174 | + if ( valid_char == FALSE ) | ||
1175 | + iter = NULL; | ||
1176 | + | ||
1177 | + return iter; | ||
1178 | +} | ||
1179 | + | ||
1180 | +static void gtk_entry_update_scrolled_window( GtkEntry *entry) | ||
1181 | +{ | ||
1182 | + GtkWidget *parent; | ||
1183 | + GtkWidget *widget; | ||
1184 | + GtkWidget *direct_parent = NULL; | ||
1185 | + GtkScrolledWindow *sw = NULL; | ||
1186 | + gboolean need_update = FALSE; | ||
1187 | + GtkAdjustment *vadjustment; | ||
1188 | + gdouble value; | ||
1189 | + | ||
1190 | + widget = parent = GTK_WIDGET(entry); | ||
1191 | + if(parent->parent != NULL) | ||
1192 | + direct_parent = parent->parent; | ||
1193 | + while(parent && !GTK_WIDGET_TOPLEVEL(parent)) | ||
1194 | + { | ||
1195 | + if(GTK_IS_SCROLLED_WINDOW(parent)) | ||
1196 | + { | ||
1197 | + need_update = TRUE; | ||
1198 | + sw = GTK_SCROLLED_WINDOW(parent); | ||
1199 | + break; | ||
1200 | + } | ||
1201 | + parent = parent->parent; | ||
1202 | + } | ||
1203 | + | ||
1204 | + if(need_update) | ||
1205 | + { | ||
1206 | + gint x=0, y=0; | ||
1207 | + vadjustment = gtk_scrolled_window_get_vadjustment(sw); | ||
1208 | + value = gtk_adjustment_get_value(vadjustment); | ||
1209 | + | ||
1210 | + if(direct_parent != NULL) | ||
1211 | + gtk_widget_translate_coordinates( direct_parent, parent, | ||
1212 | + widget->allocation.x, widget->allocation.y, &x, &y ); | ||
1213 | + | ||
1214 | + if( (gdouble) y < 0 ) | ||
1215 | + { | ||
1216 | + value = value + (gdouble) y; | ||
1217 | + if (value < vadjustment->lower) | ||
1218 | + value = vadjustment->lower; | ||
1219 | + } | ||
1220 | + else if( (gdouble )y + widget->allocation.height > vadjustment->page_size) | ||
1221 | + { | ||
1222 | + value = value + (gdouble)y + widget->allocation.height | ||
1223 | + - vadjustment->page_size; | ||
1224 | + if(value > vadjustment->upper - vadjustment->page_size) | ||
1225 | + value = vadjustment->upper - vadjustment->page_size; | ||
1226 | + } | ||
1227 | + gtk_adjustment_set_value(vadjustment, value); | ||
1228 | + gtk_scrolled_window_set_vadjustment(sw, GTK_ADJUSTMENT(vadjustment)); | ||
1229 | + } | ||
1230 | +} | ||
1231 | + | ||
1232 | +/* | ||
1233 | + * gtk_entry_set_autocap: | ||
1234 | + * @entry: a #GtkEntry | ||
1235 | + * @autocap: autocap | ||
1236 | + * | ||
1237 | + * Sets autocapitalization of the widget. | ||
1238 | + */ | ||
1239 | +static void | ||
1240 | +gtk_entry_set_autocap (GtkEntry *entry, | ||
1241 | + gboolean autocap) | ||
1242 | +{ | ||
1243 | + g_return_if_fail (GTK_IS_ENTRY (entry)); | ||
1244 | + | ||
1245 | + if (gtk_entry_get_autocap (entry) != autocap) | ||
1246 | + { | ||
1247 | + g_object_set (G_OBJECT (entry->im_context), "autocap", autocap, NULL); | ||
1248 | + g_object_notify (G_OBJECT (entry), "autocap"); | ||
1249 | + } | ||
1250 | +} | ||
1251 | + | ||
1252 | +/* | ||
1253 | + * gtk_entry_get_autocap: | ||
1254 | + * @entry: a #GtkEntry | ||
1255 | + * | ||
1256 | + * Gets autocapitalization state of the widget. | ||
1257 | + * | ||
1258 | + * Return value: a state | ||
1259 | + */ | ||
1260 | +static gboolean | ||
1261 | +gtk_entry_get_autocap (GtkEntry *entry) | ||
1262 | +{ | ||
1263 | + gboolean autocap; | ||
1264 | + g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE); | ||
1265 | + | ||
1266 | + g_object_get (G_OBJECT (entry->im_context), "autocap", &autocap, NULL); | ||
1267 | + | ||
1268 | + return autocap; | ||
1269 | +} | ||
1270 | + | ||
1271 | +/* | ||
1272 | + * gtk_entry_set_input_mode: | ||
1273 | + * @entry: a #GtkEntry | ||
1274 | + * @autocap: input mode | ||
1275 | + * | ||
1276 | + * Sets autocapitalization of the widget. | ||
1277 | + */ | ||
1278 | +static void | ||
1279 | +gtk_entry_set_input_mode (GtkEntry *entry, | ||
1280 | + gint mode) | ||
1281 | +{ | ||
1282 | + g_return_if_fail (GTK_IS_ENTRY (entry)); | ||
1283 | + | ||
1284 | + if (gtk_entry_get_input_mode (entry) != mode) | ||
1285 | + { | ||
1286 | + g_object_set (G_OBJECT (entry->im_context), "input_mode", mode, NULL); | ||
1287 | + g_object_notify (G_OBJECT (entry), "input_mode"); | ||
1288 | + } | ||
1289 | +} | ||
1290 | + | ||
1291 | +/* | ||
1292 | + * gtk_entry_get_input_mode: | ||
1293 | + * @entry: a #GtkEntry | ||
1294 | + * | ||
1295 | + * Gets input mode of the widget. | ||
1296 | + * | ||
1297 | + * Return value: input mode | ||
1298 | + */ | ||
1299 | +static gint | ||
1300 | +gtk_entry_get_input_mode (GtkEntry *entry) | ||
1301 | +{ | ||
1302 | + gint mode; | ||
1303 | + g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE); | ||
1304 | + | ||
1305 | + g_object_get (G_OBJECT (entry->im_context), "input_mode", &mode, NULL); | ||
1306 | + | ||
1307 | + return mode; | ||
1308 | +} | ||