summaryrefslogtreecommitdiffstats
path: root/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff
diff options
context:
space:
mode:
Diffstat (limited to 'meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff')
-rw-r--r--meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff2253
1 files changed, 2253 insertions, 0 deletions
diff --git a/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff b/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff
new file mode 100644
index 0000000000..87ccffa868
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff
@@ -0,0 +1,2253 @@
1--- gtk+-2.6.4/gtk/gtktreeview.c 2005-02-24 00:38:20.000000000 +0200
2+++ gtk+-2.6.4/gtk/gtktreeview.c 2005-04-06 16:19:38.274719720 +0300
3@@ -42,6 +42,7 @@
4 #include "gtkentry.h"
5 #include "gtkframe.h"
6 #include "gtktreemodelsort.h"
7+#include "gtkscrolledwindow.h"
8
9 #define GTK_TREE_VIEW_PRIORITY_VALIDATE (GDK_PRIORITY_REDRAW + 5)
10 #define GTK_TREE_VIEW_PRIORITY_SCROLL_SYNC (GTK_TREE_VIEW_PRIORITY_VALIDATE + 2)
11@@ -114,6 +115,7 @@
12 EXPAND_COLLAPSE_CURSOR_ROW,
13 SELECT_CURSOR_PARENT,
14 START_INTERACTIVE_SEARCH,
15+ ROW_INSENSITIVE,
16 LAST_SIGNAL
17 };
18
19@@ -132,7 +134,10 @@
20 PROP_SEARCH_COLUMN,
21 PROP_FIXED_HEIGHT_MODE,
22 PROP_HOVER_SELECTION,
23- PROP_HOVER_EXPAND
24+ PROP_HOVER_EXPAND,
25+ PROP_DOTTED_LINES,
26+ PROP_FORCE_LIST_KLUDGE,
27+ PROP_ALLOW_CHECKBOX_MODE
28 };
29
30 static void gtk_tree_view_class_init (GtkTreeViewClass *klass);
31@@ -338,8 +343,6 @@
32 static void gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
33 GtkRBTree *tree,
34 GtkRBNode *node);
35-static void gtk_tree_view_clamp_column_visible (GtkTreeView *tree_view,
36- GtkTreeViewColumn *column);
37 static gboolean gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view,
38 GdkEventMotion *event);
39 static void gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view);
40@@ -372,6 +375,18 @@
41 gpointer data);
42 static gboolean expand_collapse_timeout (gpointer data);
43 static gboolean do_expand_collapse (GtkTreeView *tree_view);
44+static void update_checkbox_mode (GObject *object,
45+ GParamSpec *pspec,
46+ gpointer data);
47+static void set_dotted_lines (GtkTreeView *tree_view,
48+ gboolean enable);
49+static void selection_changed (GtkTreeSelection *selection,
50+ gpointer data);
51+static void check_if_can_focus (GtkTreeView *tree_view);
52+static gint scroll_row_timeout (gpointer data);
53+
54+static void add_scroll_timeout (GtkTreeView *tree_view);
55+static void remove_scroll_timeout (GtkTreeView *tree_view);
56
57 /* interactive search */
58 static void gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view);
59@@ -694,8 +709,54 @@
60 FALSE,
61 G_PARAM_READWRITE));
62
63+ /**
64+ * GtkTreeView:dotted-lines:
65+ *
66+ * Enables or disables the dotted lines for hierarchical trees.
67+ * Hildon patch.
68+ */
69+ g_object_class_install_property (o_class,
70+ PROP_DOTTED_LINES,
71+ g_param_spec_boolean ("dotted_lines",
72+ P_("Dotted Lines"),
73+ P_("Whether to show or hide dotted lines for hierarchical trees"),
74+ FALSE,
75+ G_PARAM_READWRITE));
76+
77+ /**
78+ * GtkTreeView:force-list-kludge:
79+ *
80+ * Hildon kludge for fixing file tree behaviour until a cleaner
81+ * implementation is scheduled: if this property is set, then rows
82+ * can be activated by tapping even if the underlying tree model is
83+ * not technically a list.
84+ */
85+ g_object_class_install_property (o_class,
86+ PROP_FORCE_LIST_KLUDGE,
87+ g_param_spec_boolean ("force_list_kludge",
88+ P_("Force List Behaviour"),
89+ P_("Whether to activate tapped focused items even if model was not a list"),
90+ FALSE,
91+ G_PARAM_READWRITE));
92+
93+ /**
94+ * GtkTreeView:enable-checkbox-mode:
95+ *
96+ * Another Hildon kludge for allowing the existence of GtkTreeViews
97+ * that have activatable columns but that still is not a Text Listbox
98+ * in multiple selection with checkboxes mode.
99+ */
100+ g_object_class_install_property (o_class,
101+ PROP_ALLOW_CHECKBOX_MODE,
102+ g_param_spec_boolean ("allow_checkbox_mode",
103+ P_("Enable Checkbox Mode"),
104+ P_("Whether to behave like a Listbox in a multiple selection with checkboxes mode, if checkboxes exist"),
105+ TRUE,
106+ G_PARAM_READWRITE));
107+
108 /* Style properties */
109 #define _TREE_VIEW_EXPANDER_SIZE 12
110+#define _TREE_VIEW_EXPANDER_INDENT 10
111 #define _TREE_VIEW_VERTICAL_SEPARATOR 2
112 #define _TREE_VIEW_HORIZONTAL_SEPARATOR 2
113
114@@ -709,6 +770,15 @@
115 G_PARAM_READABLE));
116
117 gtk_widget_class_install_style_property (widget_class,
118+ g_param_spec_int ("expander_indent",
119+ P_("Expander intent"),
120+ P_("Defines the expanders indent"),
121+ 0,
122+ G_MAXINT,
123+ _TREE_VIEW_EXPANDER_INDENT,
124+ G_PARAM_READABLE));
125+
126+ gtk_widget_class_install_style_property (widget_class,
127 g_param_spec_int ("vertical_separator",
128 P_("Vertical Separator Width"),
129 P_("Vertical space between cells. Must be an even number"),
130@@ -754,6 +824,13 @@
131 GDK_TYPE_COLOR,
132 G_PARAM_READABLE));
133
134+ gtk_widget_class_install_style_property (widget_class,
135+ g_param_spec_boolean ("passive_focus",
136+ P_("Enables passive focus"),
137+ P_("Used for tree view passive focus"),
138+ TRUE,
139+ G_PARAM_READABLE));
140+
141 /* Signals */
142 widget_class->set_scroll_adjustments_signal =
143 g_signal_new ("set_scroll_adjustments",
144@@ -917,6 +994,16 @@
145 _gtk_marshal_BOOLEAN__NONE,
146 G_TYPE_BOOLEAN, 0);
147
148+ tree_view_signals[ROW_INSENSITIVE] =
149+ g_signal_new ("row_insensitive",
150+ G_TYPE_FROM_CLASS (o_class),
151+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
152+ G_STRUCT_OFFSET (GtkTreeViewClass, row_insensitive),
153+ NULL, NULL,
154+ _gtk_marshal_VOID__OBJECT,
155+ G_TYPE_NONE, 1,
156+ GTK_TYPE_TREE_PATH);
157+
158 /* Key bindings */
159 gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0,
160 GTK_MOVEMENT_DISPLAY_LINES, -1);
161@@ -1004,12 +1091,13 @@
162
163 gtk_binding_entry_add_signal (binding_set, GDK_space, 0, "select_cursor_row", 1,
164 G_TYPE_BOOLEAN, TRUE);
165+ /* Hildon change: Enter shouldn't select
166 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "select_cursor_row", 1,
167 G_TYPE_BOOLEAN, TRUE);
168 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0, "select_cursor_row", 1,
169 G_TYPE_BOOLEAN, TRUE);
170 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "select_cursor_row", 1,
171- G_TYPE_BOOLEAN, TRUE);
172+ G_TYPE_BOOLEAN, TRUE);*/
173
174 /* expand and collapse rows */
175 gtk_binding_entry_add_signal (binding_set, GDK_plus, 0, "expand_collapse_cursor_row", 3,
176@@ -1123,19 +1211,31 @@
177 gtk_binding_entry_add_signal (binding_set, GDK_f, GDK_CONTROL_MASK, "start_interactive_search", 0);
178
179 gtk_binding_entry_add_signal (binding_set, GDK_F, GDK_CONTROL_MASK, "start_interactive_search", 0);
180+
181+ /* Hildon addition: Add key bindings to Right and Left arrows */
182+ gtk_binding_entry_add_signal (binding_set, GDK_Right, 0, "expand_collapse_cursor_row", 3,
183+ G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, TRUE, G_TYPE_BOOLEAN, FALSE);
184+ gtk_binding_entry_add_signal (binding_set, GDK_plus, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
185+ G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, TRUE, G_TYPE_BOOLEAN, TRUE);
186+ gtk_binding_entry_add_signal (binding_set, GDK_Left, 0, "expand_collapse_cursor_row", 3,
187+ G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, FALSE);
188+ gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
189+ G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, TRUE);
190 }
191
192 static void
193 gtk_tree_view_init (GtkTreeView *tree_view)
194 {
195 tree_view->priv = g_new0 (GtkTreeViewPrivate, 1);
196- GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS);
197+
198+ /* Hildon: focus cannot be gained until at least one row is added */
199+ GTK_WIDGET_UNSET_FLAGS (tree_view, GTK_CAN_FOCUS);
200
201 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (tree_view), FALSE);
202
203+ /* Hildon: Headers invisible by default */
204 tree_view->priv->flags = GTK_TREE_VIEW_SHOW_EXPANDERS
205- | GTK_TREE_VIEW_DRAW_KEYFOCUS
206- | GTK_TREE_VIEW_HEADERS_VISIBLE;
207+ | GTK_TREE_VIEW_DRAW_KEYFOCUS;
208
209 /* We need some padding */
210 tree_view->priv->dy = 0;
211@@ -1165,6 +1265,26 @@
212
213 tree_view->priv->hover_selection = FALSE;
214 tree_view->priv->hover_expand = FALSE;
215+
216+ tree_view->priv->ctrl_pressed = FALSE;
217+ tree_view->priv->shift_pressed = FALSE;
218+
219+ tree_view->priv->checkbox_mode = FALSE;
220+ tree_view->priv->allow_checkbox_mode = TRUE;
221+ tree_view->priv->pen_down = FALSE;
222+ tree_view->priv->pen_drag_active = FALSE;
223+ tree_view->priv->pen_drag_reverse = FALSE;
224+ tree_view->priv->first_drag_row = NULL;
225+ tree_view->priv->last_drag_row = NULL;
226+ tree_view->priv->queued_expand_row = NULL;
227+ tree_view->priv->queued_select_row = NULL;
228+ tree_view->priv->pen_focus = TRUE;
229+
230+ /* Hildon: cursor should follow when selection changes */
231+ g_signal_connect (tree_view->priv->selection, "changed",
232+ G_CALLBACK (selection_changed), tree_view);
233+
234+ gtk_widget_set_name (GTK_WIDGET (tree_view), "treeview");
235 }
236
237
238@@ -1223,6 +1343,27 @@
239 case PROP_HOVER_EXPAND:
240 tree_view->priv->hover_expand = g_value_get_boolean (value);
241 break;
242+ case PROP_DOTTED_LINES:
243+ set_dotted_lines (tree_view, g_value_get_boolean (value));
244+ break;
245+ case PROP_FORCE_LIST_KLUDGE:
246+ tree_view->priv->force_list_kludge = g_value_get_boolean (value);
247+ break;
248+ case PROP_ALLOW_CHECKBOX_MODE:
249+ if ((tree_view->priv->allow_checkbox_mode = g_value_get_boolean (value)))
250+ {
251+ gtk_widget_set_name (GTK_WIDGET(tree_view), "treeview");
252+ update_checkbox_mode (NULL, NULL, tree_view);
253+ }
254+ else
255+ {
256+ /* ugly hack - to ensure that checkboxes are independent of the
257+ selection if !allow_checkbox_mode, we must be able to use
258+ different theming in that case */
259+ gtk_widget_set_name (GTK_WIDGET(tree_view), "no_checkbox_mode");
260+ tree_view->priv->checkbox_mode = FALSE;
261+ }
262+ break;
263 default:
264 break;
265 }
266@@ -1276,6 +1417,15 @@
267 case PROP_HOVER_EXPAND:
268 g_value_set_boolean (value, tree_view->priv->hover_expand);
269 break;
270+ case PROP_DOTTED_LINES:
271+ g_value_set_boolean (value, tree_view->priv->dotted_lines);
272+ break;
273+ case PROP_FORCE_LIST_KLUDGE:
274+ g_value_set_boolean (value, tree_view->priv->force_list_kludge);
275+ break;
276+ case PROP_ALLOW_CHECKBOX_MODE:
277+ g_value_set_boolean (value, tree_view->priv->allow_checkbox_mode);
278+ break;
279 default:
280 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
281 break;
282@@ -1376,6 +1526,27 @@
283 tree_view->priv->destroy_count_data = NULL;
284 }
285
286+ if (tree_view->priv->first_drag_row)
287+ {
288+ gtk_tree_row_reference_free (tree_view->priv->first_drag_row);
289+ tree_view->priv->first_drag_row = NULL;
290+ }
291+ if (tree_view->priv->last_drag_row)
292+ {
293+ gtk_tree_row_reference_free (tree_view->priv->last_drag_row);
294+ tree_view->priv->last_drag_row = NULL;
295+ }
296+ if (tree_view->priv->queued_expand_row)
297+ {
298+ gtk_tree_row_reference_free (tree_view->priv->queued_expand_row);
299+ tree_view->priv->queued_expand_row = NULL;
300+ }
301+ if (tree_view->priv->queued_select_row)
302+ {
303+ gtk_tree_row_reference_free (tree_view->priv->queued_select_row);
304+ tree_view->priv->queued_select_row = NULL;
305+ }
306+
307 gtk_tree_row_reference_free (tree_view->priv->cursor);
308 tree_view->priv->cursor = NULL;
309
310@@ -1494,6 +1665,8 @@
311 gtk_tree_view_map_buttons (tree_view);
312
313 gdk_window_show (widget->window);
314+
315+ check_if_can_focus (tree_view);
316 }
317
318 static void
319@@ -1895,6 +2068,8 @@
320 gint full_requested_width = 0;
321 gint number_of_expand_columns = 0;
322 gboolean rtl;
323+ GtkWidget *scroll;
324+ GtkPolicyType ptype;
325
326 tree_view = GTK_TREE_VIEW (widget);
327
328@@ -1969,6 +2144,19 @@
329 allocation.x = width;
330 column->width = real_requested_width;
331
332+ /* a dirty Hildon hack to force truncation if not enough space. This hack is applied
333+ * only if we are NOT in a scrolled window with hscroll*/
334+ scroll = gtk_widget_get_ancestor(widget, GTK_TYPE_SCROLLED_WINDOW);
335+ if ((!scroll ||
336+ (gtk_scrolled_window_get_policy (GTK_SCROLLED_WINDOW (scroll), &ptype, NULL), ptype == GTK_POLICY_NEVER))
337+ && (width + real_requested_width > widget->allocation.width))
338+ {
339+ column->width = widget->allocation.width - width;
340+ if (column->width < 1)
341+ column->width = 1;
342+ gtk_widget_queue_draw (widget);
343+ }
344+
345 if (column->expand)
346 {
347 if (number_of_expand_columns == 1)
348@@ -2153,6 +2341,23 @@
349 GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
350 }
351
352+/* helper function for gtk_tree_view_button_press */
353+static void
354+activate_callback (GtkTreeModel *model,
355+ GtkTreePath *path,
356+ GtkTreeIter *iter,
357+ gpointer data)
358+{
359+ GtkTreeView *tree_view = GTK_TREE_VIEW (data);
360+
361+ /* Hildon: if the tree view has no active focus we don't activate
362+ * the selected row */
363+ if ( !GTK_WIDGET_HAS_FOCUS (GTK_WIDGET(data)) )
364+ return;
365+
366+ gtk_tree_view_row_activated (tree_view, path, tree_view->priv->focus_column);
367+}
368+
369 static gboolean
370 gtk_tree_view_button_press (GtkWidget *widget,
371 GdkEventButton *event)
372@@ -2166,6 +2371,7 @@
373 gint vertical_separator;
374 gint horizontal_separator;
375 gboolean rtl;
376+ gint expander_indent;
377
378 g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
379 g_return_val_if_fail (event != NULL, FALSE);
380@@ -2176,6 +2382,7 @@
381 gtk_widget_style_get (widget,
382 "vertical_separator", &vertical_separator,
383 "horizontal_separator", &horizontal_separator,
384+ "expander_indent", &expander_indent,
385 NULL);
386
387
388@@ -2199,6 +2406,14 @@
389 gint column_handled_click = FALSE;
390 gboolean row_double_click = FALSE;
391 gboolean rtl;
392+ gboolean force_list_kludge;
393+ GtkRBNode *cursor = NULL;
394+ gboolean focus_grab = FALSE;
395+
396+ if (!GTK_WIDGET_HAS_FOCUS (widget))
397+ focus_grab = TRUE;
398+
399+ GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
400
401 /* Empty tree? */
402 if (tree_view->priv->tree == NULL)
403@@ -2207,7 +2422,9 @@
404 return TRUE;
405 }
406
407- /* are we in an arrow? */
408+ /* In Hildon we don't want to use the arrows */
409+#if 0
410+ /* are we in an arrow? */
411 if (tree_view->priv->prelight_node &&
412 GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
413 {
414@@ -2226,6 +2443,7 @@
415 grab_focus_and_unset_draw_keyfocus (tree_view);
416 return TRUE;
417 }
418+#endif
419
420 /* find the node that was clicked */
421 new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
422@@ -2247,6 +2465,65 @@
423 background_area.height = ROW_HEIGHT (tree_view, GTK_RBNODE_GET_HEIGHT (node));
424 background_area.x = 0;
425
426+ if (tree_view->priv->first_drag_row)
427+ {
428+ gtk_tree_row_reference_free (tree_view->priv->first_drag_row);
429+ tree_view->priv->first_drag_row = NULL;
430+ }
431+ if (tree_view->priv->last_drag_row)
432+ {
433+ gtk_tree_row_reference_free (tree_view->priv->last_drag_row);
434+ tree_view->priv->last_drag_row = NULL;
435+ }
436+ tree_view->priv->first_drag_row =
437+ gtk_tree_row_reference_new (tree_view->priv->model, path);
438+ tree_view->priv->last_drag_row = gtk_tree_row_reference_copy (tree_view->priv->first_drag_row);
439+
440+ /* force_list_kludge allows pen dragging even if
441+ GTK_TREE_MODEL_LIST_ONLY is not set (to fix file tree) */
442+ g_object_get (widget, "force_list_kludge", &force_list_kludge, NULL);
443+
444+ /* Hildon: activate pen dragging, if listbox is not hierarchical and
445+ the pen was not put down in a position that initiates drag'n'drop */
446+ if (!tree_view->priv->pen_down &&
447+ (force_list_kludge ||
448+ (gtk_tree_model_get_flags(tree_view->priv->model)
449+ & GTK_TREE_MODEL_LIST_ONLY)) &&
450+ (tree_view->priv->checkbox_mode ||
451+ !gtk_tree_selection_path_is_selected(tree_view->priv->selection, path)))
452+ {
453+ gpointer drag_data;
454+
455+ tree_view->priv->pen_down = TRUE;
456+ tree_view->priv->pen_focus = TRUE;
457+
458+ /* also block attached dnd signal handler */
459+ drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
460+ if (drag_data)
461+ g_signal_handlers_block_matched (widget,
462+ G_SIGNAL_MATCH_DATA,
463+ 0, 0, NULL, NULL,
464+ drag_data);
465+ }
466+
467+ /* For the Hildon buttonpress find out the previously selected row */
468+ GtkRBTree *cursor_tree = NULL;
469+ GtkTreePath *cursor_path = NULL;
470+
471+ if (tree_view->priv->cursor)
472+ {
473+ cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
474+ if (cursor_path)
475+ {
476+ _gtk_tree_view_find_node (tree_view, cursor_path,
477+ &cursor_tree, &cursor);
478+ gtk_tree_path_free (cursor_path);
479+ }
480+ }
481+
482+ /* Hildon: in checkbox mode, dragging sets all checkboxes
483+ to the same state as the first toggled checkbox */
484+ tree_view->priv->new_state = !gtk_tree_selection_path_is_selected(tree_view->priv->selection, path);
485
486 /* Let the column have a chance at selecting it. */
487 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
488@@ -2275,8 +2552,11 @@
489 if (gtk_tree_view_is_expander_column (tree_view, column) &&
490 TREE_VIEW_DRAW_EXPANDERS(tree_view))
491 {
492- cell_area.x += depth * tree_view->priv->expander_size;
493- cell_area.width -= depth * tree_view->priv->expander_size;
494+ gint adjust;
495+
496+ adjust = depth * tree_view->priv->expander_size + (depth - 1) * expander_indent;
497+ cell_area.x += adjust;
498+ cell_area.width -= adjust;
499 }
500 break;
501 }
502@@ -2364,15 +2644,19 @@
503 */
504 if (event->type == GDK_BUTTON_PRESS)
505 {
506+ /* Hildon: ignore Ctrl and Shift */
507+#if 0
508 if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
509 tree_view->priv->ctrl_pressed = TRUE;
510 if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
511 tree_view->priv->shift_pressed = TRUE;
512+#endif
513
514 focus_cell = _gtk_tree_view_column_get_cell_at_pos (column, event->x - background_area.x);
515 if (focus_cell)
516 gtk_tree_view_column_focus_cell (column, focus_cell);
517
518+#if 0
519 if (event->state & GDK_CONTROL_MASK)
520 {
521 gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
522@@ -2387,6 +2671,86 @@
523 {
524 gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
525 }
526+#endif
527+ if (tree_view->priv->checkbox_mode)
528+ {
529+ GtkRBTree *tree = NULL;
530+ GtkRBNode *node = NULL;
531+
532+ _gtk_tree_view_find_node (tree_view, path, &tree, &node);
533+
534+ /* cursor cannot move to an insensitive row, so we
535+ need to check here to avoid toggling the current
536+ row by clicking on an insensitive row */
537+ if (_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
538+ node, path))
539+ {
540+ gtk_tree_view_real_set_cursor (tree_view, path,
541+ FALSE, TRUE);
542+ gtk_tree_view_real_toggle_cursor_row (tree_view);
543+ }
544+ else
545+ /* Usually this would be emitted by real_set_cursor.
546+ However in this case we never call it. */
547+ g_signal_emit (tree_view, tree_view_signals[ROW_INSENSITIVE], 0, path);
548+ }
549+ else
550+ {
551+ gboolean queue_row = TRUE;
552+ gboolean force_list_kludge;
553+
554+ /* force_list_kludge allows rows to be activated even if
555+ GTK_TREE_MODEL_LIST_ONLY is not set (to fix file tree) */
556+ g_object_get (widget, "force_list_kludge",
557+ &force_list_kludge, NULL);
558+ if ((force_list_kludge ||
559+ (gtk_tree_model_get_flags (tree_view->priv->model) &
560+ GTK_TREE_MODEL_LIST_ONLY)) &&
561+ gtk_tree_row_reference_valid (tree_view->priv->cursor))
562+ {
563+ /* special case: text listbox without checkboxes
564+ should activate selected rows when user taps
565+ on cursor row, but not affect selection*/
566+ GtkTreePath *cursor_path =
567+ gtk_tree_row_reference_get_path (tree_view->priv->cursor);
568+ if (gtk_tree_path_compare (cursor_path, path) == 0)
569+ {
570+ gtk_tree_selection_selected_foreach (tree_view->priv->selection,
571+ activate_callback,
572+ tree_view);
573+ queue_row = FALSE;
574+ }
575+ }
576+
577+ if (queue_row &&
578+ (gtk_tree_selection_get_mode (tree_view->priv->selection) == GTK_SELECTION_MULTIPLE) &&
579+ gtk_tree_selection_path_is_selected (tree_view->priv->selection, path))
580+ {
581+ GtkTreePath *old_cursor_path = NULL;
582+
583+ /* we don't know if the user is selecting an item or performing
584+ multiple item drag and drop until we know where button is released */
585+ if (tree_view->priv->queued_select_row)
586+ gtk_tree_row_reference_free (tree_view->priv->queued_select_row);
587+ tree_view->priv->queued_select_row =
588+ gtk_tree_row_reference_new (tree_view->priv->model, path);
589+
590+ /* however, move focus */
591+ if (tree_view->priv->cursor)
592+ {
593+ old_cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
594+ gtk_tree_row_reference_free (tree_view->priv->cursor);
595+ }
596+ tree_view->priv->cursor = gtk_tree_row_reference_new (tree_view->priv->model,
597+ path);
598+ gtk_tree_view_queue_draw_path (tree_view, path, NULL);
599+ if (old_cursor_path)
600+ gtk_tree_view_queue_draw_path (tree_view, old_cursor_path, NULL);
601+ }
602+ else
603+ gtk_tree_view_real_set_cursor (tree_view, path,
604+ queue_row, TRUE);
605+ }
606
607 tree_view->priv->ctrl_pressed = FALSE;
608 tree_view->priv->shift_pressed = FALSE;
609@@ -2412,6 +2776,15 @@
610 tree_view->priv->press_start_y = event->y;
611 }
612
613+ /* Hildon: if selected row is tapped -> the row gets activated and expands */
614+ if (!focus_grab)
615+ {
616+ /* ...although not until button is released */
617+ gtk_tree_row_reference_free (tree_view->priv->queued_expand_row);
618+ tree_view->priv->queued_expand_row =
619+ gtk_tree_row_reference_new (tree_view->priv->model, path);
620+ }
621+
622 /* Test if a double click happened on the same row. */
623 if (event->button == 1)
624 {
625@@ -2433,6 +2806,8 @@
626 }
627 }
628
629+ /* Hildon doesn't support double clicks */
630+#if 0
631 if (row_double_click)
632 {
633 if (tree_view->priv->last_button_press)
634@@ -2443,6 +2818,7 @@
635 tree_view->priv->last_button_press_2 = NULL;
636 }
637 else
638+#endif
639 {
640 if (tree_view->priv->last_button_press)
641 gtk_tree_row_reference_free (tree_view->priv->last_button_press);
642@@ -2626,6 +3002,28 @@
643
644 tree_view = GTK_TREE_VIEW (widget);
645
646+ /* unblock attached dnd signal handler */
647+ if (tree_view->priv->pen_down)
648+ {
649+ gpointer drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
650+ if (drag_data)
651+ g_signal_handlers_unblock_matched (widget,
652+ G_SIGNAL_MATCH_DATA,
653+ 0, 0, NULL, NULL,
654+ drag_data);
655+ }
656+
657+ /* stop pen dragging */
658+ if (tree_view->priv->first_drag_row)
659+ gtk_tree_row_reference_free (tree_view->priv->first_drag_row);
660+ if (tree_view->priv->last_drag_row)
661+ gtk_tree_row_reference_free (tree_view->priv->last_drag_row);
662+ tree_view->priv->first_drag_row = NULL;
663+ tree_view->priv->last_drag_row = NULL;
664+ tree_view->priv->pen_down = FALSE;
665+ tree_view->priv->pen_drag_active = FALSE;
666+ remove_scroll_timeout (tree_view);
667+
668 if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
669 return gtk_tree_view_button_release_drag_column (widget, event);
670
671@@ -2635,6 +3033,65 @@
672 if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE))
673 return gtk_tree_view_button_release_column_resize (widget, event);
674
675+ if (gtk_tree_row_reference_valid (tree_view->priv->queued_select_row))
676+ {
677+ /* unselect other nodes - but only if not drag'n'dropping */
678+ if (event->window == tree_view->priv->bin_window)
679+ gtk_tree_selection_unselect_all (tree_view->priv->selection);
680+
681+ gtk_tree_view_real_set_cursor (tree_view,
682+ gtk_tree_row_reference_get_path (tree_view->priv->queued_select_row),
683+ FALSE, TRUE);
684+ gtk_tree_row_reference_free (tree_view->priv->queued_select_row);
685+ tree_view->priv->queued_select_row = NULL;
686+ }
687+
688+ /* for handling expand/collapse postponed from button_press (since we
689+ don't want expand/collapse before tap on node has been completed) */
690+ if (gtk_tree_row_reference_valid (tree_view->priv->queued_expand_row) &&
691+ tree_view->priv->tree != NULL)
692+ {
693+ GtkTreePath *queued_expand_path;
694+ GtkRBTree *tree;
695+ GtkRBNode *node;
696+ GtkRBNode *old_node;
697+ gint y;
698+
699+ queued_expand_path =
700+ gtk_tree_row_reference_get_path (tree_view->priv->queued_expand_row);
701+
702+ if (queued_expand_path)
703+ {
704+ /* must check that cursor hasn't moved elsewhere since button_press */
705+ y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, event->y);
706+ _gtk_rbtree_find_offset (tree_view->priv->tree, y, &tree, &node);
707+
708+ _gtk_tree_view_find_node (tree_view, queued_expand_path,
709+ &tree, &old_node);
710+
711+ if (node && old_node == node)
712+ {
713+ if (node->children == NULL)
714+ gtk_tree_view_real_expand_row (tree_view,
715+ queued_expand_path,
716+ tree,
717+ node,
718+ FALSE, TRUE);
719+ else
720+ gtk_tree_view_real_collapse_row (tree_view,
721+ queued_expand_path,
722+ tree,
723+ node,
724+ TRUE);
725+ }
726+
727+ gtk_tree_path_free (queued_expand_path);
728+ }
729+
730+ gtk_tree_row_reference_free( tree_view->priv->queued_expand_row);
731+ tree_view->priv->queued_expand_row = NULL;
732+ }
733+
734 if (tree_view->priv->button_pressed_node == NULL)
735 return FALSE;
736
737@@ -3311,6 +3768,7 @@
738 GtkTreeView *tree_view;
739 GtkRBTree *tree;
740 GtkRBNode *node;
741+ GtkTreePath *path, *last_drag_path, *current_path;
742 gint new_y;
743
744 tree_view = (GtkTreeView *) widget;
745@@ -3319,7 +3777,8 @@
746 return FALSE;
747
748 /* only check for an initiated drag when a button is pressed */
749- if (tree_view->priv->pressed_button >= 0)
750+ /* Hildon: active pen drag overrides drag and drop */
751+ if (tree_view->priv->pressed_button >= 0 && !tree_view->priv->pen_down)
752 gtk_tree_view_maybe_begin_dragging_row (tree_view, event);
753
754 new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
755@@ -3328,6 +3787,99 @@
756
757 _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
758
759+ /* Hildon: pen dragging */
760+ if (tree_view->priv->pen_down && node != NULL &&
761+ tree_view->priv->queued_select_row == NULL &&
762+ gtk_tree_row_reference_valid (tree_view->priv->last_drag_row))
763+ {
764+ gint direction;
765+
766+ last_drag_path = gtk_tree_row_reference_get_path (tree_view->priv->last_drag_row);
767+ path = _gtk_tree_view_find_path (tree_view, tree, node);
768+ direction = gtk_tree_path_compare (path, last_drag_path);
769+
770+ if (direction != 0)
771+ {
772+ current_path = gtk_tree_path_copy (last_drag_path);
773+
774+ /* we must ensure that no row is skipped because stylus
775+ is moving faster than motion events are generated */
776+ do {
777+ if (direction > 0)
778+ {
779+ /* gtk_tree_path_next does not let us know when it failed */
780+ GtkTreeIter iter;
781+ gtk_tree_model_get_iter (tree_view->priv->model, &iter, current_path);
782+ if (!gtk_tree_model_iter_next (tree_view->priv->model, &iter))
783+ break;
784+
785+ gtk_tree_path_next (current_path);
786+ }
787+ else if (!gtk_tree_path_prev (current_path))
788+ break;
789+
790+ /* set cursor, and start scrolling */
791+ gtk_tree_view_real_set_cursor (tree_view, current_path, FALSE, FALSE);
792+ add_scroll_timeout (tree_view);
793+
794+ if (tree_view->priv->checkbox_mode)
795+ {
796+ /* always set to same state as the first tapped node */
797+ if (tree_view->priv->new_state)
798+ gtk_tree_selection_select_path (tree_view->priv->selection,
799+ current_path);
800+ else
801+ gtk_tree_selection_unselect_path (tree_view->priv->selection,
802+ current_path);
803+ }
804+ else
805+ {
806+ if (gtk_tree_selection_path_is_selected (tree_view->priv->selection,
807+ current_path))
808+ {
809+ /* apparently we have reversed the pen drag direction */
810+ GtkTreePath *reverse_path;
811+ gint reverse_direction;
812+
813+ reverse_direction = gtk_tree_path_compare (current_path,
814+ last_drag_path);
815+ reverse_path = gtk_tree_path_copy (last_drag_path);
816+ do {
817+ gtk_tree_selection_unselect_path (tree_view->priv->selection,
818+ reverse_path);
819+ tree_view->priv->pen_drag_reverse = TRUE;
820+ if (reverse_direction > 0)
821+ {
822+ GtkTreeIter iter;
823+ gtk_tree_model_get_iter (tree_view->priv->model, &iter, reverse_path);
824+ if (!gtk_tree_model_iter_next (tree_view->priv->model, &iter))
825+ break;
826+
827+ gtk_tree_path_next (reverse_path);
828+ }
829+ else if (!gtk_tree_path_prev (reverse_path))
830+ break;
831+ } while (gtk_tree_path_compare (reverse_path, current_path) != 0);
832+ gtk_tree_path_free (reverse_path);
833+ }
834+ else
835+ {
836+ gtk_tree_selection_select_path (tree_view->priv->selection,
837+ current_path);
838+ tree_view->priv->pen_drag_reverse = FALSE;
839+ }
840+ }
841+ } while (gtk_tree_path_compare(current_path, path) != 0);
842+ gtk_tree_path_free (current_path);
843+
844+ /* update last_drag_row */
845+ gtk_tree_row_reference_free (tree_view->priv->last_drag_row);
846+ tree_view->priv->last_drag_row =
847+ gtk_tree_row_reference_new (tree_view->priv->model, path);
848+ gtk_tree_path_free (path);
849+ }
850+ }
851+
852 /* If we are currently pressing down a button, we don't want to prelight anything else. */
853 if ((tree_view->priv->button_pressed_node != NULL) &&
854 (tree_view->priv->button_pressed_node != node))
855@@ -3404,6 +3956,22 @@
856 1, 1, w, h);
857 }
858
859+/* Hildon: helper function for dotted slash drawing;
860+ returns TRUE or FALSE, depending it there are
861+ more nodes at current level */
862+static gboolean
863+iter_has_next (GtkTreeModel *model, GtkTreeIter *iter)
864+{
865+ GtkTreeIter *check_iter;
866+ gboolean result;
867+
868+ check_iter = gtk_tree_iter_copy(iter);
869+ result = gtk_tree_model_iter_next (model, check_iter);
870+
871+ gtk_tree_iter_free (check_iter);
872+ return result;
873+}
874+
875 /* Warning: Very scary function.
876 * Modify at your own risk
877 *
878@@ -3433,16 +4001,25 @@
879 guint flags;
880 gint highlight_x;
881 gint bin_window_width;
882- GtkTreePath *cursor_path;
883- GtkTreePath *drag_dest_path;
884+ GtkTreePath *cursor_path = NULL;
885+ GtkTreePath *drag_dest_path = NULL;
886 GList *last_column;
887 gint vertical_separator;
888 gint horizontal_separator;
889+ gint expander_indent;
890 gint focus_line_width;
891 gboolean allow_rules;
892 gboolean has_special_cell;
893 gboolean rtl;
894 gint n_visible_columns;
895+ gboolean dottedlines, passivefocus, res;
896+
897+ /* Hildon: these variables are added for dotted slash drawing
898+ (Hierarchical listbox) */
899+ gint i;
900+ gint node_elements = 64;
901+ gboolean *iter_value = NULL;
902+ GtkTreeIter node_iter, parent_iter;
903
904 g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
905
906@@ -3455,8 +4032,12 @@
907 "vertical_separator", &vertical_separator,
908 "allow_rules", &allow_rules,
909 "focus-line-width", &focus_line_width,
910+ "expander_indent", &expander_indent,
911+ "passive_focus", &passivefocus,
912 NULL);
913
914+ g_object_get (widget, "dotted_lines", &dottedlines, NULL);
915+
916 if (tree_view->priv->tree == NULL)
917 {
918 draw_empty_focus (tree_view, &event->area);
919@@ -3478,6 +4059,8 @@
920 if (node == NULL)
921 return TRUE;
922
923+ iter_value = g_new (gboolean, node_elements);
924+
925 /* find the path for the node */
926 path = _gtk_tree_view_find_path ((GtkTreeView *)widget,
927 tree,
928@@ -3486,11 +4069,25 @@
929 &iter,
930 path);
931 depth = gtk_tree_path_get_depth (path);
932+
933+ node_iter = iter;
934+ for (i = depth - 1; i >= 1; i--)
935+ {
936+ res = gtk_tree_model_iter_parent (tree_view->priv->model, &parent_iter, &node_iter);
937+ /* Check, if we should grow array */
938+ if (i >= node_elements - 1)
939+ {
940+ node_elements *= 2;
941+ iter_value = g_renew (gboolean, iter_value, node_elements);
942+ if (!iter_value)
943+ goto done;
944+ }
945+ iter_value[i] = iter_has_next (tree_view->priv->model, &parent_iter);
946+ node_iter = parent_iter;
947+ }
948+ gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
949 gtk_tree_path_free (path);
950
951- cursor_path = NULL;
952- drag_dest_path = NULL;
953-
954 if (tree_view->priv->cursor)
955 cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
956
957@@ -3533,6 +4130,7 @@
958 do
959 {
960 gboolean parity;
961+ gboolean is_first = TRUE;
962 gboolean is_separator = FALSE;
963
964 if (tree_view->priv->row_separator_func)
965@@ -3570,6 +4168,7 @@
966 GtkTreeViewColumn *column = list->data;
967 const gchar *detail = NULL;
968 GtkStateType state;
969+ gboolean is_last = (rtl ? !list->prev : !list->next);
970
971 if (!column->visible)
972 continue;
973@@ -3660,31 +4259,152 @@
974 else
975 state = GTK_STATE_NORMAL;
976
977- /* Draw background */
978- gtk_paint_flat_box (widget->style,
979- event->window,
980- state,
981- GTK_SHADOW_NONE,
982- &event->area,
983- widget,
984- detail,
985- background_area.x,
986- background_area.y,
987- background_area.width,
988- background_area.height);
989+ if (tree_view->priv->pen_focus)
990+ {
991+ if (node != cursor ||
992+ (!GTK_WIDGET_HAS_FOCUS (widget) && !passivefocus))
993+ {
994+ if ((flags & GTK_CELL_RENDERER_SELECTED)
995+ && !tree_view->priv->checkbox_mode)
996+ state = GTK_STATE_SELECTED;
997+ else
998+ state = GTK_STATE_NORMAL;
999+
1000+ /* Draw background */
1001+ gtk_paint_flat_box (widget->style,
1002+ event->window,
1003+ state,
1004+ GTK_SHADOW_NONE,
1005+ &event->area,
1006+ widget,
1007+ detail,
1008+ background_area.x,
1009+ background_area.y,
1010+ background_area.width,
1011+ background_area.height);
1012+ }
1013+ else if ((flags & GTK_CELL_RENDERER_SELECTED) &&
1014+ !tree_view->priv->checkbox_mode &&
1015+ node != cursor)
1016+ {
1017+ gtk_paint_flat_box (widget->style,
1018+ event->window,
1019+ GTK_STATE_SELECTED,
1020+ GTK_SHADOW_NONE,
1021+ &event->area,
1022+ widget,
1023+ detail,
1024+ background_area.x,
1025+ background_area.y,
1026+ background_area.width,
1027+ background_area.height);
1028+ }
1029+ }
1030+ else
1031+ {
1032+ /* Draw background */
1033+ gtk_paint_flat_box (widget->style,
1034+ event->window,
1035+ state,
1036+ GTK_SHADOW_NONE,
1037+ &event->area,
1038+ widget,
1039+ detail,
1040+ background_area.x,
1041+ background_area.y,
1042+ background_area.width,
1043+ background_area.height);
1044+ }
1045+
1046+ /* Hildon change: drawing focus is moved here because it didn't work
1047+ properly before. Some changes where also made.*/
1048+ /* draw the big row-spanning focus rectangle, if needed */
1049+ if (node == cursor &&
1050+ (!passivefocus || GTK_WIDGET_HAS_FOCUS (widget)))
1051+ {
1052+ gtk_paint_focus (widget->style,
1053+ event->window,
1054+ GTK_STATE_ACTIVE,
1055+ &event->area,
1056+ widget,
1057+ (is_first
1058+ ? (is_last ? "full" : "left")
1059+ : (is_last ? "right" : "middle")),
1060+ background_area.x - (is_first ? 0 : horizontal_separator / 2),
1061+ background_area.y - vertical_separator / 2,
1062+ background_area.width + (is_first ? 0 : (is_last ? horizontal_separator / 2 : horizontal_separator)),
1063+ background_area.height + vertical_separator);
1064+
1065+ is_first = FALSE;
1066+ }
1067+ else if (node == cursor && passivefocus &&
1068+ !GTK_WIDGET_HAS_FOCUS (widget))
1069+ {
1070+ GtkStyle *style = gtk_rc_get_style_by_paths (gtk_widget_get_settings (widget),
1071+ "hildon-focus",
1072+ NULL,
1073+ G_TYPE_NONE);
1074+ gtk_style_attach (style, event->window);
1075+
1076+ gtk_paint_focus (style, event->window, GTK_STATE_SELECTED,
1077+ &event->area, widget,
1078+ (is_first
1079+ ? (is_last ? "full" : "left")
1080+ : (is_last ? "right" : "middle")),
1081+ background_area.x - (is_first ? 0 : horizontal_separator / 2),
1082+ background_area.y - vertical_separator / 2,
1083+ background_area.width + (is_first ? 0 : (is_last ? horizontal_separator / 2 : horizontal_separator)),
1084+ background_area.height + vertical_separator);
1085+
1086+ is_first = FALSE;
1087+ }
1088+
1089+ if (node == cursor)
1090+ {
1091+ gint width, x_offset;
1092+ GtkStateType focus_rect_state;
1093+ focus_rect_state =
1094+ flags & GTK_CELL_RENDERER_FOCUSED ? GTK_STATE_ACTIVE :
1095+ (flags & GTK_CELL_RENDERER_PRELIT ? GTK_STATE_PRELIGHT :
1096+ (flags & GTK_CELL_RENDERER_INSENSITIVE ? GTK_STATE_INSENSITIVE :
1097+ (flags & GTK_CELL_RENDERER_SELECTED ? GTK_STATE_SELECTED :
1098+ GTK_STATE_NORMAL)));
1099+
1100+ gtk_tree_view_get_arrow_xrange (tree_view, tree, &x_offset, NULL);
1101+ gdk_drawable_get_size (tree_view->priv->bin_window, &width, NULL);
1102+ }
1103
1104 if (gtk_tree_view_is_expander_column (tree_view, column) &&
1105 TREE_VIEW_DRAW_EXPANDERS(tree_view))
1106 {
1107+ gint px, px2, py, i;
1108+
1109+ if (depth <= 1)
1110+ px = 0;
1111+ else
1112+ px = (depth - 1) * tree_view->priv->expander_size +
1113+ (depth - 2) * expander_indent;
1114+
1115+ /* Hildonlike hack for making the indent look better.
1116+ * indent is added to all rows except the first one */
1117+
1118 if (!rtl)
1119- cell_area.x += depth * tree_view->priv->expander_size;
1120- cell_area.width -= depth * tree_view->priv->expander_size;
1121+ cell_area.x += depth * tree_view->priv->expander_size + (depth-1) * expander_indent;
1122+ cell_area.width -= depth * tree_view->priv->expander_size + (depth-1) * expander_indent;
1123
1124 /* If we have an expander column, the highlight underline
1125 * starts with that column, so that it indicates which
1126 * level of the tree we're dropping at.
1127 */
1128 highlight_x = cell_area.x;
1129+
1130+ if (!GTK_WIDGET_IS_SENSITIVE (widget))
1131+ {
1132+ flags &= ~ (GTK_CELL_RENDERER_PRELIT + GTK_CELL_RENDERER_INSENSITIVE +
1133+ GTK_CELL_RENDERER_FOCUSED);
1134+ flags &= GTK_CELL_RENDERER_INSENSITIVE;
1135+ }
1136+
1137 if (is_separator)
1138 gtk_paint_hline (widget->style,
1139 event->window,
1140@@ -3702,6 +4422,48 @@
1141 &cell_area,
1142 &event->area,
1143 flags);
1144+
1145+ /* Hildon dotted slash line drawing for Hierarchical Listbox
1146+ widget */
1147+ if (dottedlines)
1148+ {
1149+ py = cell_area.y + cell_area.height / 2;
1150+ px2 = depth * tree_view->priv->expander_size +
1151+ (depth - 1) * expander_indent;
1152+
1153+ gdk_gc_set_line_attributes (widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1154+ 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
1155+
1156+ gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1157+ px, py, px2, py);
1158+
1159+ if (depth > 1)
1160+ {
1161+ gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1162+ px, cell_area.y, px, py);
1163+ if (iter_has_next (tree_view->priv->model, &iter))
1164+ {
1165+ gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1166+ px, py, px, cell_area.y + cell_area.height);
1167+ }
1168+ }
1169+
1170+ if (node->children)
1171+ {
1172+ gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1173+ px2, py, px2, cell_area.y + cell_area.height);
1174+ }
1175+ for (i = depth - 1; i >= 2; i--)
1176+ {
1177+ if (iter_value[i])
1178+ {
1179+ px = (i - 1)* tree_view->priv->expander_size + (i - 2) * expander_indent;
1180+ gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1181+ px, cell_area.y, px, cell_area.y + cell_area.height);
1182+ }
1183+ }
1184+ }
1185+
1186 if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT)
1187 {
1188 gint x, y;
1189@@ -3803,6 +4565,8 @@
1190 }
1191 }
1192
1193+ /* Hildon: disabled this */
1194+#if 0
1195 /* draw the big row-spanning focus rectangle, if needed */
1196 if (!has_special_cell && node == cursor &&
1197 GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS) &&
1198@@ -3830,6 +4594,7 @@
1199 width,
1200 ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node)));
1201 }
1202+#endif
1203
1204 y_offset += max_height;
1205 if (node->children)
1206@@ -3847,6 +4612,17 @@
1207 has_child = gtk_tree_model_iter_children (tree_view->priv->model,
1208 &iter,
1209 &parent);
1210+
1211+ /* Check if we need to grow array */
1212+ if (depth >= node_elements - 1)
1213+ {
1214+ node_elements *= 2;
1215+ iter_value = g_renew (gboolean, iter_value, node_elements);
1216+ if (!iter_value)
1217+ goto done;
1218+ }
1219+ iter_value[depth] = iter_has_next (tree_view->priv->model, &parent);
1220+
1221 depth++;
1222
1223 /* Sanity Check! */
1224@@ -3897,6 +4673,9 @@
1225 if (drag_dest_path)
1226 gtk_tree_path_free (drag_dest_path);
1227
1228+ if (iter_value)
1229+ g_free (iter_value);
1230+
1231 return FALSE;
1232 }
1233
1234@@ -4179,6 +4958,63 @@
1235
1236 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
1237
1238+ /* Special Hildon keyboard interactions */
1239+ if (event->keyval == GDK_Escape)
1240+ gtk_tree_selection_unselect_all (tree_view->priv->selection);
1241+
1242+ if (event->keyval == GDK_Return &&
1243+ gtk_tree_row_reference_valid (tree_view->priv->cursor))
1244+ {
1245+ gboolean force_list_kludge;
1246+
1247+ g_object_get (widget, "force_list_kludge", &force_list_kludge, NULL);
1248+ if (force_list_kludge ||
1249+ (gtk_tree_model_get_flags (tree_view->priv->model) &
1250+ GTK_TREE_MODEL_LIST_ONLY))
1251+ {
1252+ /* text listbox */
1253+ if (tree_view->priv->checkbox_mode)
1254+ {
1255+ /* multisel with checkboxes: select key toggles focused */
1256+ gtk_tree_view_real_toggle_cursor_row (tree_view);
1257+ }
1258+ else
1259+ {
1260+ /* no checkboxes: select key activates focused */
1261+ GtkTreePath *cursor_path =
1262+ gtk_tree_row_reference_get_path (tree_view->priv->cursor);
1263+
1264+ gtk_tree_view_row_activated (tree_view, cursor_path,
1265+ tree_view->priv->focus_column);
1266+
1267+ gtk_tree_path_free (cursor_path);
1268+ }
1269+ }
1270+ else
1271+ {
1272+ /* hierarchical listbox */
1273+ GtkTreePath *cursor_path;
1274+ GtkRBTree *tree;
1275+ GtkRBNode *node;
1276+
1277+ cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
1278+ _gtk_tree_view_find_node (tree_view, cursor_path, &tree, &node);
1279+
1280+ if (node->children == NULL)
1281+ gtk_tree_view_real_expand_row (tree_view,
1282+ cursor_path,
1283+ tree,
1284+ node,
1285+ FALSE, TRUE);
1286+ else
1287+ gtk_tree_view_real_collapse_row (tree_view,
1288+ cursor_path,
1289+ tree,
1290+ node,
1291+ TRUE);
1292+ }
1293+ }
1294+
1295 if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
1296 {
1297 if (event->keyval == GDK_Escape)
1298@@ -4420,6 +5256,7 @@
1299
1300 /* FIXME Is this function necessary? Can I get an enter_notify event
1301 * w/o either an expose event or a mouse motion event?
1302+ * Hildon => it is necessary to make pen dragging work correctly
1303 */
1304 static gboolean
1305 gtk_tree_view_enter_notify (GtkWidget *widget,
1306@@ -4434,6 +5271,10 @@
1307
1308 tree_view = GTK_TREE_VIEW (widget);
1309
1310+ /* stop "automatic" pen dragging */
1311+ tree_view->priv->pen_drag_active = FALSE;
1312+ remove_scroll_timeout (tree_view);
1313+
1314 /* Sanity check it */
1315 if (event->window != tree_view->priv->bin_window)
1316 return FALSE;
1317@@ -4463,6 +5304,9 @@
1318 tree_view = GTK_TREE_VIEW (widget);
1319 tree_view->priv->pressed_button = -1;
1320
1321+ if (tree_view->priv->pen_down && tree_view->priv->queued_select_row == NULL)
1322+ tree_view->priv->pen_drag_active = TRUE;
1323+
1324 if (event->mode == GDK_CROSSING_GRAB)
1325 return TRUE;
1326
1327@@ -4535,6 +5379,7 @@
1328 gboolean retval = FALSE;
1329 gboolean is_separator = FALSE;
1330 gint focus_pad;
1331+ gint expander_indent;
1332
1333 /* double check the row needs validating */
1334 if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) &&
1335@@ -4551,6 +5396,7 @@
1336 gtk_widget_style_get (GTK_WIDGET (tree_view),
1337 "focus-padding", &focus_pad,
1338 "horizontal_separator", &horizontal_separator,
1339+ "expander_indent", &expander_indent,
1340 NULL);
1341
1342 for (list = tree_view->priv->columns; list; list = list->next)
1343@@ -4577,13 +5423,16 @@
1344 {
1345 height = MAX (height, tmp_height);
1346 height = MAX (height, tree_view->priv->expander_size);
1347+
1348+ /* Hildon addition */
1349+ height -= 1;
1350 }
1351 else
1352 height = 2 + 2 * focus_pad;
1353
1354 if (gtk_tree_view_is_expander_column (tree_view, column) && TREE_VIEW_DRAW_EXPANDERS (tree_view))
1355 {
1356- tmp_width = tmp_width + horizontal_separator + depth * (tree_view->priv->expander_size);
1357+ tmp_width = tmp_width + horizontal_separator + depth * (tree_view->priv->expander_size) + (depth - 1) * expander_indent;
1358 }
1359 else
1360 tmp_width = tmp_width + horizontal_separator;
1361@@ -5585,6 +6434,16 @@
1362 #endif /* 0 */
1363
1364 static void
1365+add_scroll_timeout (GtkTreeView *tree_view)
1366+{
1367+ if (tree_view->priv->scroll_timeout == 0)
1368+ {
1369+ tree_view->priv->scroll_timeout =
1370+ g_timeout_add (150, scroll_row_timeout, tree_view);
1371+ }
1372+}
1373+
1374+static void
1375 remove_scroll_timeout (GtkTreeView *tree_view)
1376 {
1377 if (tree_view->priv->scroll_timeout != 0)
1378@@ -6130,10 +6989,9 @@
1379 tree_view->priv->open_dest_timeout =
1380 g_timeout_add (AUTO_EXPAND_TIMEOUT, open_row_timeout, tree_view);
1381 }
1382- else if (tree_view->priv->scroll_timeout == 0)
1383+ else
1384 {
1385- tree_view->priv->scroll_timeout =
1386- g_timeout_add (150, scroll_row_timeout, tree_view);
1387+ add_scroll_timeout (tree_view);
1388 }
1389
1390 if (target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
1391@@ -6901,8 +7759,6 @@
1392 GtkMovementStep step,
1393 gint count)
1394 {
1395- GdkModifierType state;
1396-
1397 g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
1398 g_return_val_if_fail (step == GTK_MOVEMENT_LOGICAL_POSITIONS ||
1399 step == GTK_MOVEMENT_VISUAL_POSITIONS ||
1400@@ -6919,6 +7775,8 @@
1401 GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
1402 gtk_widget_grab_focus (GTK_WIDGET (tree_view));
1403
1404+ /* Hildon: Ignore ctrl and shift */
1405+#if 0
1406 if (gtk_get_current_event_state (&state))
1407 {
1408 if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
1409@@ -6926,6 +7784,7 @@
1410 if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
1411 tree_view->priv->shift_pressed = TRUE;
1412 }
1413+#endif
1414 /* else we assume not pressed */
1415
1416 switch (step)
1417@@ -7092,6 +7951,27 @@
1418 done:
1419 if (!tree_view->priv->fixed_height_mode)
1420 install_presize_handler (tree_view);
1421+
1422+ /* Hildon: has row now been dimmed? If so, unselect it */
1423+ _gtk_tree_view_find_node (tree_view, path, &tree, &node);
1424+ if (!_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
1425+ node,
1426+ path))
1427+ {
1428+ if (gtk_tree_path_compare (path,
1429+ gtk_tree_row_reference_get_path(tree_view->priv->cursor))
1430+ == 0)
1431+ {
1432+ gtk_tree_row_reference_free (tree_view->priv->cursor);
1433+ tree_view->priv->cursor = NULL;
1434+ }
1435+
1436+ gtk_tree_selection_unselect_path (tree_view->priv->selection, path);
1437+ gtk_tree_view_collapse_row (tree_view, path);
1438+ }
1439+
1440+ check_if_can_focus (tree_view);
1441+
1442 if (free_path)
1443 gtk_tree_path_free (path);
1444 }
1445@@ -7196,6 +8076,11 @@
1446 install_presize_handler (tree_view);
1447 if (free_path)
1448 gtk_tree_path_free (path);
1449+
1450+ /* Hildon: after a focusable row has been added, the
1451+ entire widget becomes focusable if it wasn't before */
1452+ if ((GTK_WIDGET_FLAGS (tree_view) & GTK_CAN_FOCUS) == 0)
1453+ check_if_can_focus (tree_view);
1454 }
1455
1456 static void
1457@@ -7295,6 +8180,16 @@
1458 _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, check_selection_helper, data);
1459 }
1460
1461+static gboolean
1462+check_if_can_focus_idle (GtkTreeView *tree_view)
1463+{
1464+ check_if_can_focus (tree_view);
1465+
1466+ tree_view->priv->check_if_can_focus_idle_id = 0;
1467+
1468+ return FALSE;
1469+}
1470+
1471 static void
1472 gtk_tree_view_row_deleted (GtkTreeModel *model,
1473 GtkTreePath *path,
1474@@ -7357,6 +8252,11 @@
1475 tree_view->priv->tree = NULL;
1476
1477 _gtk_rbtree_remove (tree);
1478+
1479+ /* Hildon: no nodes -> not focusable */
1480+ /* FIXME this looks superfluos to me. check_if_can_focus is called
1481+ * at the end of this function .. -- Jorn */
1482+ GTK_WIDGET_UNSET_FLAGS (tree_view, GTK_CAN_FOCUS);
1483 }
1484 else
1485 {
1486@@ -7375,6 +8275,13 @@
1487
1488 if (selection_changed)
1489 g_signal_emit_by_name (tree_view->priv->selection, "changed");
1490+
1491+ /* FIXME whacky hack to work around the treeview not being in a clean state
1492+ * when in a tree a row has been removed, but has_child_toggled not been
1493+ * called yet */
1494+ if (tree_view->priv->check_if_can_focus_idle_id == 0)
1495+ tree_view->priv->check_if_can_focus_idle_id =
1496+ g_idle_add ((GSourceFunc) check_if_can_focus_idle, tree_view);
1497 }
1498
1499 static void
1500@@ -7508,6 +8415,7 @@
1501 GList *list;
1502 GtkTreeViewColumn *tmp_column = NULL;
1503 gint total_width;
1504+ gint expander_indent, depth;
1505 gboolean indent_expanders;
1506 gboolean rtl;
1507
1508@@ -7535,14 +8443,19 @@
1509
1510 gtk_widget_style_get (GTK_WIDGET (tree_view),
1511 "indent_expanders", &indent_expanders,
1512+ "expander_indent", &expander_indent,
1513 NULL);
1514
1515+ /* Hildonlike hack for making the indent look better.
1516+ * indent is added to all rows except the first one */
1517+ depth = _gtk_rbtree_get_depth (tree);
1518+
1519 if (indent_expanders)
1520 {
1521 if (rtl)
1522- x_offset -= tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree);
1523+ x_offset -= tree_view->priv->expander_size * depth + (depth) * expander_indent;
1524 else
1525- x_offset += tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree);
1526+ x_offset += tree_view->priv->expander_size * depth + (depth) * expander_indent;
1527 }
1528 if (x1)
1529 {
1530@@ -7617,9 +8530,11 @@
1531 gboolean retval = FALSE;
1532 gint tmpheight;
1533 gint horizontal_separator;
1534+ gint expander_indent;
1535
1536 gtk_widget_style_get (GTK_WIDGET (tree_view),
1537 "horizontal_separator", &horizontal_separator,
1538+ "expander_indent", &expander_indent,
1539 NULL);
1540
1541 if (height)
1542@@ -7657,7 +8572,7 @@
1543 if (gtk_tree_view_is_expander_column (tree_view, column) &&
1544 TREE_VIEW_DRAW_EXPANDERS (tree_view))
1545 {
1546- if (depth * tree_view->priv->expander_size + horizontal_separator + width > column->requested_width)
1547+ if ((depth - 1) *expander_indent + depth * tree_view->priv->expander_size + horizontal_separator + width > column->requested_width)
1548 {
1549 _gtk_tree_view_column_cell_set_dirty (column, TRUE);
1550 retval = TRUE;
1551@@ -7747,6 +8662,7 @@
1552 }
1553 }
1554
1555+#if 0
1556 static void
1557 gtk_tree_view_clamp_column_visible (GtkTreeView *tree_view,
1558 GtkTreeViewColumn *column)
1559@@ -7762,6 +8678,7 @@
1560 gtk_adjustment_set_value (tree_view->priv->hadjustment,
1561 column->button->allocation.x);
1562 }
1563+#endif
1564
1565 /* This function could be more efficient. I'll optimize it if profiling seems
1566 * to imply that it is important */
1567@@ -8290,7 +9207,7 @@
1568
1569 area.x = x_offset;
1570 area.y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator);
1571- area.width = expander_size + 2;
1572+ area.width = expander_size;
1573 area.height = MAX (CELL_HEIGHT (node, vertical_separator), (expander_size - vertical_separator));
1574
1575 if (node == tree_view->priv->button_pressed_node)
1576@@ -8397,7 +9314,10 @@
1577 GtkRBNode *cursor_node = NULL;
1578 GtkRBTree *new_cursor_tree = NULL;
1579 GtkRBNode *new_cursor_node = NULL;
1580+ GtkRBTree *old_cursor_tree;
1581+ GtkRBNode *old_cursor_node;
1582 GtkTreePath *cursor_path = NULL;
1583+ GtkTreePath *new_cursor_path = NULL;
1584
1585 if (! GTK_WIDGET_HAS_FOCUS (tree_view))
1586 return;
1587@@ -8415,12 +9335,30 @@
1588 if (cursor_tree == NULL)
1589 /* FIXME: we lost the cursor; should we get the first? */
1590 return;
1591- if (count == -1)
1592- _gtk_rbtree_prev_full (cursor_tree, cursor_node,
1593- &new_cursor_tree, &new_cursor_node);
1594- else
1595- _gtk_rbtree_next_full (cursor_tree, cursor_node,
1596- &new_cursor_tree, &new_cursor_node);
1597+
1598+ old_cursor_tree = cursor_tree;
1599+ old_cursor_node = cursor_node;
1600+ do {
1601+ if (count == -1)
1602+ _gtk_rbtree_prev_full (old_cursor_tree, old_cursor_node,
1603+ &new_cursor_tree, &new_cursor_node);
1604+ else
1605+ _gtk_rbtree_next_full (old_cursor_tree, old_cursor_node,
1606+ &new_cursor_tree, &new_cursor_node);
1607+
1608+ if (new_cursor_node)
1609+ {
1610+ if (new_cursor_path)
1611+ gtk_tree_path_free (new_cursor_path);
1612+
1613+ new_cursor_path = _gtk_tree_view_find_path (tree_view, new_cursor_tree, new_cursor_node);
1614+ old_cursor_tree = new_cursor_tree;
1615+ old_cursor_node = new_cursor_node;
1616+ }
1617+ } while (new_cursor_node &&
1618+ !_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
1619+ new_cursor_node,
1620+ new_cursor_path));
1621
1622 /*
1623 * If the list has only one item and multi-selection is set then select
1624@@ -8450,7 +9388,33 @@
1625 if (new_cursor_node)
1626 {
1627 cursor_path = _gtk_tree_view_find_path (tree_view, new_cursor_tree, new_cursor_node);
1628- gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE);
1629+
1630+ if (tree_view->priv->checkbox_mode)
1631+ gtk_tree_view_real_set_cursor (tree_view, cursor_path, FALSE, TRUE);
1632+ else
1633+ gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE);
1634+
1635+ if (tree_view->priv->pen_drag_active)
1636+ {
1637+ if (gtk_tree_path_compare (gtk_tree_row_reference_get_path (tree_view->priv->last_drag_row),
1638+ gtk_tree_row_reference_get_path (tree_view->priv->first_drag_row)) == 0)
1639+ tree_view->priv->pen_drag_reverse = FALSE;
1640+
1641+ if (tree_view->priv->pen_drag_reverse)
1642+ {
1643+ gtk_tree_selection_select_path (tree_view->priv->selection,
1644+ cursor_path);
1645+ gtk_tree_selection_unselect_path (tree_view->priv->selection,
1646+ gtk_tree_row_reference_get_path (tree_view->priv->last_drag_row));
1647+ }
1648+
1649+ gtk_tree_row_reference_free (tree_view->priv->last_drag_row);
1650+
1651+ tree_view->priv->last_drag_row =
1652+ gtk_tree_row_reference_new (tree_view->priv->model,
1653+ cursor_path);
1654+ }
1655+
1656 gtk_tree_path_free (cursor_path);
1657 }
1658 else
1659@@ -8467,6 +9431,8 @@
1660 {
1661 GtkRBTree *cursor_tree = NULL;
1662 GtkRBNode *cursor_node = NULL;
1663+ GtkRBTree *old_cursor_tree = NULL;
1664+ GtkRBNode *old_cursor_node = NULL;
1665 GtkTreePath *cursor_path = NULL;
1666 gint y;
1667 gint vertical_separator;
1668@@ -8474,6 +9440,9 @@
1669 if (! GTK_WIDGET_HAS_FOCUS (tree_view))
1670 return;
1671
1672+ if (tree_view->priv->tree == NULL)
1673+ return;
1674+
1675 if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
1676 cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
1677 else
1678@@ -8504,7 +9473,65 @@
1679
1680 _gtk_rbtree_find_offset (tree_view->priv->tree, y, &cursor_tree, &cursor_node);
1681 cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
1682- g_return_if_fail (cursor_path != NULL);
1683+
1684+ while (cursor_node &&
1685+ !_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
1686+ cursor_node,
1687+ cursor_path))
1688+ {
1689+ old_cursor_tree = cursor_tree;
1690+ old_cursor_node = cursor_node;
1691+
1692+ if (count < 0)
1693+ _gtk_rbtree_prev_full (old_cursor_tree, old_cursor_node,
1694+ &cursor_tree, &cursor_node);
1695+ else
1696+ _gtk_rbtree_next_full (old_cursor_tree, old_cursor_node,
1697+ &cursor_tree, &cursor_node);
1698+
1699+ if (cursor_path)
1700+ {
1701+ gtk_tree_path_free(cursor_path);
1702+ cursor_path = NULL;
1703+ }
1704+
1705+ if (cursor_node)
1706+ cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
1707+ }
1708+
1709+ if (cursor_path == NULL)
1710+ {
1711+ /* looks like we reached the end without finding a sensitive row,
1712+ so search backwards and try to find the last sensitive row as
1713+ the next best thing */
1714+ _gtk_rbtree_find_offset (tree_view->priv->tree, y, &cursor_tree, &cursor_node);
1715+ cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
1716+ while (cursor_node &&
1717+ !_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
1718+ cursor_node,
1719+ cursor_path))
1720+ {
1721+ old_cursor_tree = cursor_tree;
1722+ old_cursor_node = cursor_node;
1723+
1724+ if (count < 0)
1725+ _gtk_rbtree_next_full (old_cursor_tree, old_cursor_node,
1726+ &cursor_tree, &cursor_node);
1727+ else
1728+ _gtk_rbtree_prev_full (old_cursor_tree, old_cursor_node,
1729+ &cursor_tree, &cursor_node);
1730+
1731+ if (cursor_path)
1732+ {
1733+ gtk_tree_path_free(cursor_path);
1734+ cursor_path = NULL;
1735+ }
1736+
1737+ if (cursor_node)
1738+ cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
1739+ }
1740+ }
1741+
1742 gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE);
1743 gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
1744 gtk_tree_path_free (cursor_path);
1745@@ -8514,6 +9541,8 @@
1746 gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
1747 gint count)
1748 {
1749+ /* Hildon: cursor is always displayed on an entire row anyway */
1750+#if 0
1751 GtkRBTree *cursor_tree = NULL;
1752 GtkRBNode *cursor_node = NULL;
1753 GtkTreePath *cursor_path = NULL;
1754@@ -8589,12 +9618,15 @@
1755 g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
1756 }
1757 gtk_tree_view_clamp_column_visible (tree_view, tree_view->priv->focus_column);
1758+#endif
1759 }
1760
1761 static void
1762 gtk_tree_view_move_cursor_start_end (GtkTreeView *tree_view,
1763 gint count)
1764 {
1765+ /* Hildon: cursor is always displayed on an entire row anyway */
1766+#if 0
1767 GtkRBTree *cursor_tree;
1768 GtkRBNode *cursor_node;
1769 GtkTreePath *path;
1770@@ -8631,6 +9663,7 @@
1771 path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
1772 gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
1773 gtk_tree_path_free (path);
1774+#endif
1775 }
1776
1777 static gboolean
1778@@ -8670,7 +9703,7 @@
1779 GtkTreePath *cursor_path = NULL;
1780 GtkTreeSelectMode mode = 0;
1781
1782- if (! GTK_WIDGET_HAS_FOCUS (tree_view))
1783+ if (! GTK_WIDGET_HAS_FOCUS (tree_view) && !tree_view->priv->checkbox_mode)
1784 return FALSE;
1785
1786 if (tree_view->priv->cursor)
1787@@ -8731,7 +9764,7 @@
1788 GtkRBNode *cursor_node = NULL;
1789 GtkTreePath *cursor_path = NULL;
1790
1791- if (! GTK_WIDGET_HAS_FOCUS (tree_view))
1792+ if (! GTK_WIDGET_HAS_FOCUS (tree_view) && !tree_view->priv->checkbox_mode)
1793 return FALSE;
1794
1795 cursor_path = NULL;
1796@@ -8774,6 +9807,7 @@
1797 GtkTreePath *cursor_path = NULL;
1798 GtkRBTree *tree;
1799 GtkRBNode *node;
1800+ gboolean hildon_row;
1801
1802 if (! GTK_WIDGET_HAS_FOCUS (tree_view))
1803 return FALSE;
1804@@ -8796,10 +9830,32 @@
1805 && gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL)
1806 expand = !expand;
1807
1808- if (expand)
1809- gtk_tree_view_real_expand_row (tree_view, cursor_path, tree, node, open_all, TRUE);
1810+ /* Keyboard Navigation: if we can't expand/collapse row, we should either move active focus
1811+ to child item (right arrow) or move active focus to the parent item (left arrow) */
1812+ if (expand)
1813+ {
1814+ hildon_row = gtk_tree_view_real_expand_row (tree_view, cursor_path, tree,
1815+ node, open_all, TRUE);
1816+
1817+ if (!hildon_row || !node->children)
1818+ g_signal_emit_by_name (gtk_widget_get_ancestor (GTK_WIDGET (tree_view),
1819+ GTK_TYPE_WINDOW),
1820+ "move_focus",
1821+ GTK_DIR_TAB_FORWARD);
1822+ }
1823 else
1824- gtk_tree_view_real_collapse_row (tree_view, cursor_path, tree, node, TRUE);
1825+ {
1826+ hildon_row = gtk_tree_view_real_collapse_row (tree_view, cursor_path, tree, node, TRUE);
1827+
1828+ if (hildon_row == FALSE)
1829+ {
1830+ g_signal_emit_by_name (gtk_widget_get_ancestor (GTK_WIDGET(tree_view),
1831+ GTK_TYPE_WINDOW),
1832+ "move_focus",
1833+ GTK_DIR_TAB_BACKWARD);
1834+ gtk_tree_view_real_select_cursor_parent (tree_view);
1835+ }
1836+ }
1837
1838 gtk_tree_path_free (cursor_path);
1839
1840@@ -9327,6 +10383,14 @@
1841 tree_view->priv->last_button_press_2 = NULL;
1842 gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
1843 tree_view->priv->scroll_to_path = NULL;
1844+ gtk_tree_row_reference_free (tree_view->priv->first_drag_row);
1845+ tree_view->priv->first_drag_row = NULL;
1846+ gtk_tree_row_reference_free (tree_view->priv->last_drag_row);
1847+ tree_view->priv->last_drag_row = NULL;
1848+ gtk_tree_row_reference_free (tree_view->priv->queued_expand_row);
1849+ tree_view->priv->queued_expand_row = NULL;
1850+ gtk_tree_row_reference_free (tree_view->priv->queued_select_row);
1851+ tree_view->priv->queued_select_row = NULL;
1852
1853 tree_view->priv->scroll_to_column = NULL;
1854
1855@@ -9402,6 +10466,8 @@
1856 install_presize_handler (tree_view);
1857 }
1858
1859+ check_if_can_focus (tree_view);
1860+
1861 g_object_notify (G_OBJECT (tree_view), "model");
1862
1863 if (GTK_WIDGET_REALIZED (tree_view))
1864@@ -9744,6 +10810,10 @@
1865 G_CALLBACK (column_sizing_notify),
1866 tree_view);
1867
1868+ g_signal_handlers_disconnect_by_func (column,
1869+ G_CALLBACK (update_checkbox_mode),
1870+ tree_view);
1871+
1872 _gtk_tree_view_column_unset_tree_view (column);
1873
1874 tree_view->priv->columns = g_list_remove (tree_view->priv->columns, column);
1875@@ -9773,6 +10843,8 @@
1876 g_object_unref (column);
1877 g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
1878
1879+ update_checkbox_mode (NULL, NULL, tree_view);
1880+
1881 return tree_view->priv->n_columns;
1882 }
1883
1884@@ -9815,6 +10887,9 @@
1885 g_signal_connect (column, "notify::sizing",
1886 G_CALLBACK (column_sizing_notify), tree_view);
1887
1888+ g_signal_connect (column, "notify::visible",
1889+ G_CALLBACK (update_checkbox_mode), tree_view);
1890+
1891 tree_view->priv->columns = g_list_insert (tree_view->priv->columns,
1892 column, position);
1893 tree_view->priv->n_columns++;
1894@@ -9838,6 +10913,9 @@
1895
1896 g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
1897
1898+ update_checkbox_mode (NULL, NULL, tree_view);
1899+ check_if_can_focus (tree_view);
1900+
1901 return tree_view->priv->n_columns;
1902 }
1903
1904@@ -10295,7 +11373,6 @@
1905 GtkTreeViewColumn *column)
1906 {
1907 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
1908-
1909 g_signal_emit (tree_view, tree_view_signals[ROW_ACTIVATED], 0, path, column);
1910 }
1911
1912@@ -10560,6 +11637,16 @@
1913 GtkTreeIter iter;
1914 GtkTreeIter temp;
1915 gboolean expand;
1916+ gint vertical_separator;
1917+ GtkTreePath *collapse_path;
1918+ GtkRBTree *tree2;
1919+ GtkRBNode *node2;
1920+ GtkTreePath *child_path = NULL;
1921+ GtkTreeIter parent_iter;
1922+ GtkTreeIter child_iter;
1923+ GdkRectangle visible_rect;
1924+ gint children, n;
1925+ guint total_height;
1926
1927 remove_auto_expand_timeout (tree_view);
1928
1929@@ -10573,8 +11660,12 @@
1930 if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
1931 return FALSE;
1932
1933+ /* Hildon: insensitive rows cannot be expanded */
1934+ if (!_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
1935+ node, path))
1936+ return FALSE;
1937
1938- if (node->children && open_all)
1939+ if (node->children && open_all)
1940 {
1941 gboolean retval = FALSE;
1942 GtkTreePath *tmp_path = gtk_tree_path_copy (path);
1943@@ -10603,6 +11694,37 @@
1944 return retval;
1945 }
1946
1947+ /* Hildon: collapse other items in the same level */
1948+ gtk_widget_style_get (GTK_WIDGET (tree_view),
1949+ "vertical_separator", &vertical_separator, NULL);
1950+
1951+ /* find the first child */
1952+ collapse_path = gtk_tree_path_copy (path);
1953+ while (gtk_tree_path_prev (collapse_path))
1954+ ;
1955+
1956+ do {
1957+ if (gtk_tree_path_compare (collapse_path, path) != 0)
1958+ {
1959+ _gtk_tree_view_find_node (tree_view, collapse_path, &tree2, &node2);
1960+
1961+ if (tree2 == NULL)
1962+ /* end reached already */
1963+ break;
1964+
1965+ if (node2->children != NULL &&
1966+ gtk_tree_view_real_collapse_row (tree_view, collapse_path,
1967+ tree2, node2, FALSE))
1968+ /* no need to do anything else since only one row may
1969+ be expanded on any particular level at any time */
1970+ break;
1971+ }
1972+
1973+ gtk_tree_path_next (collapse_path);
1974+ } while (1);
1975+
1976+ gtk_tree_path_free (collapse_path);
1977+
1978 g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, &iter, path, &expand);
1979
1980 if (expand)
1981@@ -10643,6 +11765,42 @@
1982 GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED);
1983 }
1984
1985+ /* autoscroll if necessary */
1986+ validate_visible_area (tree_view);
1987+ gtk_tree_model_get_iter (tree_view->priv->model, &parent_iter, path);
1988+ _gtk_tree_view_find_node (tree_view, path, &tree2, &node2);
1989+ validate_row (tree_view, tree2, node2, &parent_iter, path);
1990+ total_height = CELL_HEIGHT (node2, vertical_separator);
1991+ children = gtk_tree_model_iter_n_children (tree_view->priv->model, &parent_iter);
1992+ for (n = 0; n < children; n++)
1993+ {
1994+ gtk_tree_model_iter_nth_child (tree_view->priv->model,
1995+ &child_iter, &parent_iter, n);
1996+
1997+ /* must free here so the path of last child is kept for later */
1998+ if (child_path != NULL)
1999+ gtk_tree_path_free (child_path);
2000+
2001+ child_path = gtk_tree_model_get_path (tree_view->priv->model, &child_iter);
2002+ _gtk_tree_view_find_node (tree_view, child_path, &tree2, &node2);
2003+
2004+ if (CELL_HEIGHT (node2, 0) == 0)
2005+ validate_row (tree_view, tree2, node2, &child_iter, child_path);
2006+
2007+ total_height += CELL_HEIGHT (node2, vertical_separator);
2008+ }
2009+
2010+ gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
2011+
2012+ /* KNOWN BUG: If no autocollapse was performed earlier above, these calls
2013+ to gtk_tree_view_scroll_to_cell do nothing although they should. */
2014+ if (total_height > visible_rect.height)
2015+ gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.0, 0.0);
2016+ else
2017+ gtk_tree_view_scroll_to_cell (tree_view, child_path, NULL, FALSE, 0.0, 0.0);
2018+
2019+ gtk_tree_path_free (child_path);
2020+
2021 install_presize_handler (tree_view);
2022
2023 g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
2024@@ -11070,6 +12228,16 @@
2025 GtkRBTree *tree = NULL;
2026 GtkRBNode *node = NULL;
2027
2028+ _gtk_tree_view_find_node (tree_view, path, &tree, &node);
2029+
2030+ /* Hildon: cursor cannot move to an insensitive row */
2031+ if (!_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
2032+ node, path))
2033+ {
2034+ g_signal_emit (tree_view, tree_view_signals[ROW_INSENSITIVE], 0, path);
2035+ return;
2036+ }
2037+
2038 if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
2039 {
2040 GtkTreePath *cursor_path;
2041@@ -11083,7 +12251,6 @@
2042 tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
2043 tree_view->priv->model,
2044 path);
2045- _gtk_tree_view_find_node (tree_view, path, &tree, &node);
2046 if (tree != NULL)
2047 {
2048 GtkRBTree *new_tree = NULL;
2049@@ -11093,7 +12260,8 @@
2050 {
2051 GtkTreeSelectMode mode = 0;
2052
2053- if (tree_view->priv->ctrl_pressed)
2054+ if (tree_view->priv->ctrl_pressed ||
2055+ tree_view->priv->pen_drag_active)
2056 mode |= GTK_TREE_SELECT_MODE_TOGGLE;
2057 if (tree_view->priv->shift_pressed)
2058 mode |= GTK_TREE_SELECT_MODE_EXTEND;
2059@@ -11213,6 +12381,9 @@
2060 {
2061 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
2062 g_return_if_fail (path != NULL);
2063+
2064+ tree_view->priv->pen_focus = FALSE;
2065+
2066 if (focus_column)
2067 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (focus_column));
2068 if (focus_cell)
2069@@ -11414,6 +12585,7 @@
2070 GtkRBNode *node = NULL;
2071 gint vertical_separator;
2072 gint horizontal_separator;
2073+ gint expander_indent;
2074
2075 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
2076 g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
2077@@ -11424,6 +12596,7 @@
2078 gtk_widget_style_get (GTK_WIDGET (tree_view),
2079 "vertical_separator", &vertical_separator,
2080 "horizontal_separator", &horizontal_separator,
2081+ "expander_indent", &expander_indent,
2082 NULL);
2083
2084 rect->x = 0;
2085@@ -11453,9 +12626,11 @@
2086 TREE_VIEW_DRAW_EXPANDERS (tree_view))
2087 {
2088 gint depth = gtk_tree_path_get_depth (path) - 1;
2089+ gint adjust;
2090
2091- rect->x += depth * tree_view->priv->expander_size;
2092- rect->width -= depth * tree_view->priv->expander_size;
2093+ adjust = depth * tree_view->priv->expander_size + (depth - 1) * expander_indent;
2094+ rect->x += adjust;
2095+ rect->width -= adjust;
2096 rect->width = MAX (rect->width, 0);
2097 }
2098 }
2099@@ -12077,8 +13252,13 @@
2100 if (gtk_tree_view_is_expander_column (tree_view, column) &&
2101 TREE_VIEW_DRAW_EXPANDERS(tree_view))
2102 {
2103- cell_area.x += depth * tree_view->priv->expander_size;
2104- cell_area.width -= depth * tree_view->priv->expander_size;
2105+ gint adjust, expander_indent;
2106+
2107+ gtk_widget_style_get (widget, "expander_indent", &expander_indent, NULL);
2108+
2109+ adjust = depth * tree_view->priv->expander_size + (depth - 1) * expander_indent;
2110+ cell_area.x += adjust;
2111+ cell_area.width -= adjust;
2112 }
2113
2114 if (gtk_tree_view_column_cell_is_visible (column))
2115@@ -13062,3 +14242,138 @@
2116 tree_view->priv->pressed_button = -1;
2117 }
2118
2119+/* Hildon addition: iterates through columns and cells, looks for
2120+ a cell with "activatable" attribute and sets or unsets
2121+ priv->checkbox_mode accordingly (except when checkbox mode
2122+ is disabled by unsetting allow_checkbox_mode).
2123+ */
2124+static void
2125+update_checkbox_mode (GObject *object, GParamSpec *pspec, gpointer data)
2126+{
2127+ GtkTreeView *tree_view = GTK_TREE_VIEW (data);
2128+ GList *columns = gtk_tree_view_get_columns (tree_view);
2129+ GList *list;
2130+ gboolean allow_checkbox_mode;
2131+
2132+ g_object_get (GTK_WIDGET (data),
2133+ "allow_checkbox_mode", &allow_checkbox_mode, NULL);
2134+ g_return_if_fail (allow_checkbox_mode);
2135+
2136+ for (list = columns; list; list = list->next)
2137+ {
2138+ GtkTreeViewColumn *col = GTK_TREE_VIEW_COLUMN (list->data);
2139+ if (gtk_tree_view_column_get_visible (col) &&
2140+ _gtk_tree_view_column_has_activatable_cell (col))
2141+ {
2142+ /* checkbox column found */
2143+ tree_view->priv->checkbox_mode = TRUE;
2144+ g_list_free (columns);
2145+ return;
2146+ }
2147+ }
2148+
2149+ /* no checkbox column was found */
2150+ tree_view->priv->checkbox_mode = FALSE;
2151+ g_list_free (columns);
2152+}
2153+
2154+static void
2155+set_dotted_lines (GtkTreeView *tree_view, gboolean enable)
2156+{
2157+ if (enable != tree_view->priv->dotted_lines)
2158+ {
2159+ tree_view->priv->dotted_lines = enable;
2160+ gtk_widget_queue_draw (GTK_WIDGET (tree_view));
2161+ }
2162+}
2163+
2164+/* This function is used to ensure two things:
2165+ * - in single selection mode, focus will always equal selection
2166+ * - in multiple selection mode, focus is removed if cursor row is
2167+ * explicitly unselected
2168+ */
2169+static void
2170+selection_changed (GtkTreeSelection *selection, gpointer data)
2171+{
2172+ GtkTreeView *tree_view = GTK_TREE_VIEW(data);
2173+ GtkTreePath *cursor_path = NULL;
2174+ GtkTreeIter iter;
2175+
2176+ /* if there are checkboxes, cursor row doesn't have to be selected */
2177+ if (tree_view->priv->checkbox_mode)
2178+ return;
2179+
2180+ if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
2181+ cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
2182+
2183+ if (cursor_path == NULL ||
2184+ !gtk_tree_selection_path_is_selected (selection, cursor_path))
2185+ {
2186+ GtkTreePath *selected_path;
2187+ GtkRBTree *tree = NULL;
2188+ GtkRBNode *node = NULL;
2189+
2190+ if (gtk_tree_selection_get_mode (selection) != GTK_SELECTION_MULTIPLE &&
2191+ gtk_tree_selection_get_selected (selection, NULL, &iter))
2192+ {
2193+ selected_path = gtk_tree_model_get_path (tree_view->priv->model,
2194+ &iter);
2195+ gtk_tree_view_real_set_cursor (tree_view, selected_path, TRUE, TRUE);
2196+ _gtk_tree_view_find_node (tree_view, selected_path, &tree, &node);
2197+ gtk_tree_view_clamp_node_visible (tree_view, tree, node);
2198+ gtk_tree_path_free (selected_path);
2199+ gtk_widget_grab_focus (GTK_WIDGET (tree_view));
2200+ }
2201+ else
2202+ {
2203+ gtk_tree_row_reference_free (tree_view->priv->cursor);
2204+ tree_view->priv->cursor = NULL;
2205+ }
2206+ }
2207+
2208+ if (cursor_path)
2209+ gtk_tree_path_free (cursor_path);
2210+}
2211+
2212+/* Helper function for ensuring that GtkTreeView is focusable
2213+ * if and only if it contains at least one sensitive top-level row.
2214+ * Should be called whenever the existence of a sensitive top-level row
2215+ * might have changed.
2216+ */
2217+static void
2218+check_if_can_focus (GtkTreeView *tree_view)
2219+{
2220+ GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
2221+ GtkTreeIter iter;
2222+
2223+ if (model == NULL || !GTK_WIDGET_MAPPED (tree_view))
2224+ return;
2225+
2226+ if (gtk_tree_model_get_iter_first (model, &iter) == FALSE)
2227+ {
2228+ GTK_WIDGET_UNSET_FLAGS (tree_view, GTK_CAN_FOCUS);
2229+ return;
2230+ }
2231+
2232+ do {
2233+ GtkTreePath *path = gtk_tree_model_get_path (model, &iter);
2234+ GtkRBTree *tree;
2235+ GtkRBNode *node;
2236+
2237+ _gtk_tree_view_find_node (tree_view, path, &tree, &node);
2238+
2239+ if (_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
2240+ node, path))
2241+ {
2242+ GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS);
2243+ if (!gtk_tree_row_reference_valid (tree_view->priv->cursor))
2244+ gtk_tree_view_real_set_cursor (tree_view, path,
2245+ !tree_view->priv->checkbox_mode,
2246+ TRUE);
2247+
2248+ return;
2249+ }
2250+ } while (gtk_tree_model_iter_next (model, &iter));
2251+
2252+ GTK_WIDGET_UNSET_FLAGS (tree_view, GTK_CAN_FOCUS);
2253+}