]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeview.c
More include cleanups
[~andy/gtk] / gtk / gtktreeview.c
1 /* gtktreeview.c
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20
21 #include "config.h"
22
23 #include <math.h>
24 #include <string.h>
25
26 #include "gtktreeview.h"
27 #include "gtkrbtree.h"
28 #include "gtktreednd.h"
29 #include "gtktreeprivate.h"
30 #include "gtkcellrenderer.h"
31 #include "gtkmainprivate.h"
32 #include "gtkmarshalers.h"
33 #include "gtkbuildable.h"
34 #include "gtkbutton.h"
35 #include "gtklabel.h"
36 #include "gtkbox.h"
37 #include "gtkarrow.h"
38 #include "gtkintl.h"
39 #include "gtkbindings.h"
40 #include "gtkcontainer.h"
41 #include "gtkentry.h"
42 #include "gtkframe.h"
43 #include "gtktreemodelsort.h"
44 #include "gtktooltip.h"
45 #include "gtkscrollable.h"
46 #include "gtkcelllayout.h"
47 #include "gtkprivate.h"
48 #include "gtkwidgetprivate.h"
49 #include "gtkentryprivate.h"
50 #include "gtkstylecontextprivate.h"
51 #include "gtktypebuiltins.h"
52 #include "a11y/gtktreeviewaccessible.h"
53
54
55 /**
56  * SECTION:gtktreeview
57  * @Short_description: A widget for displaying both trees and lists
58  * @Title: GtkTreeView
59  * @See_also: #GtkTreeViewColumn, #GtkTreeSelection, #GtkTreeDnd, #GtkTreeMode,
60  *   #GtkTreeSortable, #GtkTreeModelSort, #GtkListStore, #GtkTreeStore,
61  *   #GtkCellRenderer, #GtkCellEditable, #GtkCellRendererPixbuf,
62  *   #GtkCellRendererText, #GtkCellRendererToggle
63  *
64  * Widget that displays any object that implements the #GtkTreeModel interface.
65  *
66  * Please refer to the <link linkend="TreeWidget">tree widget conceptual
67  * overview</link> for an overview of all the objects and data types related
68  * to the tree widget and how they work together.
69  *
70  * Several different coordinate systems are exposed in the GtkTreeView API.
71  * These are:
72  *
73  * <inlinegraphic fileref="tree-view-coordinates.png" format="PNG"></inlinegraphic>
74  * <variablelist><title>Coordinate systems in GtkTreeView API</title>
75  * <varlistentry><term>Widget coordinates</term>
76  * <listitem>
77  * <para>
78  * Coordinates relative to the widget (usually <literal>widget->window</literal>).
79  * </para>
80  * </listitem>
81  * </varlistentry>
82  * <varlistentry><term>Bin window coordinates</term>
83  * <listitem>
84  * <para>
85  * Coordinates relative to the window that GtkTreeView renders to.
86  * </para>
87  * </listitem>
88  * </varlistentry>
89  * <varlistentry><term>Tree coordinates</term>
90  * <listitem>
91  * <para>
92  * Coordinates relative to the entire scrollable area of GtkTreeView. These
93  * coordinates start at (0, 0) for row 0 of the tree.
94  * </para>
95  * </listitem>
96  * </varlistentry>
97  * </variablelist>
98  *
99  * Several functions are available for converting between the different
100  * coordinate systems.  The most common translations are between widget and bin
101  * window coordinates and between bin window and tree coordinates. For the
102  * former you can use gtk_tree_view_convert_widget_to_bin_window_coords()
103  * (and vice versa), for the latter gtk_tree_view_convert_bin_window_to_tree_coords()
104  * (and vice versa).
105  *
106  * <refsect2 id="GtkTreeView-BUILDER-UI">
107  * <title>GtkTreeView as GtkBuildable</title>
108  * The GtkTreeView implementation of the GtkBuildable interface accepts
109  * #GtkTreeViewColumn objects as &lt;child&gt; elements and exposes the
110  * internal #GtkTreeSelection in UI definitions.
111  * <example>
112  * <title>A UI definition fragment with GtkTreeView</title>
113  * <programlisting><![CDATA[
114  * <object class="GtkTreeView" id="treeview">
115  *   <property name="model">liststore1</property>
116  *   <child>
117  *     <object class="GtkTreeViewColumn" id="test-column">
118  *       <property name="title">Test</property>
119  *       <child>
120  *         <object class="GtkCellRendererText" id="test-renderer"/>
121  *         <attributes>
122  *           <attribute name="text">1</attribute>
123  *         </attributes>
124  *       </child>
125  *     </object>
126  *   </child>
127  *   <child internal-child="selection">
128  *     <object class="GtkTreeSelection" id="selection">
129  *       <signal name="changed" handler="on_treeview_selection_changed"/>
130  *     </object>
131  *   </child>
132  * </object>
133  * ]]></programlisting>
134  * </example>
135  * </refsect2>
136  */
137
138 enum
139 {
140   DRAG_COLUMN_WINDOW_STATE_UNSET = 0,
141   DRAG_COLUMN_WINDOW_STATE_ORIGINAL = 1,
142   DRAG_COLUMN_WINDOW_STATE_ARROW = 2,
143   DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT = 3,
144   DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT = 4
145 };
146
147 enum
148 {
149   RUBBER_BAND_OFF = 0,
150   RUBBER_BAND_MAYBE_START = 1,
151   RUBBER_BAND_ACTIVE = 2
152 };
153
154  /* This lovely little value is used to determine how far away from the title bar
155   * you can move the mouse and still have a column drag work.
156   */
157 #define TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER(tree_view) (10*gtk_tree_view_get_effective_header_height(tree_view))
158
159 #ifdef __GNUC__
160
161 #define TREE_VIEW_INTERNAL_ASSERT(expr, ret)     G_STMT_START{          \
162      if (!(expr))                                                       \
163        {                                                                \
164          g_log (G_LOG_DOMAIN,                                           \
165                 G_LOG_LEVEL_CRITICAL,                                   \
166                 "%s (%s): assertion `%s' failed.\n"                     \
167                 "There is a disparity between the internal view of the GtkTreeView,\n"    \
168                 "and the GtkTreeModel.  This generally means that the model has changed\n"\
169                 "without letting the view know.  Any display from now on is likely to\n"  \
170                 "be incorrect.\n",                                                        \
171                 G_STRLOC,                                               \
172                 G_STRFUNC,                                              \
173                 #expr);                                                 \
174          return ret;                                                    \
175        };                               }G_STMT_END
176
177 #define TREE_VIEW_INTERNAL_ASSERT_VOID(expr)     G_STMT_START{          \
178      if (!(expr))                                                       \
179        {                                                                \
180          g_log (G_LOG_DOMAIN,                                           \
181                 G_LOG_LEVEL_CRITICAL,                                   \
182                 "%s (%s): assertion `%s' failed.\n"                     \
183                 "There is a disparity between the internal view of the GtkTreeView,\n"    \
184                 "and the GtkTreeModel.  This generally means that the model has changed\n"\
185                 "without letting the view know.  Any display from now on is likely to\n"  \
186                 "be incorrect.\n",                                                        \
187                 G_STRLOC,                                               \
188                 G_STRFUNC,                                              \
189                 #expr);                                                 \
190          return;                                                        \
191        };                               }G_STMT_END
192
193 #else
194
195 #define TREE_VIEW_INTERNAL_ASSERT(expr, ret)     G_STMT_START{          \
196      if (!(expr))                                                       \
197        {                                                                \
198          g_log (G_LOG_DOMAIN,                                           \
199                 G_LOG_LEVEL_CRITICAL,                                   \
200                 "file %s: line %d: assertion `%s' failed.\n"       \
201                 "There is a disparity between the internal view of the GtkTreeView,\n"    \
202                 "and the GtkTreeModel.  This generally means that the model has changed\n"\
203                 "without letting the view know.  Any display from now on is likely to\n"  \
204                 "be incorrect.\n",                                                        \
205                 __FILE__,                                               \
206                 __LINE__,                                               \
207                 #expr);                                                 \
208          return ret;                                                    \
209        };                               }G_STMT_END
210
211 #define TREE_VIEW_INTERNAL_ASSERT_VOID(expr)     G_STMT_START{          \
212      if (!(expr))                                                       \
213        {                                                                \
214          g_log (G_LOG_DOMAIN,                                           \
215                 G_LOG_LEVEL_CRITICAL,                                   \
216                 "file %s: line %d: assertion '%s' failed.\n"            \
217                 "There is a disparity between the internal view of the GtkTreeView,\n"    \
218                 "and the GtkTreeModel.  This generally means that the model has changed\n"\
219                 "without letting the view know.  Any display from now on is likely to\n"  \
220                 "be incorrect.\n",                                                        \
221                 __FILE__,                                               \
222                 __LINE__,                                               \
223                 #expr);                                                 \
224          return;                                                        \
225        };                               }G_STMT_END
226 #endif
227
228 #define GTK_TREE_VIEW_PRIORITY_VALIDATE (GDK_PRIORITY_REDRAW + 5)
229 #define GTK_TREE_VIEW_PRIORITY_SCROLL_SYNC (GTK_TREE_VIEW_PRIORITY_VALIDATE + 2)
230 #define GTK_TREE_VIEW_TIME_MS_PER_IDLE 30
231 #define SCROLL_EDGE_SIZE 15
232 #define EXPANDER_EXTRA_PADDING 4
233 #define GTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT 5000
234 #define AUTO_EXPAND_TIMEOUT 500
235
236 /* Translate from bin_window coordinates to rbtree (tree coordinates) and
237  * vice versa.
238  */
239 #define TREE_WINDOW_Y_TO_RBTREE_Y(tree_view,y) ((y) + tree_view->priv->dy)
240 #define RBTREE_Y_TO_TREE_WINDOW_Y(tree_view,y) ((y) - tree_view->priv->dy)
241
242 typedef struct _GtkTreeViewColumnReorder GtkTreeViewColumnReorder;
243 struct _GtkTreeViewColumnReorder
244 {
245   gint left_align;
246   gint right_align;
247   GtkTreeViewColumn *left_column;
248   GtkTreeViewColumn *right_column;
249 };
250
251 typedef struct _GtkTreeViewChild GtkTreeViewChild;
252 struct _GtkTreeViewChild
253 {
254   GtkWidget *widget;
255   gint x;
256   gint y;
257   gint width;
258   gint height;
259 };
260
261
262 typedef struct _TreeViewDragInfo TreeViewDragInfo;
263 struct _TreeViewDragInfo
264 {
265   GdkModifierType start_button_mask;
266   GtkTargetList *_unused_source_target_list;
267   GdkDragAction source_actions;
268
269   GtkTargetList *_unused_dest_target_list;
270
271   guint source_set : 1;
272   guint dest_set : 1;
273 };
274
275
276 struct _GtkTreeViewPrivate
277 {
278   GtkTreeModel *model;
279
280   /* tree information */
281   GtkRBTree *tree;
282
283   /* Container info */
284   GList *children;
285   gint width;
286   gint height;
287
288   /* Adjustments */
289   GtkAdjustment *hadjustment;
290   GtkAdjustment *vadjustment;
291   gint           min_display_width;
292   gint           min_display_height;
293
294   /* Sub windows */
295   GdkWindow *bin_window;
296   GdkWindow *header_window;
297
298   /* Scroll position state keeping */
299   GtkTreeRowReference *top_row;
300   gint top_row_dy;
301   /* dy == y pos of top_row + top_row_dy */
302   /* we cache it for simplicity of the code */
303   gint dy;
304
305   guint presize_handler_timer;
306   guint validate_rows_timer;
307   guint scroll_sync_timer;
308
309   /* Indentation and expander layout */
310   gint expander_size;
311   GtkTreeViewColumn *expander_column;
312
313   gint level_indentation;
314
315   /* Key navigation (focus), selection */
316   gint cursor_offset;
317
318   GtkTreeRowReference *anchor;
319   GtkTreeRowReference *cursor;
320
321   GtkTreeViewColumn *focus_column;
322
323   /* Current pressed node, previously pressed, prelight */
324   GtkRBNode *button_pressed_node;
325   GtkRBTree *button_pressed_tree;
326
327   gint pressed_button;
328   gint press_start_x;
329   gint press_start_y;
330
331   gint event_last_x;
332   gint event_last_y;
333
334   guint last_button_time;
335   gint last_button_x;
336   gint last_button_y;
337
338   GtkRBNode *prelight_node;
339   GtkRBTree *prelight_tree;
340
341   /* Cell Editing */
342   GtkTreeViewColumn *edited_column;
343
344   /* The node that's currently being collapsed or expanded */
345   GtkRBNode *expanded_collapsed_node;
346   GtkRBTree *expanded_collapsed_tree;
347   guint expand_collapse_timeout;
348
349   /* Auto expand/collapse timeout in hover mode */
350   guint auto_expand_timeout;
351
352   /* Selection information */
353   GtkTreeSelection *selection;
354
355   /* Header information */
356   gint n_columns;
357   GList *columns;
358   gint header_height;
359
360   GtkTreeViewColumnDropFunc column_drop_func;
361   gpointer column_drop_func_data;
362   GDestroyNotify column_drop_func_data_destroy;
363   GList *column_drag_info;
364   GtkTreeViewColumnReorder *cur_reorder;
365
366   gint prev_width_before_expander;
367
368   /* Interactive Header reordering */
369   GdkWindow *drag_window;
370   GdkWindow *drag_highlight_window;
371   GtkTreeViewColumn *drag_column;
372   gint drag_column_x;
373
374   /* Interactive Header Resizing */
375   gint drag_pos;
376   gint x_drag;
377
378   /* Non-interactive Header Resizing, expand flag support */
379   gint prev_width;
380
381   gint last_extra_space;
382   gint last_extra_space_per_column;
383   gint last_number_of_expand_columns;
384
385   /* ATK Hack */
386   GtkTreeDestroyCountFunc destroy_count_func;
387   gpointer destroy_count_data;
388   GDestroyNotify destroy_count_destroy;
389
390   /* Scroll timeout (e.g. during dnd, rubber banding) */
391   guint scroll_timeout;
392
393   /* Row drag-and-drop */
394   GtkTreeRowReference *drag_dest_row;
395   GtkTreeViewDropPosition drag_dest_pos;
396   guint open_dest_timeout;
397
398   /* Rubber banding */
399   gint rubber_band_status;
400   gint rubber_band_x;
401   gint rubber_band_y;
402   gint rubber_band_shift;
403   gint rubber_band_ctrl;
404
405   GtkRBNode *rubber_band_start_node;
406   GtkRBTree *rubber_band_start_tree;
407
408   GtkRBNode *rubber_band_end_node;
409   GtkRBTree *rubber_band_end_tree;
410
411   /* fixed height */
412   gint fixed_height;
413
414   /* Scroll-to functionality when unrealized */
415   GtkTreeRowReference *scroll_to_path;
416   GtkTreeViewColumn *scroll_to_column;
417   gfloat scroll_to_row_align;
418   gfloat scroll_to_col_align;
419
420   /* Interactive search */
421   gint selected_iter;
422   gint search_column;
423   GtkTreeViewSearchPositionFunc search_position_func;
424   GtkTreeViewSearchEqualFunc search_equal_func;
425   gpointer search_user_data;
426   GDestroyNotify search_destroy;
427   gpointer search_position_user_data;
428   GDestroyNotify search_position_destroy;
429   GtkWidget *search_window;
430   GtkWidget *search_entry;
431   gulong search_entry_changed_id;
432   guint typeselect_flush_timeout;
433
434   /* Grid and tree lines */
435   GtkTreeViewGridLines grid_lines;
436   double grid_line_dashes[2];
437   int grid_line_width;
438
439   gboolean tree_lines_enabled;
440   double tree_line_dashes[2];
441   int tree_line_width;
442
443   /* Row separators */
444   GtkTreeViewRowSeparatorFunc row_separator_func;
445   gpointer row_separator_data;
446   GDestroyNotify row_separator_destroy;
447
448   /* Tooltip support */
449   gint tooltip_column;
450
451   /* Here comes the bitfield */
452   guint scroll_to_use_align : 1;
453
454   guint fixed_height_mode : 1;
455   guint fixed_height_check : 1;
456
457   guint reorderable : 1;
458   guint header_has_focus : 1;
459   guint drag_column_window_state : 3;
460   /* hint to display rows in alternating colors */
461   guint has_rules : 1;
462   guint mark_rows_col_dirty : 1;
463
464   /* for DnD */
465   guint empty_view_drop : 1;
466
467   guint ctrl_pressed : 1;
468   guint shift_pressed : 1;
469
470   guint init_hadjust_value : 1;
471
472   guint in_top_row_to_dy : 1;
473
474   /* interactive search */
475   guint enable_search : 1;
476   guint disable_popdown : 1;
477   guint search_custom_entry_set : 1;
478   
479   guint hover_selection : 1;
480   guint hover_expand : 1;
481   guint imcontext_changed : 1;
482
483   guint rubber_banding_enable : 1;
484
485   guint in_grab : 1;
486
487   guint post_validation_flag : 1;
488
489   /* Whether our key press handler is to avoid sending an unhandled binding to the search entry */
490   guint search_entry_avoid_unhandled_binding : 1;
491
492   /* GtkScrollablePolicy needs to be checked when
493    * driving the scrollable adjustment values */
494   guint hscroll_policy : 1;
495   guint vscroll_policy : 1;
496
497   /* GtkTreeView flags */
498   guint is_list : 1;
499   guint show_expanders : 1;
500   guint in_column_resize : 1;
501   guint arrow_prelit : 1;
502   guint headers_visible : 1;
503   guint draw_keyfocus : 1;
504   guint model_setup : 1;
505   guint in_column_drag : 1;
506 };
507
508
509 /* Signals */
510 enum
511 {
512   ROW_ACTIVATED,
513   TEST_EXPAND_ROW,
514   TEST_COLLAPSE_ROW,
515   ROW_EXPANDED,
516   ROW_COLLAPSED,
517   COLUMNS_CHANGED,
518   CURSOR_CHANGED,
519   MOVE_CURSOR,
520   SELECT_ALL,
521   UNSELECT_ALL,
522   SELECT_CURSOR_ROW,
523   TOGGLE_CURSOR_ROW,
524   EXPAND_COLLAPSE_CURSOR_ROW,
525   SELECT_CURSOR_PARENT,
526   START_INTERACTIVE_SEARCH,
527   LAST_SIGNAL
528 };
529
530 /* Properties */
531 enum {
532   PROP_0,
533   PROP_MODEL,
534   PROP_HADJUSTMENT,
535   PROP_VADJUSTMENT,
536   PROP_HSCROLL_POLICY,
537   PROP_VSCROLL_POLICY,
538   PROP_HEADERS_VISIBLE,
539   PROP_HEADERS_CLICKABLE,
540   PROP_EXPANDER_COLUMN,
541   PROP_REORDERABLE,
542   PROP_RULES_HINT,
543   PROP_ENABLE_SEARCH,
544   PROP_SEARCH_COLUMN,
545   PROP_FIXED_HEIGHT_MODE,
546   PROP_HOVER_SELECTION,
547   PROP_HOVER_EXPAND,
548   PROP_SHOW_EXPANDERS,
549   PROP_LEVEL_INDENTATION,
550   PROP_RUBBER_BANDING,
551   PROP_ENABLE_GRID_LINES,
552   PROP_ENABLE_TREE_LINES,
553   PROP_TOOLTIP_COLUMN
554 };
555
556 /* object signals */
557 static void     gtk_tree_view_finalize             (GObject          *object);
558 static void     gtk_tree_view_set_property         (GObject         *object,
559                                                     guint            prop_id,
560                                                     const GValue    *value,
561                                                     GParamSpec      *pspec);
562 static void     gtk_tree_view_get_property         (GObject         *object,
563                                                     guint            prop_id,
564                                                     GValue          *value,
565                                                     GParamSpec      *pspec);
566
567 /* gtkwidget signals */
568 static void     gtk_tree_view_destroy              (GtkWidget        *widget);
569 static void     gtk_tree_view_realize              (GtkWidget        *widget);
570 static void     gtk_tree_view_unrealize            (GtkWidget        *widget);
571 static void     gtk_tree_view_map                  (GtkWidget        *widget);
572 static void     gtk_tree_view_get_preferred_width  (GtkWidget        *widget,
573                                                     gint             *minimum,
574                                                     gint             *natural);
575 static void     gtk_tree_view_get_preferred_height (GtkWidget        *widget,
576                                                     gint             *minimum,
577                                                     gint             *natural);
578 static void     gtk_tree_view_size_request         (GtkWidget        *widget,
579                                                     GtkRequisition   *requisition,
580                                                     gboolean          may_validate);
581 static void     gtk_tree_view_size_allocate        (GtkWidget        *widget,
582                                                     GtkAllocation    *allocation);
583 static gboolean gtk_tree_view_draw                 (GtkWidget        *widget,
584                                                     cairo_t          *cr);
585 static gboolean gtk_tree_view_key_press            (GtkWidget        *widget,
586                                                     GdkEventKey      *event);
587 static gboolean gtk_tree_view_key_release          (GtkWidget        *widget,
588                                                     GdkEventKey      *event);
589 static gboolean gtk_tree_view_motion               (GtkWidget        *widget,
590                                                     GdkEventMotion   *event);
591 static gboolean gtk_tree_view_enter_notify         (GtkWidget        *widget,
592                                                     GdkEventCrossing *event);
593 static gboolean gtk_tree_view_leave_notify         (GtkWidget        *widget,
594                                                     GdkEventCrossing *event);
595 static gboolean gtk_tree_view_button_press         (GtkWidget        *widget,
596                                                     GdkEventButton   *event);
597 static gboolean gtk_tree_view_button_release       (GtkWidget        *widget,
598                                                     GdkEventButton   *event);
599 static gboolean gtk_tree_view_grab_broken          (GtkWidget          *widget,
600                                                     GdkEventGrabBroken *event);
601 #if 0
602 static gboolean gtk_tree_view_configure            (GtkWidget         *widget,
603                                                     GdkEventConfigure *event);
604 #endif
605
606 static GtkWidgetPath * gtk_tree_view_get_path_for_child (GtkContainer *container,
607                                                          GtkWidget    *child);
608
609 static void     gtk_tree_view_set_focus_child      (GtkContainer     *container,
610                                                     GtkWidget        *child);
611 static gint     gtk_tree_view_focus_out            (GtkWidget        *widget,
612                                                     GdkEventFocus    *event);
613 static gint     gtk_tree_view_focus                (GtkWidget        *widget,
614                                                     GtkDirectionType  direction);
615 static void     gtk_tree_view_grab_focus           (GtkWidget        *widget);
616 static void     gtk_tree_view_style_updated        (GtkWidget        *widget);
617 static void     gtk_tree_view_grab_notify          (GtkWidget        *widget,
618                                                     gboolean          was_grabbed);
619 static void     gtk_tree_view_state_flags_changed  (GtkWidget        *widget,
620                                                     GtkStateFlags     previous_state);
621
622 /* container signals */
623 static void     gtk_tree_view_remove               (GtkContainer     *container,
624                                                     GtkWidget        *widget);
625 static void     gtk_tree_view_forall               (GtkContainer     *container,
626                                                     gboolean          include_internals,
627                                                     GtkCallback       callback,
628                                                     gpointer          callback_data);
629
630 /* Source side drag signals */
631 static void gtk_tree_view_drag_begin       (GtkWidget        *widget,
632                                             GdkDragContext   *context);
633 static void gtk_tree_view_drag_end         (GtkWidget        *widget,
634                                             GdkDragContext   *context);
635 static void gtk_tree_view_drag_data_get    (GtkWidget        *widget,
636                                             GdkDragContext   *context,
637                                             GtkSelectionData *selection_data,
638                                             guint             info,
639                                             guint             time);
640 static void gtk_tree_view_drag_data_delete (GtkWidget        *widget,
641                                             GdkDragContext   *context);
642
643 /* Target side drag signals */
644 static void     gtk_tree_view_drag_leave         (GtkWidget        *widget,
645                                                   GdkDragContext   *context,
646                                                   guint             time);
647 static gboolean gtk_tree_view_drag_motion        (GtkWidget        *widget,
648                                                   GdkDragContext   *context,
649                                                   gint              x,
650                                                   gint              y,
651                                                   guint             time);
652 static gboolean gtk_tree_view_drag_drop          (GtkWidget        *widget,
653                                                   GdkDragContext   *context,
654                                                   gint              x,
655                                                   gint              y,
656                                                   guint             time);
657 static void     gtk_tree_view_drag_data_received (GtkWidget        *widget,
658                                                   GdkDragContext   *context,
659                                                   gint              x,
660                                                   gint              y,
661                                                   GtkSelectionData *selection_data,
662                                                   guint             info,
663                                                   guint             time);
664
665 /* tree_model signals */
666 static void     gtk_tree_view_set_hadjustment             (GtkTreeView     *tree_view,
667                                                            GtkAdjustment   *adjustment);
668 static void     gtk_tree_view_set_vadjustment             (GtkTreeView     *tree_view,
669                                                            GtkAdjustment   *adjustment);
670 static gboolean gtk_tree_view_real_move_cursor            (GtkTreeView     *tree_view,
671                                                            GtkMovementStep  step,
672                                                            gint             count);
673 static gboolean gtk_tree_view_real_select_all             (GtkTreeView     *tree_view);
674 static gboolean gtk_tree_view_real_unselect_all           (GtkTreeView     *tree_view);
675 static gboolean gtk_tree_view_real_select_cursor_row      (GtkTreeView     *tree_view,
676                                                            gboolean         start_editing);
677 static gboolean gtk_tree_view_real_toggle_cursor_row      (GtkTreeView     *tree_view);
678 static gboolean gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView     *tree_view,
679                                                                gboolean         logical,
680                                                                gboolean         expand,
681                                                                gboolean         open_all);
682 static gboolean gtk_tree_view_real_select_cursor_parent   (GtkTreeView     *tree_view);
683 static void gtk_tree_view_row_changed                     (GtkTreeModel    *model,
684                                                            GtkTreePath     *path,
685                                                            GtkTreeIter     *iter,
686                                                            gpointer         data);
687 static void gtk_tree_view_row_inserted                    (GtkTreeModel    *model,
688                                                            GtkTreePath     *path,
689                                                            GtkTreeIter     *iter,
690                                                            gpointer         data);
691 static void gtk_tree_view_row_has_child_toggled           (GtkTreeModel    *model,
692                                                            GtkTreePath     *path,
693                                                            GtkTreeIter     *iter,
694                                                            gpointer         data);
695 static void gtk_tree_view_row_deleted                     (GtkTreeModel    *model,
696                                                            GtkTreePath     *path,
697                                                            gpointer         data);
698 static void gtk_tree_view_rows_reordered                  (GtkTreeModel    *model,
699                                                            GtkTreePath     *parent,
700                                                            GtkTreeIter     *iter,
701                                                            gint            *new_order,
702                                                            gpointer         data);
703
704 /* Incremental reflow */
705 static gboolean validate_row             (GtkTreeView *tree_view,
706                                           GtkRBTree   *tree,
707                                           GtkRBNode   *node,
708                                           GtkTreeIter *iter,
709                                           GtkTreePath *path);
710 static void     validate_visible_area    (GtkTreeView *tree_view);
711 static gboolean validate_rows_handler    (GtkTreeView *tree_view);
712 static gboolean do_validate_rows         (GtkTreeView *tree_view,
713                                           gboolean     size_request);
714 static gboolean validate_rows            (GtkTreeView *tree_view);
715 static gboolean presize_handler_callback (gpointer     data);
716 static void     install_presize_handler  (GtkTreeView *tree_view);
717 static void     install_scroll_sync_handler (GtkTreeView *tree_view);
718 static void     gtk_tree_view_set_top_row   (GtkTreeView *tree_view,
719                                              GtkTreePath *path,
720                                              gint         offset);
721 static void     gtk_tree_view_dy_to_top_row (GtkTreeView *tree_view);
722 static void     gtk_tree_view_top_row_to_dy (GtkTreeView *tree_view);
723 static void     invalidate_empty_focus      (GtkTreeView *tree_view);
724
725 /* Internal functions */
726 static gboolean gtk_tree_view_is_expander_column             (GtkTreeView        *tree_view,
727                                                               GtkTreeViewColumn  *column);
728 static inline gboolean gtk_tree_view_draw_expanders          (GtkTreeView        *tree_view);
729 static void     gtk_tree_view_add_move_binding               (GtkBindingSet      *binding_set,
730                                                               guint               keyval,
731                                                               guint               modmask,
732                                                               gboolean            add_shifted_binding,
733                                                               GtkMovementStep     step,
734                                                               gint                count);
735 static gint     gtk_tree_view_unref_and_check_selection_tree (GtkTreeView        *tree_view,
736                                                               GtkRBTree          *tree);
737 static void     gtk_tree_view_queue_draw_path                (GtkTreeView        *tree_view,
738                                                               GtkTreePath        *path,
739                                                               const GdkRectangle *clip_rect);
740 static void     gtk_tree_view_queue_draw_arrow               (GtkTreeView        *tree_view,
741                                                               GtkRBTree          *tree,
742                                                               GtkRBNode          *node);
743 static void     gtk_tree_view_draw_arrow                     (GtkTreeView        *tree_view,
744                                                               cairo_t            *cr,
745                                                               GtkRBTree          *tree,
746                                                               GtkRBNode          *node,
747                                                               gint                x,
748                                                               gint                y);
749 static void     gtk_tree_view_get_arrow_xrange               (GtkTreeView        *tree_view,
750                                                               GtkRBTree          *tree,
751                                                               gint               *x1,
752                                                               gint               *x2);
753 static gint     gtk_tree_view_new_column_width               (GtkTreeView        *tree_view,
754                                                               gint                i,
755                                                               gint               *x);
756 static void     gtk_tree_view_adjustment_changed             (GtkAdjustment      *adjustment,
757                                                               GtkTreeView        *tree_view);
758 static void     gtk_tree_view_build_tree                     (GtkTreeView        *tree_view,
759                                                               GtkRBTree          *tree,
760                                                               GtkTreeIter        *iter,
761                                                               gint                depth,
762                                                               gboolean            recurse);
763 static void     gtk_tree_view_clamp_node_visible             (GtkTreeView        *tree_view,
764                                                               GtkRBTree          *tree,
765                                                               GtkRBNode          *node);
766 static void     gtk_tree_view_clamp_column_visible           (GtkTreeView        *tree_view,
767                                                               GtkTreeViewColumn  *column,
768                                                               gboolean            focus_to_cell);
769 static gboolean gtk_tree_view_maybe_begin_dragging_row       (GtkTreeView        *tree_view,
770                                                               GdkEventMotion     *event);
771 static void     gtk_tree_view_focus_to_cursor                (GtkTreeView        *tree_view);
772 static void     gtk_tree_view_move_cursor_up_down            (GtkTreeView        *tree_view,
773                                                               gint                count);
774 static void     gtk_tree_view_move_cursor_page_up_down       (GtkTreeView        *tree_view,
775                                                               gint                count);
776 static void     gtk_tree_view_move_cursor_left_right         (GtkTreeView        *tree_view,
777                                                               gint                count);
778 static void     gtk_tree_view_move_cursor_start_end          (GtkTreeView        *tree_view,
779                                                               gint                count);
780 static gboolean gtk_tree_view_real_collapse_row              (GtkTreeView        *tree_view,
781                                                               GtkTreePath        *path,
782                                                               GtkRBTree          *tree,
783                                                               GtkRBNode          *node,
784                                                               gboolean            animate);
785 static gboolean gtk_tree_view_real_expand_row                (GtkTreeView        *tree_view,
786                                                               GtkTreePath        *path,
787                                                               GtkRBTree          *tree,
788                                                               GtkRBNode          *node,
789                                                               gboolean            open_all,
790                                                               gboolean            animate);
791 static void     gtk_tree_view_real_set_cursor                (GtkTreeView        *tree_view,
792                                                               GtkTreePath        *path,
793                                                               gboolean            clear_and_select,
794                                                               gboolean            clamp_node);
795 static gboolean gtk_tree_view_has_can_focus_cell             (GtkTreeView        *tree_view);
796 static void     column_sizing_notify                         (GObject            *object,
797                                                               GParamSpec         *pspec,
798                                                               gpointer            data);
799 static void     gtk_tree_view_stop_rubber_band               (GtkTreeView        *tree_view);
800 static void     update_prelight                              (GtkTreeView        *tree_view,
801                                                               int                 x,
802                                                               int                 y);
803
804 static inline gint gtk_tree_view_get_effective_header_height (GtkTreeView *tree_view);
805
806 static inline gint gtk_tree_view_get_cell_area_y_offset      (GtkTreeView *tree_view,
807                                                               GtkRBTree   *tree,
808                                                               GtkRBNode   *node,
809                                                               gint         vertical_separator);
810 static inline gint gtk_tree_view_get_cell_area_height        (GtkTreeView *tree_view,
811                                                               GtkRBNode   *node,
812                                                               gint         vertical_separator);
813
814 static inline gint gtk_tree_view_get_row_y_offset            (GtkTreeView *tree_view,
815                                                               GtkRBTree   *tree,
816                                                               GtkRBNode   *node);
817 static inline gint gtk_tree_view_get_row_height              (GtkTreeView *tree_view,
818                                                               GtkRBNode   *node);
819
820 /* interactive search */
821 static void     gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view);
822 static void     gtk_tree_view_search_dialog_hide        (GtkWidget        *search_dialog,
823                                                          GtkTreeView      *tree_view,
824                                                          GdkDevice        *device);
825 static void     gtk_tree_view_search_position_func      (GtkTreeView      *tree_view,
826                                                          GtkWidget        *search_dialog,
827                                                          gpointer          user_data);
828 static void     gtk_tree_view_search_disable_popdown    (GtkEntry         *entry,
829                                                          GtkMenu          *menu,
830                                                          gpointer          data);
831 static void     gtk_tree_view_search_preedit_changed    (GtkIMContext     *im_context,
832                                                          GtkTreeView      *tree_view);
833 static void     gtk_tree_view_search_activate           (GtkEntry         *entry,
834                                                          GtkTreeView      *tree_view);
835 static gboolean gtk_tree_view_real_search_enable_popdown(gpointer          data);
836 static void     gtk_tree_view_search_enable_popdown     (GtkWidget        *widget,
837                                                          gpointer          data);
838 static gboolean gtk_tree_view_search_delete_event       (GtkWidget        *widget,
839                                                          GdkEventAny      *event,
840                                                          GtkTreeView      *tree_view);
841 static gboolean gtk_tree_view_search_button_press_event (GtkWidget        *widget,
842                                                          GdkEventButton   *event,
843                                                          GtkTreeView      *tree_view);
844 static gboolean gtk_tree_view_search_scroll_event       (GtkWidget        *entry,
845                                                          GdkEventScroll   *event,
846                                                          GtkTreeView      *tree_view);
847 static gboolean gtk_tree_view_search_key_press_event    (GtkWidget        *entry,
848                                                          GdkEventKey      *event,
849                                                          GtkTreeView      *tree_view);
850 static gboolean gtk_tree_view_search_move               (GtkWidget        *window,
851                                                          GtkTreeView      *tree_view,
852                                                          gboolean          up);
853 static gboolean gtk_tree_view_search_equal_func         (GtkTreeModel     *model,
854                                                          gint              column,
855                                                          const gchar      *key,
856                                                          GtkTreeIter      *iter,
857                                                          gpointer          search_data);
858 static gboolean gtk_tree_view_search_iter               (GtkTreeModel     *model,
859                                                          GtkTreeSelection *selection,
860                                                          GtkTreeIter      *iter,
861                                                          const gchar      *text,
862                                                          gint             *count,
863                                                          gint              n);
864 static void     gtk_tree_view_search_init               (GtkWidget        *entry,
865                                                          GtkTreeView      *tree_view);
866 static void     gtk_tree_view_put                       (GtkTreeView      *tree_view,
867                                                          GtkWidget        *child_widget,
868                                                          gint              x,
869                                                          gint              y,
870                                                          gint              width,
871                                                          gint              height);
872 static gboolean gtk_tree_view_start_editing             (GtkTreeView      *tree_view,
873                                                          GtkTreePath      *cursor_path,
874                                                          gboolean          edit_only);
875 static void gtk_tree_view_stop_editing                  (GtkTreeView *tree_view,
876                                                          gboolean     cancel_editing);
877 static gboolean gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view,
878                                                              GdkDevice   *device,
879                                                              gboolean     keybinding);
880 static gboolean gtk_tree_view_start_interactive_search      (GtkTreeView *tree_view);
881 static GtkTreeViewColumn *gtk_tree_view_get_drop_column (GtkTreeView       *tree_view,
882                                                          GtkTreeViewColumn *column,
883                                                          gint               drop_position);
884
885 /* GtkBuildable */
886 static void     gtk_tree_view_buildable_add_child          (GtkBuildable      *tree_view,
887                                                             GtkBuilder        *builder,
888                                                             GObject           *child,
889                                                             const gchar       *type);
890 static GObject *gtk_tree_view_buildable_get_internal_child (GtkBuildable      *buildable,
891                                                             GtkBuilder        *builder,
892                                                             const gchar       *childname);
893 static void     gtk_tree_view_buildable_init               (GtkBuildableIface *iface);
894
895
896 static gboolean scroll_row_timeout                   (gpointer     data);
897 static void     add_scroll_timeout                   (GtkTreeView *tree_view);
898 static void     remove_scroll_timeout                (GtkTreeView *tree_view);
899
900 static guint tree_view_signals [LAST_SIGNAL] = { 0 };
901
902 \f
903
904 /* GType Methods
905  */
906
907 G_DEFINE_TYPE_WITH_CODE (GtkTreeView, gtk_tree_view, GTK_TYPE_CONTAINER,
908                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
909                                                 gtk_tree_view_buildable_init)
910                          G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
911
912 static void
913 gtk_tree_view_class_init (GtkTreeViewClass *class)
914 {
915   GObjectClass *o_class;
916   GtkWidgetClass *widget_class;
917   GtkContainerClass *container_class;
918   GtkBindingSet *binding_set;
919
920   binding_set = gtk_binding_set_by_class (class);
921
922   o_class = (GObjectClass *) class;
923   widget_class = (GtkWidgetClass *) class;
924   container_class = (GtkContainerClass *) class;
925
926   /* GObject signals */
927   o_class->set_property = gtk_tree_view_set_property;
928   o_class->get_property = gtk_tree_view_get_property;
929   o_class->finalize = gtk_tree_view_finalize;
930
931   /* GtkWidget signals */
932   widget_class->destroy = gtk_tree_view_destroy;
933   widget_class->map = gtk_tree_view_map;
934   widget_class->realize = gtk_tree_view_realize;
935   widget_class->unrealize = gtk_tree_view_unrealize;
936   widget_class->get_preferred_width = gtk_tree_view_get_preferred_width;
937   widget_class->get_preferred_height = gtk_tree_view_get_preferred_height;
938   widget_class->size_allocate = gtk_tree_view_size_allocate;
939   widget_class->button_press_event = gtk_tree_view_button_press;
940   widget_class->button_release_event = gtk_tree_view_button_release;
941   widget_class->grab_broken_event = gtk_tree_view_grab_broken;
942   /*widget_class->configure_event = gtk_tree_view_configure;*/
943   widget_class->motion_notify_event = gtk_tree_view_motion;
944   widget_class->draw = gtk_tree_view_draw;
945   widget_class->key_press_event = gtk_tree_view_key_press;
946   widget_class->key_release_event = gtk_tree_view_key_release;
947   widget_class->enter_notify_event = gtk_tree_view_enter_notify;
948   widget_class->leave_notify_event = gtk_tree_view_leave_notify;
949   widget_class->focus_out_event = gtk_tree_view_focus_out;
950   widget_class->drag_begin = gtk_tree_view_drag_begin;
951   widget_class->drag_end = gtk_tree_view_drag_end;
952   widget_class->drag_data_get = gtk_tree_view_drag_data_get;
953   widget_class->drag_data_delete = gtk_tree_view_drag_data_delete;
954   widget_class->drag_leave = gtk_tree_view_drag_leave;
955   widget_class->drag_motion = gtk_tree_view_drag_motion;
956   widget_class->drag_drop = gtk_tree_view_drag_drop;
957   widget_class->drag_data_received = gtk_tree_view_drag_data_received;
958   widget_class->focus = gtk_tree_view_focus;
959   widget_class->grab_focus = gtk_tree_view_grab_focus;
960   widget_class->style_updated = gtk_tree_view_style_updated;
961   widget_class->grab_notify = gtk_tree_view_grab_notify;
962   widget_class->state_flags_changed = gtk_tree_view_state_flags_changed;
963
964   /* GtkContainer signals */
965   container_class->remove = gtk_tree_view_remove;
966   container_class->forall = gtk_tree_view_forall;
967   container_class->set_focus_child = gtk_tree_view_set_focus_child;
968   container_class->get_path_for_child = gtk_tree_view_get_path_for_child;
969
970   class->move_cursor = gtk_tree_view_real_move_cursor;
971   class->select_all = gtk_tree_view_real_select_all;
972   class->unselect_all = gtk_tree_view_real_unselect_all;
973   class->select_cursor_row = gtk_tree_view_real_select_cursor_row;
974   class->toggle_cursor_row = gtk_tree_view_real_toggle_cursor_row;
975   class->expand_collapse_cursor_row = gtk_tree_view_real_expand_collapse_cursor_row;
976   class->select_cursor_parent = gtk_tree_view_real_select_cursor_parent;
977   class->start_interactive_search = gtk_tree_view_start_interactive_search;
978
979   /* Properties */
980
981   g_object_class_install_property (o_class,
982                                    PROP_MODEL,
983                                    g_param_spec_object ("model",
984                                                         P_("TreeView Model"),
985                                                         P_("The model for the tree view"),
986                                                         GTK_TYPE_TREE_MODEL,
987                                                         GTK_PARAM_READWRITE));
988
989   g_object_class_override_property (o_class, PROP_HADJUSTMENT,    "hadjustment");
990   g_object_class_override_property (o_class, PROP_VADJUSTMENT,    "vadjustment");
991   g_object_class_override_property (o_class, PROP_HSCROLL_POLICY, "hscroll-policy");
992   g_object_class_override_property (o_class, PROP_VSCROLL_POLICY, "vscroll-policy");
993
994   g_object_class_install_property (o_class,
995                                    PROP_HEADERS_VISIBLE,
996                                    g_param_spec_boolean ("headers-visible",
997                                                          P_("Headers Visible"),
998                                                          P_("Show the column header buttons"),
999                                                          TRUE,
1000                                                          GTK_PARAM_READWRITE));
1001
1002   g_object_class_install_property (o_class,
1003                                    PROP_HEADERS_CLICKABLE,
1004                                    g_param_spec_boolean ("headers-clickable",
1005                                                          P_("Headers Clickable"),
1006                                                          P_("Column headers respond to click events"),
1007                                                          TRUE,
1008                                                          GTK_PARAM_READWRITE));
1009
1010   g_object_class_install_property (o_class,
1011                                    PROP_EXPANDER_COLUMN,
1012                                    g_param_spec_object ("expander-column",
1013                                                         P_("Expander Column"),
1014                                                         P_("Set the column for the expander column"),
1015                                                         GTK_TYPE_TREE_VIEW_COLUMN,
1016                                                         GTK_PARAM_READWRITE));
1017
1018   g_object_class_install_property (o_class,
1019                                    PROP_REORDERABLE,
1020                                    g_param_spec_boolean ("reorderable",
1021                                                          P_("Reorderable"),
1022                                                          P_("View is reorderable"),
1023                                                          FALSE,
1024                                                          GTK_PARAM_READWRITE));
1025
1026   g_object_class_install_property (o_class,
1027                                    PROP_RULES_HINT,
1028                                    g_param_spec_boolean ("rules-hint",
1029                                                          P_("Rules Hint"),
1030                                                          P_("Set a hint to the theme engine to draw rows in alternating colors"),
1031                                                          FALSE,
1032                                                          GTK_PARAM_READWRITE));
1033
1034     g_object_class_install_property (o_class,
1035                                      PROP_ENABLE_SEARCH,
1036                                      g_param_spec_boolean ("enable-search",
1037                                                            P_("Enable Search"),
1038                                                            P_("View allows user to search through columns interactively"),
1039                                                            TRUE,
1040                                                            GTK_PARAM_READWRITE));
1041
1042     g_object_class_install_property (o_class,
1043                                      PROP_SEARCH_COLUMN,
1044                                      g_param_spec_int ("search-column",
1045                                                        P_("Search Column"),
1046                                                        P_("Model column to search through during interactive search"),
1047                                                        -1,
1048                                                        G_MAXINT,
1049                                                        -1,
1050                                                        GTK_PARAM_READWRITE));
1051
1052     /**
1053      * GtkTreeView:fixed-height-mode:
1054      *
1055      * Setting the ::fixed-height-mode property to %TRUE speeds up 
1056      * #GtkTreeView by assuming that all rows have the same height. 
1057      * Only enable this option if all rows are the same height.  
1058      * Please see gtk_tree_view_set_fixed_height_mode() for more 
1059      * information on this option.
1060      *
1061      * Since: 2.4
1062      **/
1063     g_object_class_install_property (o_class,
1064                                      PROP_FIXED_HEIGHT_MODE,
1065                                      g_param_spec_boolean ("fixed-height-mode",
1066                                                            P_("Fixed Height Mode"),
1067                                                            P_("Speeds up GtkTreeView by assuming that all rows have the same height"),
1068                                                            FALSE,
1069                                                            GTK_PARAM_READWRITE));
1070     
1071     /**
1072      * GtkTreeView:hover-selection:
1073      * 
1074      * Enables or disables the hover selection mode of @tree_view.
1075      * Hover selection makes the selected row follow the pointer.
1076      * Currently, this works only for the selection modes 
1077      * %GTK_SELECTION_SINGLE and %GTK_SELECTION_BROWSE.
1078      *
1079      * This mode is primarily intended for treeviews in popups, e.g.
1080      * in #GtkComboBox or #GtkEntryCompletion.
1081      *
1082      * Since: 2.6
1083      */
1084     g_object_class_install_property (o_class,
1085                                      PROP_HOVER_SELECTION,
1086                                      g_param_spec_boolean ("hover-selection",
1087                                                            P_("Hover Selection"),
1088                                                            P_("Whether the selection should follow the pointer"),
1089                                                            FALSE,
1090                                                            GTK_PARAM_READWRITE));
1091
1092     /**
1093      * GtkTreeView:hover-expand:
1094      * 
1095      * Enables or disables the hover expansion mode of @tree_view.
1096      * Hover expansion makes rows expand or collapse if the pointer moves 
1097      * over them.
1098      *
1099      * This mode is primarily intended for treeviews in popups, e.g.
1100      * in #GtkComboBox or #GtkEntryCompletion.
1101      *
1102      * Since: 2.6
1103      */
1104     g_object_class_install_property (o_class,
1105                                      PROP_HOVER_EXPAND,
1106                                      g_param_spec_boolean ("hover-expand",
1107                                                            P_("Hover Expand"),
1108                                                            P_("Whether rows should be expanded/collapsed when the pointer moves over them"),
1109                                                            FALSE,
1110                                                            GTK_PARAM_READWRITE));
1111
1112     /**
1113      * GtkTreeView:show-expanders:
1114      *
1115      * %TRUE if the view has expanders.
1116      *
1117      * Since: 2.12
1118      */
1119     g_object_class_install_property (o_class,
1120                                      PROP_SHOW_EXPANDERS,
1121                                      g_param_spec_boolean ("show-expanders",
1122                                                            P_("Show Expanders"),
1123                                                            P_("View has expanders"),
1124                                                            TRUE,
1125                                                            GTK_PARAM_READWRITE));
1126
1127     /**
1128      * GtkTreeView:level-indentation:
1129      *
1130      * Extra indentation for each level.
1131      *
1132      * Since: 2.12
1133      */
1134     g_object_class_install_property (o_class,
1135                                      PROP_LEVEL_INDENTATION,
1136                                      g_param_spec_int ("level-indentation",
1137                                                        P_("Level Indentation"),
1138                                                        P_("Extra indentation for each level"),
1139                                                        0,
1140                                                        G_MAXINT,
1141                                                        0,
1142                                                        GTK_PARAM_READWRITE));
1143
1144     g_object_class_install_property (o_class,
1145                                      PROP_RUBBER_BANDING,
1146                                      g_param_spec_boolean ("rubber-banding",
1147                                                            P_("Rubber Banding"),
1148                                                            P_("Whether to enable selection of multiple items by dragging the mouse pointer"),
1149                                                            FALSE,
1150                                                            GTK_PARAM_READWRITE));
1151
1152     g_object_class_install_property (o_class,
1153                                      PROP_ENABLE_GRID_LINES,
1154                                      g_param_spec_enum ("enable-grid-lines",
1155                                                         P_("Enable Grid Lines"),
1156                                                         P_("Whether grid lines should be drawn in the tree view"),
1157                                                         GTK_TYPE_TREE_VIEW_GRID_LINES,
1158                                                         GTK_TREE_VIEW_GRID_LINES_NONE,
1159                                                         GTK_PARAM_READWRITE));
1160
1161     g_object_class_install_property (o_class,
1162                                      PROP_ENABLE_TREE_LINES,
1163                                      g_param_spec_boolean ("enable-tree-lines",
1164                                                            P_("Enable Tree Lines"),
1165                                                            P_("Whether tree lines should be drawn in the tree view"),
1166                                                            FALSE,
1167                                                            GTK_PARAM_READWRITE));
1168
1169     g_object_class_install_property (o_class,
1170                                      PROP_TOOLTIP_COLUMN,
1171                                      g_param_spec_int ("tooltip-column",
1172                                                        P_("Tooltip Column"),
1173                                                        P_("The column in the model containing the tooltip texts for the rows"),
1174                                                        -1,
1175                                                        G_MAXINT,
1176                                                        -1,
1177                                                        GTK_PARAM_READWRITE));
1178
1179   /* Style properties */
1180 #define _TREE_VIEW_EXPANDER_SIZE 14
1181 #define _TREE_VIEW_VERTICAL_SEPARATOR 2
1182 #define _TREE_VIEW_HORIZONTAL_SEPARATOR 2
1183
1184   gtk_widget_class_install_style_property (widget_class,
1185                                            g_param_spec_int ("expander-size",
1186                                                              P_("Expander Size"),
1187                                                              P_("Size of the expander arrow"),
1188                                                              0,
1189                                                              G_MAXINT,
1190                                                              _TREE_VIEW_EXPANDER_SIZE,
1191                                                              GTK_PARAM_READABLE));
1192
1193   gtk_widget_class_install_style_property (widget_class,
1194                                            g_param_spec_int ("vertical-separator",
1195                                                              P_("Vertical Separator Width"),
1196                                                              P_("Vertical space between cells.  Must be an even number"),
1197                                                              0,
1198                                                              G_MAXINT,
1199                                                              _TREE_VIEW_VERTICAL_SEPARATOR,
1200                                                              GTK_PARAM_READABLE));
1201
1202   gtk_widget_class_install_style_property (widget_class,
1203                                            g_param_spec_int ("horizontal-separator",
1204                                                              P_("Horizontal Separator Width"),
1205                                                              P_("Horizontal space between cells.  Must be an even number"),
1206                                                              0,
1207                                                              G_MAXINT,
1208                                                              _TREE_VIEW_HORIZONTAL_SEPARATOR,
1209                                                              GTK_PARAM_READABLE));
1210
1211   gtk_widget_class_install_style_property (widget_class,
1212                                            g_param_spec_boolean ("allow-rules",
1213                                                                  P_("Allow Rules"),
1214                                                                  P_("Allow drawing of alternating color rows"),
1215                                                                  TRUE,
1216                                                                  GTK_PARAM_READABLE));
1217
1218   gtk_widget_class_install_style_property (widget_class,
1219                                            g_param_spec_boolean ("indent-expanders",
1220                                                                  P_("Indent Expanders"),
1221                                                                  P_("Make the expanders indented"),
1222                                                                  TRUE,
1223                                                                  GTK_PARAM_READABLE));
1224
1225   gtk_widget_class_install_style_property (widget_class,
1226                                            g_param_spec_boxed ("even-row-color",
1227                                                                P_("Even Row Color"),
1228                                                                P_("Color to use for even rows"),
1229                                                                GDK_TYPE_COLOR,
1230                                                                GTK_PARAM_READABLE));
1231
1232   gtk_widget_class_install_style_property (widget_class,
1233                                            g_param_spec_boxed ("odd-row-color",
1234                                                                P_("Odd Row Color"),
1235                                                                P_("Color to use for odd rows"),
1236                                                                GDK_TYPE_COLOR,
1237                                                                GTK_PARAM_READABLE));
1238
1239   gtk_widget_class_install_style_property (widget_class,
1240                                            g_param_spec_int ("grid-line-width",
1241                                                              P_("Grid line width"),
1242                                                              P_("Width, in pixels, of the tree view grid lines"),
1243                                                              0, G_MAXINT, 1,
1244                                                              GTK_PARAM_READABLE));
1245
1246   gtk_widget_class_install_style_property (widget_class,
1247                                            g_param_spec_int ("tree-line-width",
1248                                                              P_("Tree line width"),
1249                                                              P_("Width, in pixels, of the tree view lines"),
1250                                                              0, G_MAXINT, 1,
1251                                                              GTK_PARAM_READABLE));
1252
1253   gtk_widget_class_install_style_property (widget_class,
1254                                            g_param_spec_string ("grid-line-pattern",
1255                                                                 P_("Grid line pattern"),
1256                                                                 P_("Dash pattern used to draw the tree view grid lines"),
1257                                                                 "\1\1",
1258                                                                 GTK_PARAM_READABLE));
1259
1260   gtk_widget_class_install_style_property (widget_class,
1261                                            g_param_spec_string ("tree-line-pattern",
1262                                                                 P_("Tree line pattern"),
1263                                                                 P_("Dash pattern used to draw the tree view lines"),
1264                                                                 "\1\1",
1265                                                                 GTK_PARAM_READABLE));
1266
1267   /* Signals */
1268   /**
1269    * GtkTreeView::row-activated:
1270    * @tree_view: the object on which the signal is emitted
1271    * @path: the #GtkTreePath for the activated row
1272    * @column: the #GtkTreeViewColumn in which the activation occurred
1273    *
1274    * The "row-activated" signal is emitted when the method
1275    * gtk_tree_view_row_activated() is called or the user double clicks 
1276    * a treeview row. It is also emitted when a non-editable row is 
1277    * selected and one of the keys: Space, Shift+Space, Return or 
1278    * Enter is pressed.
1279    * 
1280    * For selection handling refer to the <link linkend="TreeWidget">tree 
1281    * widget conceptual overview</link> as well as #GtkTreeSelection.
1282    */
1283   tree_view_signals[ROW_ACTIVATED] =
1284     g_signal_new (I_("row-activated"),
1285                   G_TYPE_FROM_CLASS (o_class),
1286                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1287                   G_STRUCT_OFFSET (GtkTreeViewClass, row_activated),
1288                   NULL, NULL,
1289                   _gtk_marshal_VOID__BOXED_OBJECT,
1290                   G_TYPE_NONE, 2,
1291                   GTK_TYPE_TREE_PATH,
1292                   GTK_TYPE_TREE_VIEW_COLUMN);
1293
1294   /**
1295    * GtkTreeView::test-expand-row:
1296    * @tree_view: the object on which the signal is emitted
1297    * @iter: the tree iter of the row to expand
1298    * @path: a tree path that points to the row 
1299    * 
1300    * The given row is about to be expanded (show its children nodes). Use this
1301    * signal if you need to control the expandability of individual rows.
1302    *
1303    * Returns: %FALSE to allow expansion, %TRUE to reject
1304    */
1305   tree_view_signals[TEST_EXPAND_ROW] =
1306     g_signal_new (I_("test-expand-row"),
1307                   G_TYPE_FROM_CLASS (o_class),
1308                   G_SIGNAL_RUN_LAST,
1309                   G_STRUCT_OFFSET (GtkTreeViewClass, test_expand_row),
1310                   _gtk_boolean_handled_accumulator, NULL,
1311                   _gtk_marshal_BOOLEAN__BOXED_BOXED,
1312                   G_TYPE_BOOLEAN, 2,
1313                   GTK_TYPE_TREE_ITER,
1314                   GTK_TYPE_TREE_PATH);
1315
1316   /**
1317    * GtkTreeView::test-collapse-row:
1318    * @tree_view: the object on which the signal is emitted
1319    * @iter: the tree iter of the row to collapse
1320    * @path: a tree path that points to the row 
1321    * 
1322    * The given row is about to be collapsed (hide its children nodes). Use this
1323    * signal if you need to control the collapsibility of individual rows.
1324    *
1325    * Returns: %FALSE to allow collapsing, %TRUE to reject
1326    */
1327   tree_view_signals[TEST_COLLAPSE_ROW] =
1328     g_signal_new (I_("test-collapse-row"),
1329                   G_TYPE_FROM_CLASS (o_class),
1330                   G_SIGNAL_RUN_LAST,
1331                   G_STRUCT_OFFSET (GtkTreeViewClass, test_collapse_row),
1332                   _gtk_boolean_handled_accumulator, NULL,
1333                   _gtk_marshal_BOOLEAN__BOXED_BOXED,
1334                   G_TYPE_BOOLEAN, 2,
1335                   GTK_TYPE_TREE_ITER,
1336                   GTK_TYPE_TREE_PATH);
1337
1338   /**
1339    * GtkTreeView::row-expanded:
1340    * @tree_view: the object on which the signal is emitted
1341    * @iter: the tree iter of the expanded row
1342    * @path: a tree path that points to the row 
1343    * 
1344    * The given row has been expanded (child nodes are shown).
1345    */
1346   tree_view_signals[ROW_EXPANDED] =
1347     g_signal_new (I_("row-expanded"),
1348                   G_TYPE_FROM_CLASS (o_class),
1349                   G_SIGNAL_RUN_LAST,
1350                   G_STRUCT_OFFSET (GtkTreeViewClass, row_expanded),
1351                   NULL, NULL,
1352                   _gtk_marshal_VOID__BOXED_BOXED,
1353                   G_TYPE_NONE, 2,
1354                   GTK_TYPE_TREE_ITER,
1355                   GTK_TYPE_TREE_PATH);
1356
1357   /**
1358    * GtkTreeView::row-collapsed:
1359    * @tree_view: the object on which the signal is emitted
1360    * @iter: the tree iter of the collapsed row
1361    * @path: a tree path that points to the row 
1362    * 
1363    * The given row has been collapsed (child nodes are hidden).
1364    */
1365   tree_view_signals[ROW_COLLAPSED] =
1366     g_signal_new (I_("row-collapsed"),
1367                   G_TYPE_FROM_CLASS (o_class),
1368                   G_SIGNAL_RUN_LAST,
1369                   G_STRUCT_OFFSET (GtkTreeViewClass, row_collapsed),
1370                   NULL, NULL,
1371                   _gtk_marshal_VOID__BOXED_BOXED,
1372                   G_TYPE_NONE, 2,
1373                   GTK_TYPE_TREE_ITER,
1374                   GTK_TYPE_TREE_PATH);
1375
1376   /**
1377    * GtkTreeView::columns-changed:
1378    * @tree_view: the object on which the signal is emitted 
1379    * 
1380    * The number of columns of the treeview has changed.
1381    */
1382   tree_view_signals[COLUMNS_CHANGED] =
1383     g_signal_new (I_("columns-changed"),
1384                   G_TYPE_FROM_CLASS (o_class),
1385                   G_SIGNAL_RUN_LAST,
1386                   G_STRUCT_OFFSET (GtkTreeViewClass, columns_changed),
1387                   NULL, NULL,
1388                   _gtk_marshal_VOID__VOID,
1389                   G_TYPE_NONE, 0);
1390
1391   /**
1392    * GtkTreeView::cursor-changed:
1393    * @tree_view: the object on which the signal is emitted
1394    * 
1395    * The position of the cursor (focused cell) has changed.
1396    */
1397   tree_view_signals[CURSOR_CHANGED] =
1398     g_signal_new (I_("cursor-changed"),
1399                   G_TYPE_FROM_CLASS (o_class),
1400                   G_SIGNAL_RUN_LAST,
1401                   G_STRUCT_OFFSET (GtkTreeViewClass, cursor_changed),
1402                   NULL, NULL,
1403                   _gtk_marshal_VOID__VOID,
1404                   G_TYPE_NONE, 0);
1405
1406   tree_view_signals[MOVE_CURSOR] =
1407     g_signal_new (I_("move-cursor"),
1408                   G_TYPE_FROM_CLASS (o_class),
1409                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1410                   G_STRUCT_OFFSET (GtkTreeViewClass, move_cursor),
1411                   NULL, NULL,
1412                   _gtk_marshal_BOOLEAN__ENUM_INT,
1413                   G_TYPE_BOOLEAN, 2,
1414                   GTK_TYPE_MOVEMENT_STEP,
1415                   G_TYPE_INT);
1416
1417   tree_view_signals[SELECT_ALL] =
1418     g_signal_new (I_("select-all"),
1419                   G_TYPE_FROM_CLASS (o_class),
1420                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1421                   G_STRUCT_OFFSET (GtkTreeViewClass, select_all),
1422                   NULL, NULL,
1423                   _gtk_marshal_BOOLEAN__VOID,
1424                   G_TYPE_BOOLEAN, 0);
1425
1426   tree_view_signals[UNSELECT_ALL] =
1427     g_signal_new (I_("unselect-all"),
1428                   G_TYPE_FROM_CLASS (o_class),
1429                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1430                   G_STRUCT_OFFSET (GtkTreeViewClass, unselect_all),
1431                   NULL, NULL,
1432                   _gtk_marshal_BOOLEAN__VOID,
1433                   G_TYPE_BOOLEAN, 0);
1434
1435   tree_view_signals[SELECT_CURSOR_ROW] =
1436     g_signal_new (I_("select-cursor-row"),
1437                   G_TYPE_FROM_CLASS (o_class),
1438                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1439                   G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_row),
1440                   NULL, NULL,
1441                   _gtk_marshal_BOOLEAN__BOOLEAN,
1442                   G_TYPE_BOOLEAN, 1,
1443                   G_TYPE_BOOLEAN);
1444
1445   tree_view_signals[TOGGLE_CURSOR_ROW] =
1446     g_signal_new (I_("toggle-cursor-row"),
1447                   G_TYPE_FROM_CLASS (o_class),
1448                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1449                   G_STRUCT_OFFSET (GtkTreeViewClass, toggle_cursor_row),
1450                   NULL, NULL,
1451                   _gtk_marshal_BOOLEAN__VOID,
1452                   G_TYPE_BOOLEAN, 0);
1453
1454   tree_view_signals[EXPAND_COLLAPSE_CURSOR_ROW] =
1455     g_signal_new (I_("expand-collapse-cursor-row"),
1456                   G_TYPE_FROM_CLASS (o_class),
1457                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1458                   G_STRUCT_OFFSET (GtkTreeViewClass, expand_collapse_cursor_row),
1459                   NULL, NULL,
1460                   _gtk_marshal_BOOLEAN__BOOLEAN_BOOLEAN_BOOLEAN,
1461                   G_TYPE_BOOLEAN, 3,
1462                   G_TYPE_BOOLEAN,
1463                   G_TYPE_BOOLEAN,
1464                   G_TYPE_BOOLEAN);
1465
1466   tree_view_signals[SELECT_CURSOR_PARENT] =
1467     g_signal_new (I_("select-cursor-parent"),
1468                   G_TYPE_FROM_CLASS (o_class),
1469                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1470                   G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_parent),
1471                   NULL, NULL,
1472                   _gtk_marshal_BOOLEAN__VOID,
1473                   G_TYPE_BOOLEAN, 0);
1474
1475   tree_view_signals[START_INTERACTIVE_SEARCH] =
1476     g_signal_new (I_("start-interactive-search"),
1477                   G_TYPE_FROM_CLASS (o_class),
1478                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1479                   G_STRUCT_OFFSET (GtkTreeViewClass, start_interactive_search),
1480                   NULL, NULL,
1481                   _gtk_marshal_BOOLEAN__VOID,
1482                   G_TYPE_BOOLEAN, 0);
1483
1484   /* Key bindings */
1485   gtk_tree_view_add_move_binding (binding_set, GDK_KEY_Up, 0, TRUE,
1486                                   GTK_MOVEMENT_DISPLAY_LINES, -1);
1487   gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_Up, 0, TRUE,
1488                                   GTK_MOVEMENT_DISPLAY_LINES, -1);
1489
1490   gtk_tree_view_add_move_binding (binding_set, GDK_KEY_Down, 0, TRUE,
1491                                   GTK_MOVEMENT_DISPLAY_LINES, 1);
1492   gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_Down, 0, TRUE,
1493                                   GTK_MOVEMENT_DISPLAY_LINES, 1);
1494
1495   gtk_tree_view_add_move_binding (binding_set, GDK_KEY_p, GDK_CONTROL_MASK, FALSE,
1496                                   GTK_MOVEMENT_DISPLAY_LINES, -1);
1497
1498   gtk_tree_view_add_move_binding (binding_set, GDK_KEY_n, GDK_CONTROL_MASK, FALSE,
1499                                   GTK_MOVEMENT_DISPLAY_LINES, 1);
1500
1501   gtk_tree_view_add_move_binding (binding_set, GDK_KEY_Home, 0, TRUE,
1502                                   GTK_MOVEMENT_BUFFER_ENDS, -1);
1503   gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_Home, 0, TRUE,
1504                                   GTK_MOVEMENT_BUFFER_ENDS, -1);
1505
1506   gtk_tree_view_add_move_binding (binding_set, GDK_KEY_End, 0, TRUE,
1507                                   GTK_MOVEMENT_BUFFER_ENDS, 1);
1508   gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_End, 0, TRUE,
1509                                   GTK_MOVEMENT_BUFFER_ENDS, 1);
1510
1511   gtk_tree_view_add_move_binding (binding_set, GDK_KEY_Page_Up, 0, TRUE,
1512                                   GTK_MOVEMENT_PAGES, -1);
1513   gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0, TRUE,
1514                                   GTK_MOVEMENT_PAGES, -1);
1515
1516   gtk_tree_view_add_move_binding (binding_set, GDK_KEY_Page_Down, 0, TRUE,
1517                                   GTK_MOVEMENT_PAGES, 1);
1518   gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0, TRUE,
1519                                   GTK_MOVEMENT_PAGES, 1);
1520
1521
1522   gtk_binding_entry_add_signal (binding_set, GDK_KEY_Right, 0, "move-cursor", 2,
1523                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
1524                                 G_TYPE_INT, 1);
1525
1526   gtk_binding_entry_add_signal (binding_set, GDK_KEY_Left, 0, "move-cursor", 2,
1527                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
1528                                 G_TYPE_INT, -1);
1529
1530   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Right, 0, "move-cursor", 2,
1531                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
1532                                 G_TYPE_INT, 1);
1533
1534   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Left, 0, "move-cursor", 2,
1535                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
1536                                 G_TYPE_INT, -1);
1537
1538   gtk_binding_entry_add_signal (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK,
1539                                 "move-cursor", 2,
1540                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
1541                                 G_TYPE_INT, 1);
1542
1543   gtk_binding_entry_add_signal (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK,
1544                                 "move-cursor", 2,
1545                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
1546                                 G_TYPE_INT, -1);
1547
1548   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
1549                                 "move-cursor", 2,
1550                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
1551                                 G_TYPE_INT, 1);
1552
1553   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
1554                                 "move-cursor", 2,
1555                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
1556                                 G_TYPE_INT, -1);
1557
1558   gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_CONTROL_MASK, "toggle-cursor-row", 0);
1559   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_CONTROL_MASK, "toggle-cursor-row", 0);
1560
1561   gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK, "select-all", 0);
1562   gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK, "select-all", 0);
1563
1564   gtk_binding_entry_add_signal (binding_set, GDK_KEY_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "unselect-all", 0);
1565   gtk_binding_entry_add_signal (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK, "unselect-all", 0);
1566
1567   gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_SHIFT_MASK, "select-cursor-row", 1,
1568                                 G_TYPE_BOOLEAN, TRUE);
1569   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_SHIFT_MASK, "select-cursor-row", 1,
1570                                 G_TYPE_BOOLEAN, TRUE);
1571
1572   gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0, "select-cursor-row", 1,
1573                                 G_TYPE_BOOLEAN, TRUE);
1574   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0, "select-cursor-row", 1,
1575                                 G_TYPE_BOOLEAN, TRUE);
1576   gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0, "select-cursor-row", 1,
1577                                 G_TYPE_BOOLEAN, TRUE);
1578   gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0, "select-cursor-row", 1,
1579                                 G_TYPE_BOOLEAN, TRUE);
1580   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0, "select-cursor-row", 1,
1581                                 G_TYPE_BOOLEAN, TRUE);
1582
1583   /* expand and collapse rows */
1584   gtk_binding_entry_add_signal (binding_set, GDK_KEY_plus, 0, "expand-collapse-cursor-row", 3,
1585                                 G_TYPE_BOOLEAN, TRUE,
1586                                 G_TYPE_BOOLEAN, TRUE,
1587                                 G_TYPE_BOOLEAN, FALSE);
1588
1589   gtk_binding_entry_add_signal (binding_set, GDK_KEY_asterisk, 0,
1590                                 "expand-collapse-cursor-row", 3,
1591                                 G_TYPE_BOOLEAN, TRUE,
1592                                 G_TYPE_BOOLEAN, TRUE,
1593                                 G_TYPE_BOOLEAN, TRUE);
1594   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Multiply, 0,
1595                                 "expand-collapse-cursor-row", 3,
1596                                 G_TYPE_BOOLEAN, TRUE,
1597                                 G_TYPE_BOOLEAN, TRUE,
1598                                 G_TYPE_BOOLEAN, TRUE);
1599
1600   gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, 0,
1601                                 "expand-collapse-cursor-row", 3,
1602                                 G_TYPE_BOOLEAN, TRUE,
1603                                 G_TYPE_BOOLEAN, FALSE,
1604                                 G_TYPE_BOOLEAN, FALSE);
1605   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Divide, 0,
1606                                 "expand-collapse-cursor-row", 3,
1607                                 G_TYPE_BOOLEAN, TRUE,
1608                                 G_TYPE_BOOLEAN, FALSE,
1609                                 G_TYPE_BOOLEAN, FALSE);
1610
1611   /* Not doable on US keyboards */
1612   gtk_binding_entry_add_signal (binding_set, GDK_KEY_plus, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
1613                                 G_TYPE_BOOLEAN, TRUE,
1614                                 G_TYPE_BOOLEAN, TRUE,
1615                                 G_TYPE_BOOLEAN, TRUE);
1616   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Add, 0, "expand-collapse-cursor-row", 3,
1617                                 G_TYPE_BOOLEAN, TRUE,
1618                                 G_TYPE_BOOLEAN, TRUE,
1619                                 G_TYPE_BOOLEAN, FALSE);
1620   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Add, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
1621                                 G_TYPE_BOOLEAN, TRUE,
1622                                 G_TYPE_BOOLEAN, TRUE,
1623                                 G_TYPE_BOOLEAN, TRUE);
1624   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Add, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
1625                                 G_TYPE_BOOLEAN, TRUE,
1626                                 G_TYPE_BOOLEAN, TRUE,
1627                                 G_TYPE_BOOLEAN, TRUE);
1628   gtk_binding_entry_add_signal (binding_set, GDK_KEY_Right, GDK_SHIFT_MASK,
1629                                 "expand-collapse-cursor-row", 3,
1630                                 G_TYPE_BOOLEAN, FALSE,
1631                                 G_TYPE_BOOLEAN, TRUE,
1632                                 G_TYPE_BOOLEAN, TRUE);
1633   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Right, GDK_SHIFT_MASK,
1634                                 "expand-collapse-cursor-row", 3,
1635                                 G_TYPE_BOOLEAN, FALSE,
1636                                 G_TYPE_BOOLEAN, TRUE,
1637                                 G_TYPE_BOOLEAN, TRUE);
1638   gtk_binding_entry_add_signal (binding_set, GDK_KEY_Right,
1639                                 GDK_CONTROL_MASK | GDK_SHIFT_MASK,
1640                                 "expand-collapse-cursor-row", 3,
1641                                 G_TYPE_BOOLEAN, FALSE,
1642                                 G_TYPE_BOOLEAN, TRUE,
1643                                 G_TYPE_BOOLEAN, TRUE);
1644   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Right,
1645                                 GDK_CONTROL_MASK | GDK_SHIFT_MASK,
1646                                 "expand-collapse-cursor-row", 3,
1647                                 G_TYPE_BOOLEAN, FALSE,
1648                                 G_TYPE_BOOLEAN, TRUE,
1649                                 G_TYPE_BOOLEAN, TRUE);
1650
1651   gtk_binding_entry_add_signal (binding_set, GDK_KEY_minus, 0, "expand-collapse-cursor-row", 3,
1652                                 G_TYPE_BOOLEAN, TRUE,
1653                                 G_TYPE_BOOLEAN, FALSE,
1654                                 G_TYPE_BOOLEAN, FALSE);
1655   gtk_binding_entry_add_signal (binding_set, GDK_KEY_minus, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
1656                                 G_TYPE_BOOLEAN, TRUE,
1657                                 G_TYPE_BOOLEAN, FALSE,
1658                                 G_TYPE_BOOLEAN, TRUE);
1659   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Subtract, 0, "expand-collapse-cursor-row", 3,
1660                                 G_TYPE_BOOLEAN, TRUE,
1661                                 G_TYPE_BOOLEAN, FALSE,
1662                                 G_TYPE_BOOLEAN, FALSE);
1663   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Subtract, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
1664                                 G_TYPE_BOOLEAN, TRUE,
1665                                 G_TYPE_BOOLEAN, FALSE,
1666                                 G_TYPE_BOOLEAN, TRUE);
1667   gtk_binding_entry_add_signal (binding_set, GDK_KEY_Left, GDK_SHIFT_MASK,
1668                                 "expand-collapse-cursor-row", 3,
1669                                 G_TYPE_BOOLEAN, FALSE,
1670                                 G_TYPE_BOOLEAN, FALSE,
1671                                 G_TYPE_BOOLEAN, TRUE);
1672   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Left, GDK_SHIFT_MASK,
1673                                 "expand-collapse-cursor-row", 3,
1674                                 G_TYPE_BOOLEAN, FALSE,
1675                                 G_TYPE_BOOLEAN, FALSE,
1676                                 G_TYPE_BOOLEAN, TRUE);
1677   gtk_binding_entry_add_signal (binding_set, GDK_KEY_Left,
1678                                 GDK_CONTROL_MASK | GDK_SHIFT_MASK,
1679                                 "expand-collapse-cursor-row", 3,
1680                                 G_TYPE_BOOLEAN, FALSE,
1681                                 G_TYPE_BOOLEAN, FALSE,
1682                                 G_TYPE_BOOLEAN, TRUE);
1683   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Left,
1684                                 GDK_CONTROL_MASK | GDK_SHIFT_MASK,
1685                                 "expand-collapse-cursor-row", 3,
1686                                 G_TYPE_BOOLEAN, FALSE,
1687                                 G_TYPE_BOOLEAN, FALSE,
1688                                 G_TYPE_BOOLEAN, TRUE);
1689
1690   gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, 0, "select-cursor-parent", 0);
1691   gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_CONTROL_MASK, "select-cursor-parent", 0);
1692
1693   gtk_binding_entry_add_signal (binding_set, GDK_KEY_f, GDK_CONTROL_MASK, "start-interactive-search", 0);
1694
1695   gtk_binding_entry_add_signal (binding_set, GDK_KEY_F, GDK_CONTROL_MASK, "start-interactive-search", 0);
1696
1697   g_type_class_add_private (o_class, sizeof (GtkTreeViewPrivate));
1698
1699   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_TREE_VIEW_ACCESSIBLE);
1700 }
1701
1702 static void
1703 gtk_tree_view_init (GtkTreeView *tree_view)
1704 {
1705   tree_view->priv = G_TYPE_INSTANCE_GET_PRIVATE (tree_view, GTK_TYPE_TREE_VIEW, GtkTreeViewPrivate);
1706
1707   gtk_widget_set_can_focus (GTK_WIDGET (tree_view), TRUE);
1708   gtk_widget_set_redraw_on_allocate (GTK_WIDGET (tree_view), FALSE);
1709
1710   tree_view->priv->show_expanders = TRUE;
1711   tree_view->priv->draw_keyfocus = TRUE;
1712   tree_view->priv->headers_visible = TRUE;
1713
1714   /* We need some padding */
1715   tree_view->priv->dy = 0;
1716   tree_view->priv->cursor_offset = 0;
1717   tree_view->priv->n_columns = 0;
1718   tree_view->priv->header_height = 1;
1719   tree_view->priv->x_drag = 0;
1720   tree_view->priv->drag_pos = -1;
1721   tree_view->priv->header_has_focus = FALSE;
1722   tree_view->priv->pressed_button = -1;
1723   tree_view->priv->press_start_x = -1;
1724   tree_view->priv->press_start_y = -1;
1725   tree_view->priv->reorderable = FALSE;
1726   tree_view->priv->presize_handler_timer = 0;
1727   tree_view->priv->scroll_sync_timer = 0;
1728   tree_view->priv->fixed_height = -1;
1729   tree_view->priv->fixed_height_mode = FALSE;
1730   tree_view->priv->fixed_height_check = 0;
1731   tree_view->priv->selection = _gtk_tree_selection_new_with_tree_view (tree_view);
1732   tree_view->priv->enable_search = TRUE;
1733   tree_view->priv->search_column = -1;
1734   tree_view->priv->search_position_func = gtk_tree_view_search_position_func;
1735   tree_view->priv->search_equal_func = gtk_tree_view_search_equal_func;
1736   tree_view->priv->search_custom_entry_set = FALSE;
1737   tree_view->priv->typeselect_flush_timeout = 0;
1738   tree_view->priv->init_hadjust_value = TRUE;    
1739   tree_view->priv->width = 0;
1740           
1741   tree_view->priv->hover_selection = FALSE;
1742   tree_view->priv->hover_expand = FALSE;
1743
1744   tree_view->priv->level_indentation = 0;
1745
1746   tree_view->priv->rubber_banding_enable = FALSE;
1747
1748   tree_view->priv->grid_lines = GTK_TREE_VIEW_GRID_LINES_NONE;
1749   tree_view->priv->tree_lines_enabled = FALSE;
1750
1751   tree_view->priv->tooltip_column = -1;
1752
1753   tree_view->priv->post_validation_flag = FALSE;
1754
1755   tree_view->priv->last_button_x = -1;
1756   tree_view->priv->last_button_y = -1;
1757
1758   tree_view->priv->event_last_x = -10000;
1759   tree_view->priv->event_last_y = -10000;
1760
1761   gtk_tree_view_set_vadjustment (tree_view, NULL);
1762   gtk_tree_view_set_hadjustment (tree_view, NULL);
1763 }
1764
1765 \f
1766
1767 /* GObject Methods
1768  */
1769
1770 static void
1771 gtk_tree_view_set_property (GObject         *object,
1772                             guint            prop_id,
1773                             const GValue    *value,
1774                             GParamSpec      *pspec)
1775 {
1776   GtkTreeView *tree_view;
1777
1778   tree_view = GTK_TREE_VIEW (object);
1779
1780   switch (prop_id)
1781     {
1782     case PROP_MODEL:
1783       gtk_tree_view_set_model (tree_view, g_value_get_object (value));
1784       break;
1785     case PROP_HADJUSTMENT:
1786       gtk_tree_view_set_hadjustment (tree_view, g_value_get_object (value));
1787       break;
1788     case PROP_VADJUSTMENT:
1789       gtk_tree_view_set_vadjustment (tree_view, g_value_get_object (value));
1790       break;
1791     case PROP_HSCROLL_POLICY:
1792       tree_view->priv->hscroll_policy = g_value_get_enum (value);
1793       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
1794       break;
1795     case PROP_VSCROLL_POLICY:
1796       tree_view->priv->vscroll_policy = g_value_get_enum (value);
1797       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
1798       break;
1799     case PROP_HEADERS_VISIBLE:
1800       gtk_tree_view_set_headers_visible (tree_view, g_value_get_boolean (value));
1801       break;
1802     case PROP_HEADERS_CLICKABLE:
1803       gtk_tree_view_set_headers_clickable (tree_view, g_value_get_boolean (value));
1804       break;
1805     case PROP_EXPANDER_COLUMN:
1806       gtk_tree_view_set_expander_column (tree_view, g_value_get_object (value));
1807       break;
1808     case PROP_REORDERABLE:
1809       gtk_tree_view_set_reorderable (tree_view, g_value_get_boolean (value));
1810       break;
1811     case PROP_RULES_HINT:
1812       gtk_tree_view_set_rules_hint (tree_view, g_value_get_boolean (value));
1813       break;
1814     case PROP_ENABLE_SEARCH:
1815       gtk_tree_view_set_enable_search (tree_view, g_value_get_boolean (value));
1816       break;
1817     case PROP_SEARCH_COLUMN:
1818       gtk_tree_view_set_search_column (tree_view, g_value_get_int (value));
1819       break;
1820     case PROP_FIXED_HEIGHT_MODE:
1821       gtk_tree_view_set_fixed_height_mode (tree_view, g_value_get_boolean (value));
1822       break;
1823     case PROP_HOVER_SELECTION:
1824       tree_view->priv->hover_selection = g_value_get_boolean (value);
1825       break;
1826     case PROP_HOVER_EXPAND:
1827       tree_view->priv->hover_expand = g_value_get_boolean (value);
1828       break;
1829     case PROP_SHOW_EXPANDERS:
1830       gtk_tree_view_set_show_expanders (tree_view, g_value_get_boolean (value));
1831       break;
1832     case PROP_LEVEL_INDENTATION:
1833       tree_view->priv->level_indentation = g_value_get_int (value);
1834       break;
1835     case PROP_RUBBER_BANDING:
1836       tree_view->priv->rubber_banding_enable = g_value_get_boolean (value);
1837       break;
1838     case PROP_ENABLE_GRID_LINES:
1839       gtk_tree_view_set_grid_lines (tree_view, g_value_get_enum (value));
1840       break;
1841     case PROP_ENABLE_TREE_LINES:
1842       gtk_tree_view_set_enable_tree_lines (tree_view, g_value_get_boolean (value));
1843       break;
1844     case PROP_TOOLTIP_COLUMN:
1845       gtk_tree_view_set_tooltip_column (tree_view, g_value_get_int (value));
1846       break;
1847     default:
1848       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1849       break;
1850     }
1851 }
1852
1853 static void
1854 gtk_tree_view_get_property (GObject    *object,
1855                             guint       prop_id,
1856                             GValue     *value,
1857                             GParamSpec *pspec)
1858 {
1859   GtkTreeView *tree_view;
1860
1861   tree_view = GTK_TREE_VIEW (object);
1862
1863   switch (prop_id)
1864     {
1865     case PROP_MODEL:
1866       g_value_set_object (value, tree_view->priv->model);
1867       break;
1868     case PROP_HADJUSTMENT:
1869       g_value_set_object (value, tree_view->priv->hadjustment);
1870       break;
1871     case PROP_VADJUSTMENT:
1872       g_value_set_object (value, tree_view->priv->vadjustment);
1873       break;
1874     case PROP_HSCROLL_POLICY:
1875       g_value_set_enum (value, tree_view->priv->hscroll_policy);
1876       break;
1877     case PROP_VSCROLL_POLICY:
1878       g_value_set_enum (value, tree_view->priv->vscroll_policy);
1879       break;
1880     case PROP_HEADERS_VISIBLE:
1881       g_value_set_boolean (value, gtk_tree_view_get_headers_visible (tree_view));
1882       break;
1883     case PROP_HEADERS_CLICKABLE:
1884       g_value_set_boolean (value, gtk_tree_view_get_headers_clickable (tree_view));
1885       break;
1886     case PROP_EXPANDER_COLUMN:
1887       g_value_set_object (value, tree_view->priv->expander_column);
1888       break;
1889     case PROP_REORDERABLE:
1890       g_value_set_boolean (value, tree_view->priv->reorderable);
1891       break;
1892     case PROP_RULES_HINT:
1893       g_value_set_boolean (value, tree_view->priv->has_rules);
1894       break;
1895     case PROP_ENABLE_SEARCH:
1896       g_value_set_boolean (value, tree_view->priv->enable_search);
1897       break;
1898     case PROP_SEARCH_COLUMN:
1899       g_value_set_int (value, tree_view->priv->search_column);
1900       break;
1901     case PROP_FIXED_HEIGHT_MODE:
1902       g_value_set_boolean (value, tree_view->priv->fixed_height_mode);
1903       break;
1904     case PROP_HOVER_SELECTION:
1905       g_value_set_boolean (value, tree_view->priv->hover_selection);
1906       break;
1907     case PROP_HOVER_EXPAND:
1908       g_value_set_boolean (value, tree_view->priv->hover_expand);
1909       break;
1910     case PROP_SHOW_EXPANDERS:
1911       g_value_set_boolean (value, tree_view->priv->show_expanders);
1912       break;
1913     case PROP_LEVEL_INDENTATION:
1914       g_value_set_int (value, tree_view->priv->level_indentation);
1915       break;
1916     case PROP_RUBBER_BANDING:
1917       g_value_set_boolean (value, tree_view->priv->rubber_banding_enable);
1918       break;
1919     case PROP_ENABLE_GRID_LINES:
1920       g_value_set_enum (value, tree_view->priv->grid_lines);
1921       break;
1922     case PROP_ENABLE_TREE_LINES:
1923       g_value_set_boolean (value, tree_view->priv->tree_lines_enabled);
1924       break;
1925     case PROP_TOOLTIP_COLUMN:
1926       g_value_set_int (value, tree_view->priv->tooltip_column);
1927       break;
1928     default:
1929       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1930       break;
1931     }
1932 }
1933
1934 static void
1935 gtk_tree_view_finalize (GObject *object)
1936 {
1937   G_OBJECT_CLASS (gtk_tree_view_parent_class)->finalize (object);
1938 }
1939
1940
1941 static GtkBuildableIface *parent_buildable_iface;
1942
1943 static void
1944 gtk_tree_view_buildable_init (GtkBuildableIface *iface)
1945 {
1946   parent_buildable_iface = g_type_interface_peek_parent (iface);
1947   iface->add_child = gtk_tree_view_buildable_add_child;
1948   iface->get_internal_child = gtk_tree_view_buildable_get_internal_child;
1949 }
1950
1951 static void
1952 gtk_tree_view_buildable_add_child (GtkBuildable *tree_view,
1953                                    GtkBuilder  *builder,
1954                                    GObject     *child,
1955                                    const gchar *type)
1956 {
1957   gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), GTK_TREE_VIEW_COLUMN (child));
1958 }
1959
1960 static GObject *
1961 gtk_tree_view_buildable_get_internal_child (GtkBuildable      *buildable,
1962                                             GtkBuilder        *builder,
1963                                             const gchar       *childname)
1964 {
1965     if (strcmp (childname, "selection") == 0)
1966       return G_OBJECT (GTK_TREE_VIEW (buildable)->priv->selection);
1967     
1968     return parent_buildable_iface->get_internal_child (buildable,
1969                                                        builder,
1970                                                        childname);
1971 }
1972
1973 /* GtkWidget Methods
1974  */
1975
1976 static void
1977 gtk_tree_view_free_rbtree (GtkTreeView *tree_view)
1978 {
1979   _gtk_rbtree_free (tree_view->priv->tree);
1980   
1981   tree_view->priv->tree = NULL;
1982   tree_view->priv->button_pressed_node = NULL;
1983   tree_view->priv->button_pressed_tree = NULL;
1984   tree_view->priv->prelight_tree = NULL;
1985   tree_view->priv->prelight_node = NULL;
1986   tree_view->priv->expanded_collapsed_node = NULL;
1987   tree_view->priv->expanded_collapsed_tree = NULL;
1988 }
1989
1990 static void
1991 gtk_tree_view_destroy (GtkWidget *widget)
1992 {
1993   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
1994   GList *list;
1995
1996   gtk_tree_view_stop_editing (tree_view, TRUE);
1997
1998   if (tree_view->priv->columns != NULL)
1999     {
2000       list = tree_view->priv->columns;
2001       while (list)
2002         {
2003           GtkTreeViewColumn *column;
2004           column = GTK_TREE_VIEW_COLUMN (list->data);
2005           list = list->next;
2006           gtk_tree_view_remove_column (tree_view, column);
2007         }
2008       tree_view->priv->columns = NULL;
2009     }
2010
2011   if (tree_view->priv->tree != NULL)
2012     {
2013       gtk_tree_view_unref_and_check_selection_tree (tree_view, tree_view->priv->tree);
2014
2015       gtk_tree_view_free_rbtree (tree_view);
2016     }
2017
2018   if (tree_view->priv->selection != NULL)
2019     {
2020       _gtk_tree_selection_set_tree_view (tree_view->priv->selection, NULL);
2021       g_object_unref (tree_view->priv->selection);
2022       tree_view->priv->selection = NULL;
2023     }
2024
2025   if (tree_view->priv->scroll_to_path != NULL)
2026     {
2027       gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
2028       tree_view->priv->scroll_to_path = NULL;
2029     }
2030
2031   if (tree_view->priv->drag_dest_row != NULL)
2032     {
2033       gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
2034       tree_view->priv->drag_dest_row = NULL;
2035     }
2036
2037   if (tree_view->priv->top_row != NULL)
2038     {
2039       gtk_tree_row_reference_free (tree_view->priv->top_row);
2040       tree_view->priv->top_row = NULL;
2041     }
2042
2043   if (tree_view->priv->column_drop_func_data &&
2044       tree_view->priv->column_drop_func_data_destroy)
2045     {
2046       tree_view->priv->column_drop_func_data_destroy (tree_view->priv->column_drop_func_data);
2047       tree_view->priv->column_drop_func_data = NULL;
2048     }
2049
2050   if (tree_view->priv->destroy_count_destroy &&
2051       tree_view->priv->destroy_count_data)
2052     {
2053       tree_view->priv->destroy_count_destroy (tree_view->priv->destroy_count_data);
2054       tree_view->priv->destroy_count_data = NULL;
2055     }
2056
2057   gtk_tree_row_reference_free (tree_view->priv->cursor);
2058   tree_view->priv->cursor = NULL;
2059
2060   gtk_tree_row_reference_free (tree_view->priv->anchor);
2061   tree_view->priv->anchor = NULL;
2062
2063   /* destroy interactive search dialog */
2064   if (tree_view->priv->search_window)
2065     {
2066       gtk_widget_destroy (tree_view->priv->search_window);
2067       tree_view->priv->search_window = NULL;
2068       tree_view->priv->search_entry = NULL;
2069       if (tree_view->priv->typeselect_flush_timeout)
2070         {
2071           g_source_remove (tree_view->priv->typeselect_flush_timeout);
2072           tree_view->priv->typeselect_flush_timeout = 0;
2073         }
2074     }
2075
2076   if (tree_view->priv->search_destroy && tree_view->priv->search_user_data)
2077     {
2078       tree_view->priv->search_destroy (tree_view->priv->search_user_data);
2079       tree_view->priv->search_user_data = NULL;
2080     }
2081
2082   if (tree_view->priv->search_position_destroy && tree_view->priv->search_position_user_data)
2083     {
2084       tree_view->priv->search_position_destroy (tree_view->priv->search_position_user_data);
2085       tree_view->priv->search_position_user_data = NULL;
2086     }
2087
2088   if (tree_view->priv->row_separator_destroy && tree_view->priv->row_separator_data)
2089     {
2090       tree_view->priv->row_separator_destroy (tree_view->priv->row_separator_data);
2091       tree_view->priv->row_separator_data = NULL;
2092     }
2093   
2094   gtk_tree_view_set_model (tree_view, NULL);
2095
2096   if (tree_view->priv->hadjustment)
2097     {
2098       g_object_unref (tree_view->priv->hadjustment);
2099       tree_view->priv->hadjustment = NULL;
2100     }
2101   if (tree_view->priv->vadjustment)
2102     {
2103       g_object_unref (tree_view->priv->vadjustment);
2104       tree_view->priv->vadjustment = NULL;
2105     }
2106
2107   GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->destroy (widget);
2108 }
2109
2110 /* GtkWidget::map helper */
2111 static void
2112 gtk_tree_view_map_buttons (GtkTreeView *tree_view)
2113 {
2114   GList *list;
2115
2116   g_return_if_fail (gtk_widget_get_mapped (GTK_WIDGET (tree_view)));
2117
2118   if (tree_view->priv->headers_visible)
2119     {
2120       GtkTreeViewColumn *column;
2121       GtkWidget         *button;
2122       GdkWindow         *window;
2123
2124       for (list = tree_view->priv->columns; list; list = list->next)
2125         {
2126           column = list->data;
2127           button = gtk_tree_view_column_get_button (column);
2128
2129           if (gtk_tree_view_column_get_visible (column) && button)
2130             gtk_widget_show_now (button);
2131
2132           if (gtk_widget_get_visible (button) &&
2133               !gtk_widget_get_mapped (button))
2134             gtk_widget_map (button);
2135         }
2136       for (list = tree_view->priv->columns; list; list = list->next)
2137         {
2138           column = list->data;
2139           if (gtk_tree_view_column_get_visible (column) == FALSE)
2140             continue;
2141
2142           window = _gtk_tree_view_column_get_window (column);
2143           if (gtk_tree_view_column_get_resizable (column))
2144             {
2145               gdk_window_raise (window);
2146               gdk_window_show (window);
2147             }
2148           else
2149             gdk_window_hide (window);
2150         }
2151       gdk_window_show (tree_view->priv->header_window);
2152     }
2153 }
2154
2155 static void
2156 gtk_tree_view_map (GtkWidget *widget)
2157 {
2158   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
2159   GList *tmp_list;
2160
2161   gtk_widget_set_mapped (widget, TRUE);
2162
2163   tmp_list = tree_view->priv->children;
2164   while (tmp_list)
2165     {
2166       GtkTreeViewChild *child = tmp_list->data;
2167       tmp_list = tmp_list->next;
2168
2169       if (gtk_widget_get_visible (child->widget))
2170         {
2171           if (!gtk_widget_get_mapped (child->widget))
2172             gtk_widget_map (child->widget);
2173         }
2174     }
2175   gdk_window_show (tree_view->priv->bin_window);
2176
2177   gtk_tree_view_map_buttons (tree_view);
2178
2179   gdk_window_show (gtk_widget_get_window (widget));
2180 }
2181
2182 static void
2183 gtk_tree_view_realize (GtkWidget *widget)
2184 {
2185   GtkAllocation allocation;
2186   GtkStyleContext *context;
2187   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
2188   GdkWindow *window;
2189   GdkWindowAttr attributes;
2190   GList *tmp_list;
2191   gint attributes_mask;
2192
2193   gtk_widget_set_realized (widget, TRUE);
2194
2195   gtk_widget_get_allocation (widget, &allocation);
2196
2197   /* Make the main, clipping window */
2198   attributes.window_type = GDK_WINDOW_CHILD;
2199   attributes.x = allocation.x;
2200   attributes.y = allocation.y;
2201   attributes.width = allocation.width;
2202   attributes.height = allocation.height;
2203   attributes.wclass = GDK_INPUT_OUTPUT;
2204   attributes.visual = gtk_widget_get_visual (widget);
2205   attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
2206
2207   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
2208
2209   window = gdk_window_new (gtk_widget_get_parent_window (widget),
2210                            &attributes, attributes_mask);
2211   gtk_widget_set_window (widget, window);
2212   gdk_window_set_user_data (window, widget);
2213
2214   gtk_widget_get_allocation (widget, &allocation);
2215
2216   /* Make the window for the tree */
2217   attributes.x = 0;
2218   attributes.y = gtk_tree_view_get_effective_header_height (tree_view);
2219   attributes.width = MAX (tree_view->priv->width, allocation.width);
2220   attributes.height = allocation.height;
2221   attributes.event_mask = (GDK_EXPOSURE_MASK |
2222                            GDK_SCROLL_MASK |
2223                            GDK_POINTER_MOTION_MASK |
2224                            GDK_ENTER_NOTIFY_MASK |
2225                            GDK_LEAVE_NOTIFY_MASK |
2226                            GDK_BUTTON_PRESS_MASK |
2227                            GDK_BUTTON_RELEASE_MASK |
2228                            gtk_widget_get_events (widget));
2229
2230   tree_view->priv->bin_window = gdk_window_new (window,
2231                                                 &attributes, attributes_mask);
2232   gdk_window_set_user_data (tree_view->priv->bin_window, widget);
2233
2234   gtk_widget_get_allocation (widget, &allocation);
2235
2236   /* Make the column header window */
2237   attributes.x = 0;
2238   attributes.y = 0;
2239   attributes.width = MAX (tree_view->priv->width, allocation.width);
2240   attributes.height = tree_view->priv->header_height;
2241   attributes.event_mask = (GDK_EXPOSURE_MASK |
2242                            GDK_SCROLL_MASK |
2243                            GDK_ENTER_NOTIFY_MASK |
2244                            GDK_LEAVE_NOTIFY_MASK |
2245                            GDK_BUTTON_PRESS_MASK |
2246                            GDK_BUTTON_RELEASE_MASK |
2247                            GDK_KEY_PRESS_MASK |
2248                            GDK_KEY_RELEASE_MASK |
2249                            gtk_widget_get_events (widget));
2250
2251   tree_view->priv->header_window = gdk_window_new (window,
2252                                                    &attributes, attributes_mask);
2253   gdk_window_set_user_data (tree_view->priv->header_window, widget);
2254
2255   context = gtk_widget_get_style_context (widget);
2256
2257   gtk_style_context_save (context);
2258   gtk_style_context_add_class (context, GTK_STYLE_CLASS_VIEW);
2259   gtk_style_context_set_background (context, tree_view->priv->bin_window);
2260   gtk_style_context_restore (context);
2261
2262   gtk_style_context_set_background (context, tree_view->priv->header_window);
2263
2264   tmp_list = tree_view->priv->children;
2265   while (tmp_list)
2266     {
2267       GtkTreeViewChild *child = tmp_list->data;
2268       tmp_list = tmp_list->next;
2269
2270       gtk_widget_set_parent_window (child->widget, tree_view->priv->bin_window);
2271     }
2272
2273   for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
2274     _gtk_tree_view_column_realize_button (GTK_TREE_VIEW_COLUMN (tmp_list->data));
2275
2276   /* Need to call those here, since they create GCs */
2277   gtk_tree_view_set_grid_lines (tree_view, tree_view->priv->grid_lines);
2278   gtk_tree_view_set_enable_tree_lines (tree_view, tree_view->priv->tree_lines_enabled);
2279
2280   install_presize_handler (tree_view); 
2281 }
2282
2283 static void
2284 gtk_tree_view_unrealize (GtkWidget *widget)
2285 {
2286   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
2287   GtkTreeViewPrivate *priv = tree_view->priv;
2288   GtkStyleContext *context;
2289   GList *list;
2290
2291   if (priv->scroll_timeout != 0)
2292     {
2293       g_source_remove (priv->scroll_timeout);
2294       priv->scroll_timeout = 0;
2295     }
2296
2297   if (priv->auto_expand_timeout != 0)
2298     {
2299       g_source_remove (priv->auto_expand_timeout);
2300       priv->auto_expand_timeout = 0;
2301     }
2302
2303   if (priv->open_dest_timeout != 0)
2304     {
2305       g_source_remove (priv->open_dest_timeout);
2306       priv->open_dest_timeout = 0;
2307     }
2308
2309   context = gtk_widget_get_style_context (widget);
2310   gtk_style_context_cancel_animations (context, NULL);
2311
2312   if (priv->presize_handler_timer != 0)
2313     {
2314       g_source_remove (priv->presize_handler_timer);
2315       priv->presize_handler_timer = 0;
2316     }
2317
2318   if (priv->validate_rows_timer != 0)
2319     {
2320       g_source_remove (priv->validate_rows_timer);
2321       priv->validate_rows_timer = 0;
2322     }
2323
2324   if (priv->scroll_sync_timer != 0)
2325     {
2326       g_source_remove (priv->scroll_sync_timer);
2327       priv->scroll_sync_timer = 0;
2328     }
2329
2330   if (priv->typeselect_flush_timeout)
2331     {
2332       g_source_remove (priv->typeselect_flush_timeout);
2333       priv->typeselect_flush_timeout = 0;
2334     }
2335   
2336   for (list = priv->columns; list; list = list->next)
2337     _gtk_tree_view_column_unrealize_button (GTK_TREE_VIEW_COLUMN (list->data));
2338
2339   gdk_window_set_user_data (priv->bin_window, NULL);
2340   gdk_window_destroy (priv->bin_window);
2341   priv->bin_window = NULL;
2342
2343   gdk_window_set_user_data (priv->header_window, NULL);
2344   gdk_window_destroy (priv->header_window);
2345   priv->header_window = NULL;
2346
2347   if (priv->drag_window)
2348     {
2349       gdk_window_set_user_data (priv->drag_window, NULL);
2350       gdk_window_destroy (priv->drag_window);
2351       priv->drag_window = NULL;
2352     }
2353
2354   if (priv->drag_highlight_window)
2355     {
2356       gdk_window_set_user_data (priv->drag_highlight_window, NULL);
2357       gdk_window_destroy (priv->drag_highlight_window);
2358       priv->drag_highlight_window = NULL;
2359     }
2360
2361   GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->unrealize (widget);
2362 }
2363
2364 /* GtkWidget::size_request helper */
2365 static void
2366 gtk_tree_view_size_request_columns (GtkTreeView *tree_view)
2367 {
2368   GList *list;
2369
2370   tree_view->priv->header_height = 0;
2371
2372   for (list = tree_view->priv->columns; list; list = list->next)
2373     {
2374       GtkRequisition     requisition;
2375       GtkTreeViewColumn *column = list->data;
2376       GtkWidget         *button = gtk_tree_view_column_get_button (column);
2377
2378       if (button == NULL)
2379         continue;
2380
2381       gtk_widget_get_preferred_size (button, &requisition, NULL);
2382       tree_view->priv->header_height = MAX (tree_view->priv->header_height, requisition.height);
2383     }
2384 }
2385
2386
2387 /* Called only by ::size_request */
2388 static void
2389 gtk_tree_view_update_size (GtkTreeView *tree_view)
2390 {
2391   GList *list;
2392   GtkTreeViewColumn *column;
2393   gint i;
2394
2395   if (tree_view->priv->model == NULL)
2396     {
2397       tree_view->priv->width = 0;
2398       tree_view->priv->prev_width = 0;                   
2399       tree_view->priv->height = 0;
2400       return;
2401     }
2402
2403   tree_view->priv->prev_width = tree_view->priv->width;  
2404   tree_view->priv->width = 0;
2405
2406   /* keep this in sync with size_allocate below */
2407   for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++)
2408     {
2409       column = list->data;
2410       if (!gtk_tree_view_column_get_visible (column))
2411         continue;
2412
2413       tree_view->priv->width += _gtk_tree_view_column_request_width (column);
2414     }
2415
2416   if (tree_view->priv->tree == NULL)
2417     tree_view->priv->height = 0;
2418   else
2419     tree_view->priv->height = tree_view->priv->tree->root->offset;
2420 }
2421
2422 static void
2423 gtk_tree_view_size_request (GtkWidget      *widget,
2424                             GtkRequisition *requisition,
2425                             gboolean        may_validate)
2426 {
2427   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
2428
2429   if (may_validate)
2430     {
2431       /* we validate some rows initially just to make sure we have some size.
2432        * In practice, with a lot of static lists, this should get a good width.
2433        */
2434       do_validate_rows (tree_view, FALSE);
2435     }
2436
2437   gtk_tree_view_size_request_columns (tree_view);
2438   gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
2439
2440   requisition->width = tree_view->priv->width;
2441   requisition->height = tree_view->priv->height + gtk_tree_view_get_effective_header_height (tree_view);
2442 }
2443
2444 static void
2445 gtk_tree_view_get_preferred_width (GtkWidget *widget,
2446                                    gint      *minimum,
2447                                    gint      *natural)
2448 {
2449   GtkRequisition requisition;
2450
2451   gtk_tree_view_size_request (widget, &requisition, TRUE);
2452
2453   *minimum = *natural = requisition.width;
2454 }
2455
2456 static void
2457 gtk_tree_view_get_preferred_height (GtkWidget *widget,
2458                                     gint      *minimum,
2459                                     gint      *natural)
2460 {
2461   GtkRequisition requisition;
2462
2463   gtk_tree_view_size_request (widget, &requisition, TRUE);
2464
2465   *minimum = *natural = requisition.height;
2466 }
2467
2468 static int
2469 gtk_tree_view_calculate_width_before_expander (GtkTreeView *tree_view)
2470 {
2471   int width = 0;
2472   GList *list;
2473   gboolean rtl;
2474
2475   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
2476   for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
2477        list->data != tree_view->priv->expander_column;
2478        list = (rtl ? list->prev : list->next))
2479     {
2480       GtkTreeViewColumn *column = list->data;
2481
2482       width += gtk_tree_view_column_get_width (column);
2483     }
2484
2485   return width;
2486 }
2487
2488 /* GtkWidget::size_allocate helper */
2489 static void
2490 gtk_tree_view_size_allocate_columns (GtkWidget *widget,
2491                                      gboolean  *width_changed)
2492 {
2493   GtkTreeView *tree_view;
2494   GList *list, *first_column, *last_column;
2495   GtkTreeViewColumn *column;
2496   GtkAllocation widget_allocation;
2497   gint width = 0;
2498   gint extra, extra_per_column, extra_for_last;
2499   gint full_requested_width = 0;
2500   gint number_of_expand_columns = 0;
2501   gboolean rtl;
2502   gboolean update_expand;
2503   
2504   tree_view = GTK_TREE_VIEW (widget);
2505
2506   for (last_column = g_list_last (tree_view->priv->columns);
2507        last_column &&
2508        !(gtk_tree_view_column_get_visible (GTK_TREE_VIEW_COLUMN (last_column->data)));
2509        last_column = last_column->prev)
2510     ;
2511   if (last_column == NULL)
2512     return;
2513
2514   for (first_column = g_list_first (tree_view->priv->columns);
2515        first_column &&
2516        !(gtk_tree_view_column_get_visible (GTK_TREE_VIEW_COLUMN (first_column->data)));
2517        first_column = first_column->next)
2518     ;
2519
2520   rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
2521
2522   /* find out how many extra space and expandable columns we have */
2523   for (list = tree_view->priv->columns; list != last_column->next; list = list->next)
2524     {
2525       column = (GtkTreeViewColumn *)list->data;
2526
2527       if (!gtk_tree_view_column_get_visible (column))
2528         continue;
2529
2530       full_requested_width += _gtk_tree_view_column_request_width (column);
2531
2532       if (gtk_tree_view_column_get_expand (column))
2533         number_of_expand_columns++;
2534     }
2535
2536   /* Only update the expand value if the width of the widget has changed,
2537    * or the number of expand columns has changed, or if there are no expand
2538    * columns, or if we didn't have an size-allocation yet after the
2539    * last validated node.
2540    */
2541   update_expand = (width_changed && *width_changed == TRUE)
2542       || number_of_expand_columns != tree_view->priv->last_number_of_expand_columns
2543       || number_of_expand_columns == 0
2544       || tree_view->priv->post_validation_flag == TRUE;
2545
2546   tree_view->priv->post_validation_flag = FALSE;
2547
2548   gtk_widget_get_allocation (widget, &widget_allocation);
2549   if (!update_expand)
2550     {
2551       extra = tree_view->priv->last_extra_space;
2552       extra_for_last = MAX (widget_allocation.width - full_requested_width - extra, 0);
2553     }
2554   else
2555     {
2556       extra = MAX (widget_allocation.width - full_requested_width, 0);
2557       extra_for_last = 0;
2558
2559       tree_view->priv->last_extra_space = extra;
2560     }
2561
2562   if (number_of_expand_columns > 0)
2563     extra_per_column = extra/number_of_expand_columns;
2564   else
2565     extra_per_column = 0;
2566
2567   if (update_expand)
2568     {
2569       tree_view->priv->last_extra_space_per_column = extra_per_column;
2570       tree_view->priv->last_number_of_expand_columns = number_of_expand_columns;
2571     }
2572
2573   for (list = (rtl ? last_column : first_column); 
2574        list != (rtl ? first_column->prev : last_column->next);
2575        list = (rtl ? list->prev : list->next)) 
2576     {
2577       gint column_width;
2578
2579       column = list->data;
2580
2581       if (!gtk_tree_view_column_get_visible (column))
2582         continue;
2583
2584       /* We need to handle the dragged button specially.
2585        */
2586       if (column == tree_view->priv->drag_column)
2587         {
2588           GtkAllocation drag_allocation;
2589           GtkWidget    *button;
2590
2591           button = gtk_tree_view_column_get_button (tree_view->priv->drag_column);
2592
2593           drag_allocation.x = 0;
2594           drag_allocation.y = 0;
2595           drag_allocation.width = gdk_window_get_width (tree_view->priv->drag_window);
2596           drag_allocation.height = gdk_window_get_height (tree_view->priv->drag_window);
2597           gtk_widget_size_allocate (button, &drag_allocation);
2598           width += drag_allocation.width;
2599           continue;
2600         }
2601
2602       column_width = _gtk_tree_view_column_request_width (column);
2603
2604       if (gtk_tree_view_column_get_expand (column))
2605         {
2606           if (number_of_expand_columns == 1)
2607             {
2608               /* We add the remander to the last column as
2609                * */
2610               column_width += extra;
2611             }
2612           else
2613             {
2614               column_width += extra_per_column;
2615               extra -= extra_per_column;
2616               number_of_expand_columns --;
2617             }
2618         }
2619       else if (number_of_expand_columns == 0 &&
2620                list == last_column)
2621         {
2622           column_width += extra;
2623         }
2624
2625       /* In addition to expand, the last column can get even more
2626        * extra space so all available space is filled up.
2627        */
2628       if (extra_for_last > 0 && list == last_column)
2629         column_width += extra_for_last;
2630
2631       _gtk_tree_view_column_allocate (column, width, column_width);
2632
2633       width += column_width;
2634     }
2635
2636   /* We change the width here.  The user might have been resizing columns,
2637    * which changes the total width of the tree view.  This is of
2638    * importance for getting the horizontal scroll bar right.
2639    */
2640   if (tree_view->priv->width != width)
2641     {
2642       tree_view->priv->width = width;
2643       if (width_changed)
2644         *width_changed = TRUE;
2645     }
2646 }
2647
2648
2649 static void
2650 gtk_tree_view_size_allocate (GtkWidget     *widget,
2651                              GtkAllocation *allocation)
2652 {
2653   GtkAllocation widget_allocation;
2654   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
2655   GList *tmp_list;
2656   gboolean width_changed = FALSE;
2657   gint old_width;
2658
2659   gtk_widget_get_allocation (widget, &widget_allocation);
2660   old_width = widget_allocation.width;
2661   if (allocation->width != widget_allocation.width)
2662     width_changed = TRUE;
2663
2664   gtk_widget_set_allocation (widget, allocation);
2665
2666   tmp_list = tree_view->priv->children;
2667
2668   while (tmp_list)
2669     {
2670       GtkAllocation allocation;
2671
2672       GtkTreeViewChild *child = tmp_list->data;
2673       tmp_list = tmp_list->next;
2674
2675       /* totally ignore our child's requisition */
2676       allocation.x = child->x;
2677       allocation.y = child->y;
2678       allocation.width = child->width;
2679       allocation.height = child->height;
2680       gtk_widget_size_allocate (child->widget, &allocation);
2681     }
2682
2683   /* We size-allocate the columns first because the width of the
2684    * tree view (used in updating the adjustments below) might change.
2685    */
2686   gtk_tree_view_size_allocate_columns (widget, &width_changed);
2687
2688   g_object_freeze_notify (G_OBJECT (tree_view->priv->hadjustment));
2689   gtk_adjustment_set_page_size (tree_view->priv->hadjustment,
2690                                 allocation->width);
2691   gtk_adjustment_set_page_increment (tree_view->priv->hadjustment,
2692                                      allocation->width * 0.9);
2693   gtk_adjustment_set_step_increment (tree_view->priv->hadjustment,
2694                                      allocation->width * 0.1);
2695   gtk_adjustment_set_lower (tree_view->priv->hadjustment, 0);
2696   gtk_adjustment_set_upper (tree_view->priv->hadjustment,
2697                             MAX (gtk_adjustment_get_page_size (tree_view->priv->hadjustment),
2698                                  tree_view->priv->width));
2699   g_object_thaw_notify (G_OBJECT (tree_view->priv->hadjustment));
2700
2701   if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL)   
2702     {
2703       if (allocation->width < tree_view->priv->width)
2704         {
2705           if (tree_view->priv->init_hadjust_value)
2706             {
2707               gtk_adjustment_set_value (tree_view->priv->hadjustment,
2708                                         MAX (tree_view->priv->width -
2709                                              allocation->width, 0));
2710               tree_view->priv->init_hadjust_value = FALSE;
2711             }
2712           else if (allocation->width != old_width)
2713             {
2714               gtk_adjustment_set_value (tree_view->priv->hadjustment,
2715                                         CLAMP (gtk_adjustment_get_value (tree_view->priv->hadjustment) - allocation->width + old_width,
2716                                                0,
2717                                                tree_view->priv->width - allocation->width));
2718             }
2719           else
2720             gtk_adjustment_set_value (tree_view->priv->hadjustment,
2721                                       CLAMP (tree_view->priv->width - (tree_view->priv->prev_width - gtk_adjustment_get_value (tree_view->priv->hadjustment)),
2722                                              0,
2723                                              tree_view->priv->width - allocation->width));
2724         }
2725       else
2726         {
2727           gtk_adjustment_set_value (tree_view->priv->hadjustment, 0);
2728           tree_view->priv->init_hadjust_value = TRUE;
2729         }
2730     }
2731   else
2732     if (gtk_adjustment_get_value (tree_view->priv->hadjustment) + allocation->width > tree_view->priv->width)
2733       gtk_adjustment_set_value (tree_view->priv->hadjustment,
2734                                 MAX (tree_view->priv->width -
2735                                      allocation->width, 0));
2736
2737   g_object_freeze_notify (G_OBJECT (tree_view->priv->vadjustment));
2738   gtk_adjustment_set_page_size (tree_view->priv->vadjustment,
2739                                 allocation->height -
2740                                 gtk_tree_view_get_effective_header_height (tree_view));
2741   gtk_adjustment_set_step_increment (tree_view->priv->vadjustment,
2742                                      gtk_adjustment_get_page_size (tree_view->priv->vadjustment) * 0.1);
2743   gtk_adjustment_set_page_increment (tree_view->priv->vadjustment,
2744                                      gtk_adjustment_get_page_size (tree_view->priv->vadjustment) * 0.9);
2745   gtk_adjustment_set_lower (tree_view->priv->vadjustment, 0);
2746   gtk_adjustment_set_upper (tree_view->priv->vadjustment,
2747                             MAX (gtk_adjustment_get_page_size (tree_view->priv->vadjustment),
2748                                  tree_view->priv->height));
2749   g_object_thaw_notify (G_OBJECT (tree_view->priv->vadjustment));
2750
2751   /* now the adjustments and window sizes are in sync, we can sync toprow/dy again */
2752   if (tree_view->priv->height <= gtk_adjustment_get_page_size (tree_view->priv->vadjustment))
2753     gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), 0);
2754   else if (gtk_adjustment_get_value (tree_view->priv->vadjustment) + gtk_adjustment_get_page_size (tree_view->priv->vadjustment) > tree_view->priv->height)
2755     gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment),
2756                               tree_view->priv->height - gtk_adjustment_get_page_size (tree_view->priv->vadjustment));
2757   else if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
2758     gtk_tree_view_top_row_to_dy (tree_view);
2759   else
2760     gtk_tree_view_dy_to_top_row (tree_view);
2761   
2762   if (gtk_widget_get_realized (widget))
2763     {
2764       gdk_window_move_resize (gtk_widget_get_window (widget),
2765                               allocation->x, allocation->y,
2766                               allocation->width, allocation->height);
2767       gdk_window_move_resize (tree_view->priv->header_window,
2768                               - (gint) gtk_adjustment_get_value (tree_view->priv->hadjustment),
2769                               0,
2770                               MAX (tree_view->priv->width, allocation->width),
2771                               tree_view->priv->header_height);
2772       gdk_window_move_resize (tree_view->priv->bin_window,
2773                               - (gint) gtk_adjustment_get_value (tree_view->priv->hadjustment),
2774                               gtk_tree_view_get_effective_header_height (tree_view),
2775                               MAX (tree_view->priv->width, allocation->width),
2776                               allocation->height - gtk_tree_view_get_effective_header_height (tree_view));
2777
2778       if (tree_view->priv->tree == NULL)
2779         invalidate_empty_focus (tree_view);
2780
2781       if (width_changed && tree_view->priv->expander_column)
2782         {
2783           /* Might seem awkward, but is the best heuristic I could come up
2784            * with.  Only if the width of the columns before the expander
2785            * changes, we will update the prelight status.  It is this
2786            * width that makes the expander move vertically.  Always updating
2787            * prelight status causes trouble with hover selections.
2788            */
2789           gint width_before_expander;
2790
2791           width_before_expander = gtk_tree_view_calculate_width_before_expander (tree_view);
2792
2793           if (tree_view->priv->prev_width_before_expander
2794               != width_before_expander)
2795               update_prelight (tree_view,
2796                                tree_view->priv->event_last_x,
2797                                tree_view->priv->event_last_y);
2798
2799           tree_view->priv->prev_width_before_expander = width_before_expander;
2800         }
2801     }
2802 }
2803
2804 /* Grabs the focus and unsets the GTK_TREE_VIEW_DRAW_KEYFOCUS flag */
2805 static void
2806 grab_focus_and_unset_draw_keyfocus (GtkTreeView *tree_view)
2807 {
2808   GtkWidget *widget = GTK_WIDGET (tree_view);
2809
2810   if (gtk_widget_get_can_focus (widget) && !gtk_widget_has_focus (widget))
2811     gtk_widget_grab_focus (widget);
2812   tree_view->priv->draw_keyfocus = 0;
2813 }
2814
2815 static inline gboolean
2816 row_is_separator (GtkTreeView *tree_view,
2817                   GtkTreeIter *iter,
2818                   GtkTreePath *path)
2819 {
2820   gboolean is_separator = FALSE;
2821
2822   if (tree_view->priv->row_separator_func)
2823     {
2824       GtkTreeIter tmpiter;
2825
2826       if (iter)
2827         tmpiter = *iter;
2828       else
2829         {
2830           if (!gtk_tree_model_get_iter (tree_view->priv->model, &tmpiter, path))
2831             return FALSE;
2832         }
2833
2834       is_separator = tree_view->priv->row_separator_func (tree_view->priv->model,
2835                                                           &tmpiter,
2836                                                           tree_view->priv->row_separator_data);
2837     }
2838
2839   return is_separator;
2840 }
2841
2842 static gboolean
2843 gtk_tree_view_button_press (GtkWidget      *widget,
2844                             GdkEventButton *event)
2845 {
2846   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
2847   GList *list;
2848   GtkTreeViewColumn *column = NULL;
2849   gint i;
2850   GdkRectangle background_area;
2851   GdkRectangle cell_area;
2852   gint vertical_separator;
2853   gint horizontal_separator;
2854   gboolean path_is_selectable;
2855   gboolean rtl;
2856
2857   rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
2858   gtk_tree_view_stop_editing (tree_view, FALSE);
2859   gtk_widget_style_get (widget,
2860                         "vertical-separator", &vertical_separator,
2861                         "horizontal-separator", &horizontal_separator,
2862                         NULL);
2863
2864   /* Because grab_focus can cause reentrancy, we delay grab_focus until after
2865    * we're done handling the button press.
2866    */
2867
2868   if (event->window == tree_view->priv->bin_window)
2869     {
2870       GtkRBNode *node;
2871       GtkRBTree *tree;
2872       GtkTreePath *path;
2873       gint depth;
2874       gint new_y;
2875       gint y_offset;
2876       gint dval;
2877       gint pre_val, aft_val;
2878       GtkTreeViewColumn *column = NULL;
2879       gint column_handled_click = FALSE;
2880       gboolean row_double_click = FALSE;
2881       gboolean rtl;
2882       gboolean node_selected;
2883
2884       /* Empty tree? */
2885       if (tree_view->priv->tree == NULL)
2886         {
2887           grab_focus_and_unset_draw_keyfocus (tree_view);
2888           return TRUE;
2889         }
2890
2891       /* are we in an arrow? */
2892       if (tree_view->priv->prelight_node &&
2893           tree_view->priv->arrow_prelit &&
2894           gtk_tree_view_draw_expanders (tree_view))
2895         {
2896           if (event->button == 1)
2897             {
2898               gtk_grab_add (widget);
2899               tree_view->priv->button_pressed_node = tree_view->priv->prelight_node;
2900               tree_view->priv->button_pressed_tree = tree_view->priv->prelight_tree;
2901               gtk_tree_view_queue_draw_arrow (GTK_TREE_VIEW (widget),
2902                                               tree_view->priv->prelight_tree,
2903                                               tree_view->priv->prelight_node);
2904             }
2905
2906           grab_focus_and_unset_draw_keyfocus (tree_view);
2907           return TRUE;
2908         }
2909
2910       /* find the node that was clicked */
2911       new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
2912       if (new_y < 0)
2913         new_y = 0;
2914       y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
2915
2916       if (node == NULL)
2917         {
2918           /* We clicked in dead space */
2919           grab_focus_and_unset_draw_keyfocus (tree_view);
2920           return TRUE;
2921         }
2922
2923       /* Get the path and the node */
2924       path = _gtk_tree_view_find_path (tree_view, tree, node);
2925       path_is_selectable = !row_is_separator (tree_view, NULL, path);
2926
2927       if (!path_is_selectable)
2928         {
2929           gtk_tree_path_free (path);
2930           grab_focus_and_unset_draw_keyfocus (tree_view);
2931           return TRUE;
2932         }
2933
2934       depth = gtk_tree_path_get_depth (path);
2935       background_area.y = y_offset + event->y;
2936       background_area.height = gtk_tree_view_get_row_height (tree_view, node);
2937       background_area.x = 0;
2938
2939
2940       /* Let the column have a chance at selecting it. */
2941       rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
2942       for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
2943            list; list = (rtl ? list->prev : list->next))
2944         {
2945           GtkTreeViewColumn *candidate = list->data;
2946
2947           if (!gtk_tree_view_column_get_visible (candidate))
2948             continue;
2949
2950           background_area.width = gtk_tree_view_column_get_width (candidate);
2951           if ((background_area.x > (gint) event->x) ||
2952               (background_area.x + background_area.width <= (gint) event->x))
2953             {
2954               background_area.x += background_area.width;
2955               continue;
2956             }
2957
2958           /* we found the focus column */
2959           column = candidate;
2960           cell_area = background_area;
2961           cell_area.width -= horizontal_separator;
2962           cell_area.height -= vertical_separator;
2963           cell_area.x += horizontal_separator/2;
2964           cell_area.y += vertical_separator/2;
2965           if (gtk_tree_view_is_expander_column (tree_view, column))
2966             {
2967               if (!rtl)
2968                 cell_area.x += (depth - 1) * tree_view->priv->level_indentation;
2969               cell_area.width -= (depth - 1) * tree_view->priv->level_indentation;
2970
2971               if (gtk_tree_view_draw_expanders (tree_view))
2972                 {
2973                   if (!rtl)
2974                     cell_area.x += depth * tree_view->priv->expander_size;
2975                   cell_area.width -= depth * tree_view->priv->expander_size;
2976                 }
2977             }
2978           break;
2979         }
2980
2981       if (column == NULL)
2982         {
2983           gtk_tree_path_free (path);
2984           grab_focus_and_unset_draw_keyfocus (tree_view);
2985           return FALSE;
2986         }
2987
2988       tree_view->priv->focus_column = column;
2989
2990       /* decide if we edit */
2991       if (event->type == GDK_BUTTON_PRESS && event->button == 1 &&
2992           !(event->state & gtk_accelerator_get_default_mod_mask ()))
2993         {
2994           GtkTreePath *anchor;
2995           GtkTreeIter iter;
2996
2997           gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
2998           gtk_tree_view_column_cell_set_cell_data (column,
2999                                                    tree_view->priv->model,
3000                                                    &iter,
3001                                                    GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
3002                                                    node->children?TRUE:FALSE);
3003
3004           if (tree_view->priv->anchor)
3005             anchor = gtk_tree_row_reference_get_path (tree_view->priv->anchor);
3006           else
3007             anchor = NULL;
3008
3009           if ((anchor && !gtk_tree_path_compare (anchor, path))
3010               || !_gtk_tree_view_column_has_editable_cell (column))
3011             {
3012               GtkCellEditable *cell_editable = NULL;
3013
3014               /* FIXME: get the right flags */
3015               guint flags = 0;
3016
3017               if (_gtk_tree_view_column_cell_event (column,
3018                                                     (GdkEvent *)event,
3019                                                     &cell_area, flags))
3020                 {
3021                   GtkCellArea *area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (column));
3022                   cell_editable = gtk_cell_area_get_edit_widget (area);
3023
3024                   if (cell_editable != NULL)
3025                     {
3026                       gtk_tree_path_free (path);
3027                       gtk_tree_path_free (anchor);
3028                       return TRUE;
3029                     }
3030                   column_handled_click = TRUE;
3031                 }
3032             }
3033           if (anchor)
3034             gtk_tree_path_free (anchor);
3035         }
3036
3037       /* select */
3038       node_selected = GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED);
3039       pre_val = gtk_adjustment_get_value (tree_view->priv->vadjustment);
3040
3041       /* we only handle selection modifications on the first button press
3042        */
3043       if (event->type == GDK_BUTTON_PRESS)
3044         {
3045           GtkCellRenderer *focus_cell;
3046
3047           if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
3048             tree_view->priv->ctrl_pressed = TRUE;
3049           if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
3050             tree_view->priv->shift_pressed = TRUE;
3051
3052           /* We update the focus cell here, this is also needed if the
3053            * column does not contain an editable cell.  In this case,
3054            * GtkCellArea did not receive the event for processing (and
3055            * could not update the focus cell).
3056            */
3057           focus_cell = _gtk_tree_view_column_get_cell_at_pos (column,
3058                                                               &cell_area,
3059                                                               &background_area,
3060                                                               event->x,
3061                                                               event->y);
3062
3063           if (focus_cell)
3064             gtk_tree_view_column_focus_cell (column, focus_cell);
3065
3066           if (event->state & GDK_CONTROL_MASK)
3067             {
3068               gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
3069               gtk_tree_view_real_toggle_cursor_row (tree_view);
3070             }
3071           else if (event->state & GDK_SHIFT_MASK)
3072             {
3073               gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
3074               gtk_tree_view_real_select_cursor_row (tree_view, FALSE);
3075             }
3076           else
3077             {
3078               gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
3079             }
3080
3081           tree_view->priv->ctrl_pressed = FALSE;
3082           tree_view->priv->shift_pressed = FALSE;
3083         }
3084
3085       /* the treeview may have been scrolled because of _set_cursor,
3086        * correct here
3087        */
3088
3089       aft_val = gtk_adjustment_get_value (tree_view->priv->vadjustment);
3090       dval = pre_val - aft_val;
3091
3092       cell_area.y += dval;
3093       background_area.y += dval;
3094
3095       /* Save press to possibly begin a drag
3096        */
3097       if (!column_handled_click &&
3098           !tree_view->priv->in_grab &&
3099           tree_view->priv->pressed_button < 0)
3100         {
3101           tree_view->priv->pressed_button = event->button;
3102           tree_view->priv->press_start_x = event->x;
3103           tree_view->priv->press_start_y = event->y;
3104
3105           if (tree_view->priv->rubber_banding_enable
3106               && !node_selected
3107               && gtk_tree_selection_get_mode (tree_view->priv->selection) == GTK_SELECTION_MULTIPLE)
3108             {
3109               tree_view->priv->press_start_y += tree_view->priv->dy;
3110               tree_view->priv->rubber_band_x = event->x;
3111               tree_view->priv->rubber_band_y = event->y + tree_view->priv->dy;
3112               tree_view->priv->rubber_band_status = RUBBER_BAND_MAYBE_START;
3113
3114               if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
3115                 tree_view->priv->rubber_band_ctrl = TRUE;
3116               if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
3117                 tree_view->priv->rubber_band_shift = TRUE;
3118             }
3119         }
3120
3121       /* Test if a double click happened on the same row. */
3122       if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
3123         {
3124           int double_click_time, double_click_distance;
3125
3126           g_object_get (gtk_settings_get_default (),
3127                         "gtk-double-click-time", &double_click_time,
3128                         "gtk-double-click-distance", &double_click_distance,
3129                         NULL);
3130
3131           /* Same conditions as _gdk_event_button_generate */
3132           if (tree_view->priv->last_button_x != -1 &&
3133               (event->time < tree_view->priv->last_button_time + double_click_time) &&
3134               (ABS (event->x - tree_view->priv->last_button_x) <= double_click_distance) &&
3135               (ABS (event->y - tree_view->priv->last_button_y) <= double_click_distance))
3136             {
3137               /* We do no longer compare paths of this row and the
3138                * row clicked previously.  We use the double click
3139                * distance to decide whether this is a valid click,
3140                * allowing the mouse to slightly move over another row.
3141                */
3142               row_double_click = TRUE;
3143
3144               tree_view->priv->last_button_time = 0;
3145               tree_view->priv->last_button_x = -1;
3146               tree_view->priv->last_button_y = -1;
3147             }
3148           else
3149             {
3150               tree_view->priv->last_button_time = event->time;
3151               tree_view->priv->last_button_x = event->x;
3152               tree_view->priv->last_button_y = event->y;
3153             }
3154         }
3155
3156       if (row_double_click)
3157         {
3158           gtk_grab_remove (widget);
3159           gtk_tree_view_row_activated (tree_view, path, column);
3160
3161           if (tree_view->priv->pressed_button == event->button)
3162             tree_view->priv->pressed_button = -1;
3163         }
3164
3165       gtk_tree_path_free (path);
3166
3167       /* If we activated the row through a double click we don't want to grab
3168        * focus back, as moving focus to another widget is pretty common.
3169        */
3170       if (!row_double_click)
3171         grab_focus_and_unset_draw_keyfocus (tree_view);
3172
3173       return TRUE;
3174     }
3175
3176   /* We didn't click in the window.  Let's check to see if we clicked on a column resize window.
3177    */
3178   for (i = 0, list = tree_view->priv->columns; list; list = list->next, i++)
3179     {
3180       column = list->data;
3181       if (event->window == _gtk_tree_view_column_get_window (column) &&
3182           gtk_tree_view_column_get_resizable (column) &&
3183           _gtk_tree_view_column_get_window (column))
3184         {
3185           gpointer drag_data;
3186
3187           if (event->type == GDK_2BUTTON_PRESS &&
3188               gtk_tree_view_column_get_sizing (column) != GTK_TREE_VIEW_COLUMN_AUTOSIZE)
3189             {
3190               _gtk_tree_view_column_set_use_resized_width (column, FALSE);
3191               _gtk_tree_view_column_autosize (tree_view, column);
3192               return TRUE;
3193             }
3194
3195           if (gdk_device_grab (gdk_event_get_device ((GdkEvent*)event),
3196                                _gtk_tree_view_column_get_window (column),
3197                                GDK_OWNERSHIP_NONE,
3198                                FALSE,
3199                                GDK_POINTER_MOTION_HINT_MASK
3200                                 | GDK_BUTTON1_MOTION_MASK
3201                                 | GDK_BUTTON_RELEASE_MASK,
3202                                NULL,
3203                                event->time) != GDK_GRAB_SUCCESS)
3204             return FALSE;
3205
3206           gtk_grab_add (widget);
3207           tree_view->priv->in_column_resize = TRUE;
3208
3209           _gtk_tree_view_column_set_resized_width (column, gtk_tree_view_column_get_width (column) -
3210                                                    tree_view->priv->last_extra_space_per_column);
3211
3212           /* block attached dnd signal handler */
3213           drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
3214           if (drag_data)
3215             g_signal_handlers_block_matched (widget,
3216                                              G_SIGNAL_MATCH_DATA,
3217                                              0, 0, NULL, NULL,
3218                                              drag_data);
3219
3220           tree_view->priv->drag_pos = i;
3221           tree_view->priv->x_drag = gtk_tree_view_column_get_x_offset (column) + (rtl ? 0 : gtk_tree_view_column_get_width (column));
3222
3223           if (!gtk_widget_has_focus (widget))
3224             gtk_widget_grab_focus (widget);
3225
3226           return TRUE;
3227         }
3228     }
3229   return FALSE;
3230 }
3231
3232 /* GtkWidget::button_release_event helper */
3233 static gboolean
3234 gtk_tree_view_button_release_drag_column (GtkWidget      *widget,
3235                                           GdkEventButton *event)
3236 {
3237   GtkTreeView *tree_view;
3238   GtkWidget *button;
3239   GList *l;
3240   gboolean rtl;
3241   GdkDevice *device, *other;
3242
3243   tree_view = GTK_TREE_VIEW (widget);
3244
3245   rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
3246   device = gdk_event_get_device ((GdkEvent*)event);
3247   other = gdk_device_get_associated_device (device);
3248   gdk_device_ungrab (device, event->time);
3249   gdk_device_ungrab (other, event->time);
3250
3251   /* Move the button back */
3252   button = gtk_tree_view_column_get_button (tree_view->priv->drag_column);
3253   g_object_ref (button);
3254   gtk_container_remove (GTK_CONTAINER (tree_view), button);
3255   gtk_widget_set_parent_window (button, tree_view->priv->header_window);
3256   gtk_widget_set_parent (button, GTK_WIDGET (tree_view));
3257   g_object_unref (button);
3258   gtk_widget_queue_resize (widget);
3259   if (gtk_tree_view_column_get_resizable (tree_view->priv->drag_column))
3260     {
3261       gdk_window_raise (_gtk_tree_view_column_get_window (tree_view->priv->drag_column));
3262       gdk_window_show (_gtk_tree_view_column_get_window (tree_view->priv->drag_column));
3263     }
3264   else
3265     gdk_window_hide (_gtk_tree_view_column_get_window (tree_view->priv->drag_column));
3266
3267   gtk_widget_grab_focus (button);
3268
3269   if (rtl)
3270     {
3271       if (tree_view->priv->cur_reorder &&
3272           tree_view->priv->cur_reorder->right_column != tree_view->priv->drag_column)
3273         gtk_tree_view_move_column_after (tree_view, tree_view->priv->drag_column,
3274                                          tree_view->priv->cur_reorder->right_column);
3275     }
3276   else
3277     {
3278       if (tree_view->priv->cur_reorder &&
3279           tree_view->priv->cur_reorder->left_column != tree_view->priv->drag_column)
3280         gtk_tree_view_move_column_after (tree_view, tree_view->priv->drag_column,
3281                                          tree_view->priv->cur_reorder->left_column);
3282     }
3283   tree_view->priv->drag_column = NULL;
3284   gdk_window_hide (tree_view->priv->drag_window);
3285
3286   for (l = tree_view->priv->column_drag_info; l != NULL; l = l->next)
3287     g_slice_free (GtkTreeViewColumnReorder, l->data);
3288   g_list_free (tree_view->priv->column_drag_info);
3289   tree_view->priv->column_drag_info = NULL;
3290   tree_view->priv->cur_reorder = NULL;
3291
3292   if (tree_view->priv->drag_highlight_window)
3293     gdk_window_hide (tree_view->priv->drag_highlight_window);
3294
3295   /* Reset our flags */
3296   tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_UNSET;
3297   tree_view->priv->in_column_drag = FALSE;
3298
3299   return TRUE;
3300 }
3301
3302 /* GtkWidget::button_release_event helper */
3303 static gboolean
3304 gtk_tree_view_button_release_column_resize (GtkWidget      *widget,
3305                                             GdkEventButton *event)
3306 {
3307   GtkTreeView *tree_view;
3308   gpointer drag_data;
3309
3310   tree_view = GTK_TREE_VIEW (widget);
3311
3312   tree_view->priv->drag_pos = -1;
3313
3314   /* unblock attached dnd signal handler */
3315   drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
3316   if (drag_data)
3317     g_signal_handlers_unblock_matched (widget,
3318                                        G_SIGNAL_MATCH_DATA,
3319                                        0, 0, NULL, NULL,
3320                                        drag_data);
3321
3322   tree_view->priv->in_column_resize = FALSE;
3323   gtk_grab_remove (widget);
3324   gdk_device_ungrab (gdk_event_get_device ((GdkEvent*)event), event->time);
3325   return TRUE;
3326 }
3327
3328 static gboolean
3329 gtk_tree_view_button_release (GtkWidget      *widget,
3330                               GdkEventButton *event)
3331 {
3332   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
3333
3334   if (tree_view->priv->in_column_drag)
3335     return gtk_tree_view_button_release_drag_column (widget, event);
3336
3337   if (tree_view->priv->rubber_band_status)
3338     gtk_tree_view_stop_rubber_band (tree_view);
3339
3340   if (tree_view->priv->pressed_button == event->button)
3341     tree_view->priv->pressed_button = -1;
3342
3343   if (tree_view->priv->in_column_resize)
3344     return gtk_tree_view_button_release_column_resize (widget, event);
3345
3346   if (tree_view->priv->button_pressed_node == NULL)
3347     return FALSE;
3348
3349   if (event->button == 1)
3350     {
3351       if (tree_view->priv->button_pressed_node == tree_view->priv->prelight_node &&
3352           tree_view->priv->arrow_prelit)
3353         {
3354           GtkTreePath *path = NULL;
3355
3356           path = _gtk_tree_view_find_path (tree_view,
3357                                            tree_view->priv->button_pressed_tree,
3358                                            tree_view->priv->button_pressed_node);
3359           /* Actually activate the node */
3360           if (tree_view->priv->button_pressed_node->children == NULL)
3361             gtk_tree_view_real_expand_row (tree_view, path,
3362                                            tree_view->priv->button_pressed_tree,
3363                                            tree_view->priv->button_pressed_node,
3364                                            FALSE, TRUE);
3365           else
3366             gtk_tree_view_real_collapse_row (GTK_TREE_VIEW (widget), path,
3367                                              tree_view->priv->button_pressed_tree,
3368                                              tree_view->priv->button_pressed_node, TRUE);
3369           gtk_tree_path_free (path);
3370         }
3371
3372       gtk_grab_remove (widget);
3373       tree_view->priv->button_pressed_tree = NULL;
3374       tree_view->priv->button_pressed_node = NULL;
3375     }
3376
3377   return TRUE;
3378 }
3379
3380 static gboolean
3381 gtk_tree_view_grab_broken (GtkWidget          *widget,
3382                            GdkEventGrabBroken *event)
3383 {
3384   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
3385
3386   if (tree_view->priv->in_column_drag)
3387     gtk_tree_view_button_release_drag_column (widget, (GdkEventButton *)event);
3388
3389   if (tree_view->priv->in_column_resize)
3390     gtk_tree_view_button_release_column_resize (widget, (GdkEventButton *)event);
3391
3392   return TRUE;
3393 }
3394
3395 #if 0
3396 static gboolean
3397 gtk_tree_view_configure (GtkWidget *widget,
3398                          GdkEventConfigure *event)
3399 {
3400   GtkTreeView *tree_view;
3401
3402   tree_view = GTK_TREE_VIEW (widget);
3403   tree_view->priv->search_position_func (tree_view, tree_view->priv->search_window);
3404
3405   return FALSE;
3406 }
3407 #endif
3408
3409 /* GtkWidget::motion_event function set.
3410  */
3411
3412 static gboolean
3413 coords_are_over_arrow (GtkTreeView *tree_view,
3414                        GtkRBTree   *tree,
3415                        GtkRBNode   *node,
3416                        /* these are in bin window coords */
3417                        gint         x,
3418                        gint         y)
3419 {
3420   GdkRectangle arrow;
3421   gint x2;
3422
3423   if (!gtk_widget_get_realized (GTK_WIDGET (tree_view)))
3424     return FALSE;
3425
3426   if ((node->flags & GTK_RBNODE_IS_PARENT) == 0)
3427     return FALSE;
3428
3429   arrow.y = gtk_tree_view_get_row_y_offset (tree_view, tree, node);
3430   arrow.height = gtk_tree_view_get_row_height (tree_view, node);
3431
3432   gtk_tree_view_get_arrow_xrange (tree_view, tree, &arrow.x, &x2);
3433
3434   arrow.width = x2 - arrow.x;
3435
3436   return (x >= arrow.x &&
3437           x < (arrow.x + arrow.width) &&
3438           y >= arrow.y &&
3439           y < (arrow.y + arrow.height));
3440 }
3441
3442 static gboolean
3443 auto_expand_timeout (gpointer data)
3444 {
3445   GtkTreeView *tree_view = GTK_TREE_VIEW (data);
3446   GtkTreePath *path;
3447
3448   if (tree_view->priv->prelight_node)
3449     {
3450       path = _gtk_tree_view_find_path (tree_view,
3451                                        tree_view->priv->prelight_tree,
3452                                        tree_view->priv->prelight_node);   
3453
3454       if (tree_view->priv->prelight_node->children)
3455         gtk_tree_view_collapse_row (tree_view, path);
3456       else
3457         gtk_tree_view_expand_row (tree_view, path, FALSE);
3458
3459       gtk_tree_path_free (path);
3460     }
3461
3462   tree_view->priv->auto_expand_timeout = 0;
3463
3464   return FALSE;
3465 }
3466
3467 static void
3468 remove_auto_expand_timeout (GtkTreeView *tree_view)
3469 {
3470   if (tree_view->priv->auto_expand_timeout != 0)
3471     {
3472       g_source_remove (tree_view->priv->auto_expand_timeout);
3473       tree_view->priv->auto_expand_timeout = 0;
3474     }
3475 }
3476
3477 static void
3478 do_prelight (GtkTreeView *tree_view,
3479              GtkRBTree   *tree,
3480              GtkRBNode   *node,
3481              /* these are in bin_window coords */
3482              gint         x,
3483              gint         y)
3484 {
3485   if (tree_view->priv->prelight_tree == tree &&
3486       tree_view->priv->prelight_node == node)
3487     {
3488       /*  We are still on the same node,
3489           but we might need to take care of the arrow  */
3490
3491       if (tree && node && gtk_tree_view_draw_expanders (tree_view))
3492         {
3493           gboolean over_arrow;
3494
3495           over_arrow = coords_are_over_arrow (tree_view, tree, node, x, y);
3496
3497           if (over_arrow != tree_view->priv->arrow_prelit)
3498             {
3499               if (over_arrow)
3500                 tree_view->priv->arrow_prelit = TRUE;
3501               else
3502                 tree_view->priv->arrow_prelit = FALSE;
3503
3504               gtk_tree_view_queue_draw_arrow (tree_view, tree, node);
3505             }
3506         }
3507
3508       return;
3509     }
3510
3511   if (tree_view->priv->prelight_tree && tree_view->priv->prelight_node)
3512     {
3513       /*  Unprelight the old node and arrow  */
3514
3515       GTK_RBNODE_UNSET_FLAG (tree_view->priv->prelight_node,
3516                              GTK_RBNODE_IS_PRELIT);
3517
3518       if (tree_view->priv->arrow_prelit
3519           && gtk_tree_view_draw_expanders (tree_view))
3520         {
3521           tree_view->priv->arrow_prelit = FALSE;
3522           
3523           gtk_tree_view_queue_draw_arrow (tree_view,
3524                                           tree_view->priv->prelight_tree,
3525                                           tree_view->priv->prelight_node);
3526         }
3527
3528       _gtk_tree_view_queue_draw_node (tree_view,
3529                                       tree_view->priv->prelight_tree,
3530                                       tree_view->priv->prelight_node,
3531                                       NULL);
3532     }
3533
3534
3535   if (tree_view->priv->hover_expand)
3536     remove_auto_expand_timeout (tree_view);
3537
3538   /*  Set the new prelight values  */
3539   tree_view->priv->prelight_node = node;
3540   tree_view->priv->prelight_tree = tree;
3541
3542   if (!node || !tree)
3543     return;
3544
3545   /*  Prelight the new node and arrow  */
3546
3547   if (gtk_tree_view_draw_expanders (tree_view)
3548       && coords_are_over_arrow (tree_view, tree, node, x, y))
3549     {
3550       tree_view->priv->arrow_prelit = TRUE;
3551
3552       gtk_tree_view_queue_draw_arrow (tree_view, tree, node);
3553     }
3554
3555   GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_PRELIT);
3556
3557   _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
3558
3559   if (tree_view->priv->hover_expand)
3560     {
3561       tree_view->priv->auto_expand_timeout = 
3562         gdk_threads_add_timeout (AUTO_EXPAND_TIMEOUT, auto_expand_timeout, tree_view);
3563     }
3564 }
3565
3566 static void
3567 prelight_or_select (GtkTreeView *tree_view,
3568                     GtkRBTree   *tree,
3569                     GtkRBNode   *node,
3570                     /* these are in bin_window coords */
3571                     gint         x,
3572                     gint         y)
3573 {
3574   GtkSelectionMode mode = gtk_tree_selection_get_mode (tree_view->priv->selection);
3575   
3576   if (tree_view->priv->hover_selection &&
3577       (mode == GTK_SELECTION_SINGLE || mode == GTK_SELECTION_BROWSE) &&
3578       !(tree_view->priv->edited_column &&
3579         gtk_cell_area_get_edit_widget 
3580         (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (tree_view->priv->edited_column)))))
3581     {
3582       if (node)
3583         {
3584           if (!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
3585             {
3586               GtkTreePath *path;
3587               
3588               path = _gtk_tree_view_find_path (tree_view, tree, node);
3589               gtk_tree_selection_select_path (tree_view->priv->selection, path);
3590               if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
3591                 {
3592                   tree_view->priv->draw_keyfocus = FALSE;
3593                   gtk_tree_view_real_set_cursor (tree_view, path, FALSE, FALSE);
3594                 }
3595               gtk_tree_path_free (path);
3596             }
3597         }
3598
3599       else if (mode == GTK_SELECTION_SINGLE)
3600         gtk_tree_selection_unselect_all (tree_view->priv->selection);
3601     }
3602
3603     do_prelight (tree_view, tree, node, x, y);
3604 }
3605
3606 static void
3607 ensure_unprelighted (GtkTreeView *tree_view)
3608 {
3609   do_prelight (tree_view,
3610                NULL, NULL,
3611                -1000, -1000); /* coords not possibly over an arrow */
3612
3613   g_assert (tree_view->priv->prelight_node == NULL);
3614 }
3615
3616 static void
3617 update_prelight (GtkTreeView *tree_view,
3618                  gint         x,
3619                  gint         y)
3620 {
3621   int new_y;
3622   GtkRBTree *tree;
3623   GtkRBNode *node;
3624
3625   if (tree_view->priv->tree == NULL)
3626     return;
3627
3628   if (x == -10000)
3629     {
3630       ensure_unprelighted (tree_view);
3631       return;
3632     }
3633
3634   new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y);
3635   if (new_y < 0)
3636     new_y = 0;
3637
3638   _gtk_rbtree_find_offset (tree_view->priv->tree,
3639                            new_y, &tree, &node);
3640
3641   if (node)
3642     prelight_or_select (tree_view, tree, node, x, y);
3643 }
3644
3645
3646
3647
3648 /* Our motion arrow is either a box (in the case of the original spot)
3649  * or an arrow.  It is expander_size wide.
3650  */
3651 /*
3652  * 11111111111111
3653  * 01111111111110
3654  * 00111111111100
3655  * 00011111111000
3656  * 00001111110000
3657  * 00000111100000
3658  * 00000111100000
3659  * 00000111100000
3660  * ~ ~ ~ ~ ~ ~ ~
3661  * 00000111100000
3662  * 00000111100000
3663  * 00000111100000
3664  * 00001111110000
3665  * 00011111111000
3666  * 00111111111100
3667  * 01111111111110
3668  * 11111111111111
3669  */
3670
3671 static void
3672 gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
3673 {
3674   GtkTreeViewColumnReorder *reorder = tree_view->priv->cur_reorder;
3675   GtkWidget *widget = GTK_WIDGET (tree_view);
3676   cairo_surface_t *mask_image;
3677   cairo_region_t *mask_region;
3678   gint x;
3679   gint y;
3680   gint width;
3681   gint height;
3682   gint arrow_type = DRAG_COLUMN_WINDOW_STATE_UNSET;
3683   GdkWindowAttr attributes;
3684   guint attributes_mask;
3685   cairo_t *cr;
3686
3687   if (!reorder ||
3688       reorder->left_column == tree_view->priv->drag_column ||
3689       reorder->right_column == tree_view->priv->drag_column)
3690     arrow_type = DRAG_COLUMN_WINDOW_STATE_ORIGINAL;
3691   else if (reorder->left_column || reorder->right_column)
3692     {
3693       GtkAllocation left_allocation, right_allocation;
3694       GdkRectangle visible_rect;
3695       GtkWidget *button;
3696
3697       gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
3698       if (reorder->left_column)
3699         {
3700           button = gtk_tree_view_column_get_button (reorder->left_column);
3701           gtk_widget_get_allocation (button, &left_allocation);
3702           x = left_allocation.x + left_allocation.width;
3703         }
3704       else
3705         {
3706           button = gtk_tree_view_column_get_button (reorder->right_column);
3707           gtk_widget_get_allocation (button, &right_allocation);
3708           x = right_allocation.x;
3709         }
3710
3711       if (x < visible_rect.x)
3712         arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT;
3713       else if (x > visible_rect.x + visible_rect.width)
3714         arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT;
3715       else
3716         arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW;
3717     }
3718
3719   /* We want to draw the rectangle over the initial location. */
3720   if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
3721     {
3722       if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
3723         {
3724           GtkAllocation drag_allocation;
3725           GtkWidget    *button;
3726
3727           if (tree_view->priv->drag_highlight_window)
3728             {
3729               gdk_window_set_user_data (tree_view->priv->drag_highlight_window,
3730                                         NULL);
3731               gdk_window_destroy (tree_view->priv->drag_highlight_window);
3732             }
3733
3734           button = gtk_tree_view_column_get_button (tree_view->priv->drag_column);
3735           attributes.window_type = GDK_WINDOW_CHILD;
3736           attributes.wclass = GDK_INPUT_OUTPUT;
3737           attributes.x = tree_view->priv->drag_column_x;
3738           attributes.y = 0;
3739           gtk_widget_get_allocation (button, &drag_allocation);
3740           width = attributes.width = drag_allocation.width;
3741           height = attributes.height = drag_allocation.height;
3742           attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
3743           attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
3744           attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
3745           tree_view->priv->drag_highlight_window = gdk_window_new (tree_view->priv->header_window, &attributes, attributes_mask);
3746           gdk_window_set_user_data (tree_view->priv->drag_highlight_window, GTK_WIDGET (tree_view));
3747
3748           mask_image = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
3749           cr = cairo_create (mask_image);
3750
3751           cairo_rectangle (cr, 1, 1, width - 2, height - 2);
3752           cairo_stroke (cr);
3753           cairo_destroy (cr);
3754
3755           mask_region = gdk_cairo_region_create_from_surface (mask_image);
3756           gdk_window_shape_combine_region (tree_view->priv->drag_highlight_window,
3757                                            mask_region, 0, 0);
3758
3759           cairo_region_destroy (mask_region);
3760           cairo_surface_destroy (mask_image);
3761
3762           tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_ORIGINAL;
3763         }
3764     }
3765   else if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW)
3766     {
3767       GtkAllocation button_allocation;
3768       GtkWidget    *button;
3769
3770       width = tree_view->priv->expander_size;
3771
3772       /* Get x, y, width, height of arrow */
3773       gdk_window_get_origin (tree_view->priv->header_window, &x, &y);
3774       if (reorder->left_column)
3775         {
3776           button = gtk_tree_view_column_get_button (reorder->left_column);
3777           gtk_widget_get_allocation (button, &button_allocation);
3778           x += button_allocation.x + button_allocation.width - width/2;
3779           height = button_allocation.height;
3780         }
3781       else
3782         {
3783           button = gtk_tree_view_column_get_button (reorder->right_column);
3784           gtk_widget_get_allocation (button, &button_allocation);
3785           x += button_allocation.x - width/2;
3786           height = button_allocation.height;
3787         }
3788       y -= tree_view->priv->expander_size/2; /* The arrow takes up only half the space */
3789       height += tree_view->priv->expander_size;
3790
3791       /* Create the new window */
3792       if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW)
3793         {
3794           if (tree_view->priv->drag_highlight_window)
3795             {
3796               gdk_window_set_user_data (tree_view->priv->drag_highlight_window,
3797                                         NULL);
3798               gdk_window_destroy (tree_view->priv->drag_highlight_window);
3799             }
3800
3801           attributes.window_type = GDK_WINDOW_TEMP;
3802           attributes.wclass = GDK_INPUT_OUTPUT;
3803           attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
3804           attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
3805           attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
3806           attributes.x = x;
3807           attributes.y = y;
3808           attributes.width = width;
3809           attributes.height = height;
3810           tree_view->priv->drag_highlight_window = gdk_window_new (gtk_widget_get_root_window (widget),
3811                                                                    &attributes, attributes_mask);
3812           gdk_window_set_user_data (tree_view->priv->drag_highlight_window, GTK_WIDGET (tree_view));
3813
3814           mask_image = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
3815
3816           cr = cairo_create (mask_image);
3817           cairo_move_to (cr, 0, 0);
3818           cairo_line_to (cr, width, 0);
3819           cairo_line_to (cr, width / 2., width / 2);
3820           cairo_move_to (cr, 0, height);
3821           cairo_line_to (cr, width, height);
3822           cairo_line_to (cr, width / 2., height - width / 2.);
3823           cairo_fill (cr);
3824           cairo_destroy (cr);
3825
3826           mask_region = gdk_cairo_region_create_from_surface (mask_image);
3827           gdk_window_shape_combine_region (tree_view->priv->drag_highlight_window,
3828                                            mask_region, 0, 0);
3829
3830           cairo_region_destroy (mask_region);
3831           cairo_surface_destroy (mask_image);
3832         }
3833
3834       tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_ARROW;
3835       gdk_window_move (tree_view->priv->drag_highlight_window, x, y);
3836     }
3837   else if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT ||
3838            arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
3839     {
3840       GtkAllocation allocation;
3841       GtkWidget    *button;
3842
3843       width = tree_view->priv->expander_size;
3844
3845       /* Get x, y, width, height of arrow */
3846       width = width/2; /* remember, the arrow only takes half the available width */
3847       gdk_window_get_origin (gtk_widget_get_window (widget),
3848                              &x, &y);
3849       if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
3850         {
3851           gtk_widget_get_allocation (widget, &allocation);
3852           x += allocation.width - width;
3853         }
3854
3855       if (reorder->left_column)
3856         {
3857           button = gtk_tree_view_column_get_button (reorder->left_column);
3858           gtk_widget_get_allocation (button, &allocation);
3859           height = allocation.height;
3860         }
3861       else
3862         {
3863           button = gtk_tree_view_column_get_button (reorder->right_column);
3864           gtk_widget_get_allocation (button, &allocation);
3865           height = allocation.height;
3866         }
3867
3868       y -= tree_view->priv->expander_size;
3869       height += 2*tree_view->priv->expander_size;
3870
3871       /* Create the new window */
3872       if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT &&
3873           tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
3874         {
3875           if (tree_view->priv->drag_highlight_window)
3876             {
3877               gdk_window_set_user_data (tree_view->priv->drag_highlight_window,
3878                                         NULL);
3879               gdk_window_destroy (tree_view->priv->drag_highlight_window);
3880             }
3881
3882           attributes.window_type = GDK_WINDOW_TEMP;
3883           attributes.wclass = GDK_INPUT_OUTPUT;
3884           attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
3885           attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
3886           attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
3887           attributes.x = x;
3888           attributes.y = y;
3889           attributes.width = width;
3890           attributes.height = height;
3891           tree_view->priv->drag_highlight_window = gdk_window_new (NULL, &attributes, attributes_mask);
3892           gdk_window_set_user_data (tree_view->priv->drag_highlight_window, GTK_WIDGET (tree_view));
3893
3894           mask_image = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
3895
3896           cr = cairo_create (mask_image);
3897           /* mirror if we're on the left */
3898           if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT)
3899             {
3900               cairo_translate (cr, width, 0);
3901               cairo_scale (cr, -1, 1);
3902             }
3903           cairo_move_to (cr, 0, 0);
3904           cairo_line_to (cr, width, width);
3905           cairo_line_to (cr, 0, tree_view->priv->expander_size);
3906           cairo_move_to (cr, 0, height);
3907           cairo_line_to (cr, width, height - width);
3908           cairo_line_to (cr, 0, height - tree_view->priv->expander_size);
3909           cairo_fill (cr);
3910           cairo_destroy (cr);
3911
3912           mask_region = gdk_cairo_region_create_from_surface (mask_image);
3913           gdk_window_shape_combine_region (tree_view->priv->drag_highlight_window,
3914                                            mask_region, 0, 0);
3915
3916           cairo_region_destroy (mask_region);
3917           cairo_surface_destroy (mask_image);
3918         }
3919
3920       tree_view->priv->drag_column_window_state = arrow_type;
3921       gdk_window_move (tree_view->priv->drag_highlight_window, x, y);
3922    }
3923   else
3924     {
3925       g_warning (G_STRLOC"Invalid GtkTreeViewColumnReorder struct");
3926       gdk_window_hide (tree_view->priv->drag_highlight_window);
3927       return;
3928     }
3929
3930   gdk_window_show (tree_view->priv->drag_highlight_window);
3931   gdk_window_raise (tree_view->priv->drag_highlight_window);
3932 }
3933
3934 static gboolean
3935 gtk_tree_view_motion_resize_column (GtkWidget      *widget,
3936                                     GdkEventMotion *event)
3937 {
3938   gint x;
3939   gint new_width;
3940   GtkTreeViewColumn *column;
3941   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
3942
3943   column = gtk_tree_view_get_column (tree_view, tree_view->priv->drag_pos);
3944
3945   if (event->is_hint || event->window != gtk_widget_get_window (widget))
3946     gtk_widget_get_pointer (widget, &x, NULL);
3947   else
3948     x = event->x;
3949
3950   if (tree_view->priv->hadjustment)
3951     x += gtk_adjustment_get_value (tree_view->priv->hadjustment);
3952
3953   new_width = gtk_tree_view_new_column_width (tree_view,
3954                                               tree_view->priv->drag_pos, &x);
3955   if (x != tree_view->priv->x_drag &&
3956       (new_width != gtk_tree_view_column_get_fixed_width (column)))
3957     {
3958       _gtk_tree_view_column_set_use_resized_width (column, TRUE);
3959
3960       if (gtk_tree_view_column_get_expand (column))
3961         new_width -= tree_view->priv->last_extra_space_per_column;
3962
3963       _gtk_tree_view_column_set_resized_width (column, new_width);
3964
3965
3966       gtk_widget_queue_resize (widget);
3967     }
3968
3969   return FALSE;
3970 }
3971
3972
3973 static void
3974 gtk_tree_view_update_current_reorder (GtkTreeView *tree_view)
3975 {
3976   GtkTreeViewColumnReorder *reorder = NULL;
3977   GList *list;
3978   gint mouse_x;
3979
3980   gdk_window_get_pointer (tree_view->priv->header_window, &mouse_x, NULL, NULL);
3981   for (list = tree_view->priv->column_drag_info; list; list = list->next)
3982     {
3983       reorder = (GtkTreeViewColumnReorder *) list->data;
3984       if (mouse_x >= reorder->left_align && mouse_x < reorder->right_align)
3985         break;
3986       reorder = NULL;
3987     }
3988
3989   /*  if (reorder && reorder == tree_view->priv->cur_reorder)
3990       return;*/
3991
3992   tree_view->priv->cur_reorder = reorder;
3993   gtk_tree_view_motion_draw_column_motion_arrow (tree_view);
3994 }
3995
3996 static void
3997 gtk_tree_view_vertical_autoscroll (GtkTreeView *tree_view)
3998 {
3999   GdkRectangle visible_rect;
4000   gint y;
4001   gint offset;
4002
4003   gdk_window_get_pointer (tree_view->priv->bin_window, NULL, &y, NULL);
4004   y += tree_view->priv->dy;
4005
4006   gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
4007
4008   /* see if we are near the edge. */
4009   offset = y - (visible_rect.y + 2 * SCROLL_EDGE_SIZE);
4010   if (offset > 0)
4011     {
4012       offset = y - (visible_rect.y + visible_rect.height - 2 * SCROLL_EDGE_SIZE);
4013       if (offset < 0)
4014         return;
4015     }
4016
4017   gtk_adjustment_set_value (tree_view->priv->vadjustment,
4018                             MAX (gtk_adjustment_get_value (tree_view->priv->vadjustment) + offset, 0.0));
4019 }
4020
4021 static gboolean
4022 gtk_tree_view_horizontal_autoscroll (GtkTreeView *tree_view)
4023 {
4024   GdkRectangle visible_rect;
4025   gint x;
4026   gint offset;
4027
4028   gdk_window_get_pointer (tree_view->priv->bin_window, &x, NULL, NULL);
4029
4030   gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
4031
4032   /* See if we are near the edge. */
4033   offset = x - (visible_rect.x + SCROLL_EDGE_SIZE);
4034   if (offset > 0)
4035     {
4036       offset = x - (visible_rect.x + visible_rect.width - SCROLL_EDGE_SIZE);
4037       if (offset < 0)
4038         return TRUE;
4039     }
4040   offset = offset/3;
4041
4042   gtk_adjustment_set_value (tree_view->priv->hadjustment,
4043                             MAX (gtk_adjustment_get_value (tree_view->priv->hadjustment) + offset, 0.0));
4044
4045   return TRUE;
4046
4047 }
4048
4049 static gboolean
4050 gtk_tree_view_motion_drag_column (GtkWidget      *widget,
4051                                   GdkEventMotion *event)
4052 {
4053   GtkAllocation allocation, button_allocation;
4054   GtkTreeView *tree_view = (GtkTreeView *) widget;
4055   GtkTreeViewColumn *column = tree_view->priv->drag_column;
4056   GtkWidget *button;
4057   gint x, y;
4058
4059   /* Sanity Check */
4060   if ((column == NULL) ||
4061       (event->window != tree_view->priv->drag_window))
4062     return FALSE;
4063
4064   button = gtk_tree_view_column_get_button (column);
4065
4066   /* Handle moving the header */
4067   gdk_window_get_position (tree_view->priv->drag_window, &x, &y);
4068   gtk_widget_get_allocation (widget, &allocation);
4069   gtk_widget_get_allocation (button, &button_allocation);
4070   x = CLAMP (x + (gint)event->x - _gtk_tree_view_column_get_drag_x (column), 0,
4071              MAX (tree_view->priv->width, allocation.width) - button_allocation.width);
4072   gdk_window_move (tree_view->priv->drag_window, x, y);
4073   
4074   /* autoscroll, if needed */
4075   gtk_tree_view_horizontal_autoscroll (tree_view);
4076   /* Update the current reorder position and arrow; */
4077   gtk_tree_view_update_current_reorder (tree_view);
4078
4079   return TRUE;
4080 }
4081
4082 static void
4083 gtk_tree_view_stop_rubber_band (GtkTreeView *tree_view)
4084 {
4085   remove_scroll_timeout (tree_view);
4086   gtk_grab_remove (GTK_WIDGET (tree_view));
4087
4088   if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
4089     {
4090       GtkTreePath *tmp_path;
4091
4092       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
4093
4094       /* The anchor path should be set to the start path */
4095       tmp_path = _gtk_tree_view_find_path (tree_view,
4096                                            tree_view->priv->rubber_band_start_tree,
4097                                            tree_view->priv->rubber_band_start_node);
4098
4099       if (tree_view->priv->anchor)
4100         gtk_tree_row_reference_free (tree_view->priv->anchor);
4101
4102       tree_view->priv->anchor =
4103         gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
4104                                           tree_view->priv->model,
4105                                           tmp_path);
4106
4107       gtk_tree_path_free (tmp_path);
4108
4109       /* ... and the cursor to the end path */
4110       tmp_path = _gtk_tree_view_find_path (tree_view,
4111                                            tree_view->priv->rubber_band_end_tree,
4112                                            tree_view->priv->rubber_band_end_node);
4113       gtk_tree_view_real_set_cursor (GTK_TREE_VIEW (tree_view), tmp_path, FALSE, FALSE);
4114       gtk_tree_path_free (tmp_path);
4115
4116       _gtk_tree_selection_emit_changed (tree_view->priv->selection);
4117     }
4118
4119   /* Clear status variables */
4120   tree_view->priv->rubber_band_status = RUBBER_BAND_OFF;
4121   tree_view->priv->rubber_band_shift = 0;
4122   tree_view->priv->rubber_band_ctrl = 0;
4123
4124   tree_view->priv->rubber_band_start_node = NULL;
4125   tree_view->priv->rubber_band_start_tree = NULL;
4126   tree_view->priv->rubber_band_end_node = NULL;
4127   tree_view->priv->rubber_band_end_tree = NULL;
4128 }
4129
4130 static void
4131 gtk_tree_view_update_rubber_band_selection_range (GtkTreeView *tree_view,
4132                                                  GtkRBTree   *start_tree,
4133                                                  GtkRBNode   *start_node,
4134                                                  GtkRBTree   *end_tree,
4135                                                  GtkRBNode   *end_node,
4136                                                  gboolean     select,
4137                                                  gboolean     skip_start,
4138                                                  gboolean     skip_end)
4139 {
4140   if (start_node == end_node)
4141     return;
4142
4143   /* We skip the first node and jump inside the loop */
4144   if (skip_start)
4145     goto skip_first;
4146
4147   do
4148     {
4149       /* Small optimization by assuming insensitive nodes are never
4150        * selected.
4151        */
4152       if (!GTK_RBNODE_FLAG_SET (start_node, GTK_RBNODE_IS_SELECTED))
4153         {
4154           GtkTreePath *path;
4155           gboolean selectable;
4156
4157           path = _gtk_tree_view_find_path (tree_view, start_tree, start_node);
4158           selectable = _gtk_tree_selection_row_is_selectable (tree_view->priv->selection, start_node, path);
4159           gtk_tree_path_free (path);
4160
4161           if (!selectable)
4162             goto node_not_selectable;
4163         }
4164
4165       if (select)
4166         {
4167           if (tree_view->priv->rubber_band_shift)
4168             GTK_RBNODE_SET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
4169           else if (tree_view->priv->rubber_band_ctrl)
4170             {
4171               /* Toggle the selection state */
4172               if (GTK_RBNODE_FLAG_SET (start_node, GTK_RBNODE_IS_SELECTED))
4173                 GTK_RBNODE_UNSET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
4174               else
4175                 GTK_RBNODE_SET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
4176             }
4177           else
4178             GTK_RBNODE_SET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
4179         }
4180       else
4181         {
4182           /* Mirror the above */
4183           if (tree_view->priv->rubber_band_shift)
4184             GTK_RBNODE_UNSET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
4185           else if (tree_view->priv->rubber_band_ctrl)
4186             {
4187               /* Toggle the selection state */
4188               if (GTK_RBNODE_FLAG_SET (start_node, GTK_RBNODE_IS_SELECTED))
4189                 GTK_RBNODE_UNSET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
4190               else
4191                 GTK_RBNODE_SET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
4192             }
4193           else
4194             GTK_RBNODE_UNSET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
4195         }
4196
4197       _gtk_tree_view_queue_draw_node (tree_view, start_tree, start_node, NULL);
4198
4199 node_not_selectable:
4200       if (start_node == end_node)
4201         break;
4202
4203 skip_first:
4204
4205       if (start_node->children)
4206         {
4207           start_tree = start_node->children;
4208           start_node = start_tree->root;
4209           while (start_node->left != start_tree->nil)
4210             start_node = start_node->left;
4211         }
4212       else
4213         {
4214           _gtk_rbtree_next_full (start_tree, start_node, &start_tree, &start_node);
4215
4216           if (!start_tree)
4217             /* Ran out of tree */
4218             break;
4219         }
4220
4221       if (skip_end && start_node == end_node)
4222         break;
4223     }
4224   while (TRUE);
4225 }
4226
4227 static void
4228 gtk_tree_view_update_rubber_band_selection (GtkTreeView *tree_view)
4229 {
4230   GtkRBTree *start_tree, *end_tree;
4231   GtkRBNode *start_node, *end_node;
4232
4233   _gtk_rbtree_find_offset (tree_view->priv->tree, MIN (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y), &start_tree, &start_node);
4234   _gtk_rbtree_find_offset (tree_view->priv->tree, MAX (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y), &end_tree, &end_node);
4235
4236   /* Handle the start area first */
4237   if (!tree_view->priv->rubber_band_start_node)
4238     {
4239       gtk_tree_view_update_rubber_band_selection_range (tree_view,
4240                                                        start_tree,
4241                                                        start_node,
4242                                                        end_tree,
4243                                                        end_node,
4244                                                        TRUE,
4245                                                        FALSE,
4246                                                        FALSE);
4247     }
4248   else if (_gtk_rbtree_node_find_offset (start_tree, start_node) <
4249            _gtk_rbtree_node_find_offset (tree_view->priv->rubber_band_start_tree, tree_view->priv->rubber_band_start_node))
4250     {
4251       /* New node is above the old one; selection became bigger */
4252       gtk_tree_view_update_rubber_band_selection_range (tree_view,
4253                                                        start_tree,
4254                                                        start_node,
4255                                                        tree_view->priv->rubber_band_start_tree,
4256                                                        tree_view->priv->rubber_band_start_node,
4257                                                        TRUE,
4258                                                        FALSE,
4259                                                        TRUE);
4260     }
4261   else if (_gtk_rbtree_node_find_offset (start_tree, start_node) >
4262            _gtk_rbtree_node_find_offset (tree_view->priv->rubber_band_start_tree, tree_view->priv->rubber_band_start_node))
4263     {
4264       /* New node is below the old one; selection became smaller */
4265       gtk_tree_view_update_rubber_band_selection_range (tree_view,
4266                                                        tree_view->priv->rubber_band_start_tree,
4267                                                        tree_view->priv->rubber_band_start_node,
4268                                                        start_tree,
4269                                                        start_node,
4270                                                        FALSE,
4271                                                        FALSE,
4272                                                        TRUE);
4273     }
4274
4275   tree_view->priv->rubber_band_start_tree = start_tree;
4276   tree_view->priv->rubber_band_start_node = start_node;
4277
4278   /* Next, handle the end area */
4279   if (!tree_view->priv->rubber_band_end_node)
4280     {
4281       /* In the event this happens, start_node was also NULL; this case is
4282        * handled above.
4283        */
4284     }
4285   else if (!end_node)
4286     {
4287       /* Find the last node in the tree */
4288       _gtk_rbtree_find_offset (tree_view->priv->tree, tree_view->priv->height - 1,
4289                                &end_tree, &end_node);
4290
4291       /* Selection reached end of the tree */
4292       gtk_tree_view_update_rubber_band_selection_range (tree_view,
4293                                                        tree_view->priv->rubber_band_end_tree,
4294                                                        tree_view->priv->rubber_band_end_node,
4295                                                        end_tree,
4296                                                        end_node,
4297                                                        TRUE,
4298                                                        TRUE,
4299                                                        FALSE);
4300     }
4301   else if (_gtk_rbtree_node_find_offset (end_tree, end_node) >
4302            _gtk_rbtree_node_find_offset (tree_view->priv->rubber_band_end_tree, tree_view->priv->rubber_band_end_node))
4303     {
4304       /* New node is below the old one; selection became bigger */
4305       gtk_tree_view_update_rubber_band_selection_range (tree_view,
4306                                                        tree_view->priv->rubber_band_end_tree,
4307                                                        tree_view->priv->rubber_band_end_node,
4308                                                        end_tree,
4309                                                        end_node,
4310                                                        TRUE,
4311                                                        TRUE,
4312                                                        FALSE);
4313     }
4314   else if (_gtk_rbtree_node_find_offset (end_tree, end_node) <
4315            _gtk_rbtree_node_find_offset (tree_view->priv->rubber_band_end_tree, tree_view->priv->rubber_band_end_node))
4316     {
4317       /* New node is above the old one; selection became smaller */
4318       gtk_tree_view_update_rubber_band_selection_range (tree_view,
4319                                                        end_tree,
4320                                                        end_node,
4321                                                        tree_view->priv->rubber_band_end_tree,
4322                                                        tree_view->priv->rubber_band_end_node,
4323                                                        FALSE,
4324                                                        TRUE,
4325                                                        FALSE);
4326     }
4327
4328   tree_view->priv->rubber_band_end_tree = end_tree;
4329   tree_view->priv->rubber_band_end_node = end_node;
4330 }
4331
4332 static void
4333 gtk_tree_view_update_rubber_band (GtkTreeView *tree_view)
4334 {
4335   gint x, y;
4336   GdkRectangle old_area;
4337   GdkRectangle new_area;
4338   GdkRectangle common;
4339   cairo_region_t *invalid_region;
4340
4341   old_area.x = MIN (tree_view->priv->press_start_x, tree_view->priv->rubber_band_x);
4342   old_area.y = MIN (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y) - tree_view->priv->dy;
4343   old_area.width = ABS (tree_view->priv->rubber_band_x - tree_view->priv->press_start_x) + 1;
4344   old_area.height = ABS (tree_view->priv->rubber_band_y - tree_view->priv->press_start_y) + 1;
4345
4346   gdk_window_get_pointer (tree_view->priv->bin_window, &x, &y, NULL);
4347
4348   x = MAX (x, 0);
4349   y = MAX (y, 0) + tree_view->priv->dy;
4350
4351   new_area.x = MIN (tree_view->priv->press_start_x, x);
4352   new_area.y = MIN (tree_view->priv->press_start_y, y) - tree_view->priv->dy;
4353   new_area.width = ABS (x - tree_view->priv->press_start_x) + 1;
4354   new_area.height = ABS (y - tree_view->priv->press_start_y) + 1;
4355
4356   invalid_region = cairo_region_create_rectangle (&old_area);
4357   cairo_region_union_rectangle (invalid_region, &new_area);
4358
4359   gdk_rectangle_intersect (&old_area, &new_area, &common);
4360   if (common.width > 2 && common.height > 2)
4361     {
4362       cairo_region_t *common_region;
4363
4364       /* make sure the border is invalidated */
4365       common.x += 1;
4366       common.y += 1;
4367       common.width -= 2;
4368       common.height -= 2;
4369
4370       common_region = cairo_region_create_rectangle (&common);
4371
4372       cairo_region_subtract (invalid_region, common_region);
4373       cairo_region_destroy (common_region);
4374     }
4375
4376   gdk_window_invalidate_region (tree_view->priv->bin_window, invalid_region, TRUE);
4377
4378   cairo_region_destroy (invalid_region);
4379
4380   tree_view->priv->rubber_band_x = x;
4381   tree_view->priv->rubber_band_y = y;
4382
4383   gtk_tree_view_update_rubber_band_selection (tree_view);
4384 }
4385
4386 static void
4387 gtk_tree_view_paint_rubber_band (GtkTreeView  *tree_view,
4388                                  cairo_t      *cr)
4389 {
4390   GdkRectangle rect;
4391   GtkStyleContext *context;
4392
4393   cairo_save (cr);
4394
4395   context = gtk_widget_get_style_context (GTK_WIDGET (tree_view));
4396
4397   gtk_style_context_save (context);
4398   gtk_style_context_add_class (context, GTK_STYLE_CLASS_RUBBERBAND);
4399
4400   rect.x = MIN (tree_view->priv->press_start_x, tree_view->priv->rubber_band_x);
4401   rect.y = MIN (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y) - tree_view->priv->dy;
4402   rect.width = ABS (tree_view->priv->press_start_x - tree_view->priv->rubber_band_x) + 1;
4403   rect.height = ABS (tree_view->priv->press_start_y - tree_view->priv->rubber_band_y) + 1;
4404
4405   gdk_cairo_rectangle (cr, &rect);
4406   cairo_clip (cr);
4407
4408   gtk_render_background (context, cr,
4409                          rect.x, rect.y,
4410                          rect.width, rect.height);
4411   gtk_render_frame (context, cr,
4412                     rect.x, rect.y,
4413                     rect.width, rect.height);
4414
4415   gtk_style_context_restore (context);
4416   cairo_restore (cr);
4417 }
4418
4419 static gboolean
4420 gtk_tree_view_motion_bin_window (GtkWidget      *widget,
4421                                  GdkEventMotion *event)
4422 {
4423   GtkTreeView *tree_view;
4424   GtkRBTree *tree;
4425   GtkRBNode *node;
4426   gint new_y;
4427
4428   tree_view = (GtkTreeView *) widget;
4429
4430   if (tree_view->priv->tree == NULL)
4431     return FALSE;
4432
4433   if (tree_view->priv->rubber_band_status == RUBBER_BAND_MAYBE_START)
4434     {
4435       gtk_grab_add (GTK_WIDGET (tree_view));
4436       gtk_tree_view_update_rubber_band (tree_view);
4437
4438       tree_view->priv->rubber_band_status = RUBBER_BAND_ACTIVE;
4439     }
4440   else if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
4441     {
4442       gtk_tree_view_update_rubber_band (tree_view);
4443
4444       add_scroll_timeout (tree_view);
4445     }
4446
4447   /* only check for an initiated drag when a button is pressed */
4448   if (tree_view->priv->pressed_button >= 0
4449       && !tree_view->priv->rubber_band_status)
4450     gtk_tree_view_maybe_begin_dragging_row (tree_view, event);
4451
4452   new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
4453   if (new_y < 0)
4454     new_y = 0;
4455
4456   _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
4457
4458   /* If we are currently pressing down a button, we don't want to prelight anything else. */
4459   if ((tree_view->priv->button_pressed_node != NULL) &&
4460       (tree_view->priv->button_pressed_node != node))
4461     node = NULL;
4462
4463   tree_view->priv->event_last_x = event->x;
4464   tree_view->priv->event_last_y = event->y;
4465
4466   prelight_or_select (tree_view, tree, node, event->x, event->y);
4467
4468   return TRUE;
4469 }
4470
4471 static gboolean
4472 gtk_tree_view_motion (GtkWidget      *widget,
4473                       GdkEventMotion *event)
4474 {
4475   GtkTreeView *tree_view;
4476
4477   tree_view = (GtkTreeView *) widget;
4478
4479   /* Resizing a column */
4480   if (tree_view->priv->in_column_resize)
4481     return gtk_tree_view_motion_resize_column (widget, event);
4482
4483   /* Drag column */
4484   if (tree_view->priv->in_column_drag)
4485     return gtk_tree_view_motion_drag_column (widget, event);
4486
4487   /* Sanity check it */
4488   if (event->window == tree_view->priv->bin_window)
4489     return gtk_tree_view_motion_bin_window (widget, event);
4490
4491   return FALSE;
4492 }
4493
4494 /* Invalidate the focus rectangle near the edge of the bin_window; used when
4495  * the tree is empty.
4496  */
4497 static void
4498 invalidate_empty_focus (GtkTreeView *tree_view)
4499 {
4500   GdkRectangle area;
4501
4502   if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
4503     return;
4504
4505   area.x = 0;
4506   area.y = 0;
4507   area.width = gdk_window_get_width (tree_view->priv->bin_window);
4508   area.height = gdk_window_get_height (tree_view->priv->bin_window);
4509   gdk_window_invalidate_rect (tree_view->priv->bin_window, &area, FALSE);
4510 }
4511
4512 /* Draws a focus rectangle near the edge of the bin_window; used when the tree
4513  * is empty.
4514  */
4515 static void
4516 draw_empty_focus (GtkTreeView *tree_view, cairo_t *cr)
4517 {
4518   GtkWidget *widget = GTK_WIDGET (tree_view);
4519   gint w, h;
4520
4521   if (!gtk_widget_has_visible_focus (widget))
4522     return;
4523
4524   w = gdk_window_get_width (tree_view->priv->bin_window) - 2;
4525   h = gdk_window_get_height (tree_view->priv->bin_window) - 2;
4526
4527   if (w > 0 && h > 0)
4528     {
4529       GtkStyleContext *context;
4530       GtkStateFlags state;
4531
4532       context = gtk_widget_get_style_context (widget);
4533       state = gtk_widget_get_state_flags (widget);
4534
4535       gtk_style_context_save (context);
4536       gtk_style_context_set_state (context, state);
4537
4538       gtk_render_focus (context, cr, 1, 1, w, h);
4539
4540       gtk_style_context_restore (context);
4541     }
4542 }
4543
4544 typedef enum {
4545   GTK_TREE_VIEW_GRID_LINE,
4546   GTK_TREE_VIEW_TREE_LINE,
4547   GTK_TREE_VIEW_FOREGROUND_LINE
4548 } GtkTreeViewLineType;
4549
4550 static void
4551 gtk_tree_view_draw_line (GtkTreeView         *tree_view,
4552                          cairo_t             *cr,
4553                          GtkTreeViewLineType  type,
4554                          int                  x1,
4555                          int                  y1,
4556                          int                  x2,
4557                          int                  y2)
4558 {
4559   cairo_save (cr);
4560
4561   switch (type)
4562     {
4563     case GTK_TREE_VIEW_TREE_LINE:
4564       cairo_set_source_rgb (cr, 0, 0, 0);
4565       cairo_set_line_width (cr, tree_view->priv->tree_line_width);
4566       if (tree_view->priv->tree_line_dashes[0])
4567         cairo_set_dash (cr, 
4568                         tree_view->priv->tree_line_dashes,
4569                         2, 0.5);
4570       break;
4571     case GTK_TREE_VIEW_GRID_LINE:
4572       cairo_set_source_rgb (cr, 0, 0, 0);
4573       cairo_set_line_width (cr, tree_view->priv->grid_line_width);
4574       if (tree_view->priv->grid_line_dashes[0])
4575         cairo_set_dash (cr, 
4576                         tree_view->priv->grid_line_dashes,
4577                         2, 0.5);
4578       break;
4579     default:
4580       g_assert_not_reached ();
4581       /* fall through */
4582     case GTK_TREE_VIEW_FOREGROUND_LINE:
4583       {
4584         GtkStyleContext *context;
4585         GtkStateFlags state;
4586         GdkRGBA color;
4587
4588         context = gtk_widget_get_style_context (GTK_WIDGET (tree_view));
4589         state = gtk_widget_get_state_flags (GTK_WIDGET (tree_view));
4590
4591         cairo_set_line_width (cr, 1.0);
4592         gtk_style_context_get_color (context, state, &color);
4593         gdk_cairo_set_source_rgba (cr, &color);
4594       }
4595
4596       break;
4597     }
4598
4599   cairo_move_to (cr, x1 + 0.5, y1 + 0.5);
4600   cairo_line_to (cr, x2 + 0.5, y2 + 0.5);
4601   cairo_stroke (cr);
4602
4603   cairo_restore (cr);
4604 }
4605                          
4606 static void
4607 gtk_tree_view_draw_grid_lines (GtkTreeView    *tree_view,
4608                                cairo_t        *cr,
4609                                gint            n_visible_columns)
4610 {
4611   GList *list = tree_view->priv->columns;
4612   gint i = 0;
4613   gint current_x = 0;
4614
4615   if (tree_view->priv->grid_lines != GTK_TREE_VIEW_GRID_LINES_VERTICAL
4616       && tree_view->priv->grid_lines != GTK_TREE_VIEW_GRID_LINES_BOTH)
4617     return;
4618
4619   /* Only draw the lines for visible rows and columns */
4620   for (list = tree_view->priv->columns; list; list = list->next, i++)
4621     {
4622       GtkTreeViewColumn *column = list->data;
4623
4624       /* We don't want a line for the last column */
4625       if (i == n_visible_columns - 1)
4626         break;
4627
4628       if (!gtk_tree_view_column_get_visible (column))
4629         continue;
4630
4631       current_x += gtk_tree_view_column_get_width (column);
4632
4633       gtk_tree_view_draw_line (tree_view, cr,
4634                                GTK_TREE_VIEW_GRID_LINE,
4635                                current_x - 1, 0,
4636                                current_x - 1, tree_view->priv->height);
4637     }
4638 }
4639
4640 /* Warning: Very scary function.
4641  * Modify at your own risk
4642  *
4643  * KEEP IN SYNC WITH gtk_tree_view_create_row_drag_icon()!
4644  * FIXME: It's not...
4645  */
4646 static gboolean
4647 gtk_tree_view_bin_draw (GtkWidget      *widget,
4648                         cairo_t        *cr)
4649 {
4650   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
4651   GtkTreePath *path;
4652   GtkRBTree *tree;
4653   GList *list;
4654   GtkRBNode *node;
4655   GtkRBNode *cursor = NULL;
4656   GtkRBTree *cursor_tree = NULL;
4657   GtkRBNode *drag_highlight = NULL;
4658   GtkRBTree *drag_highlight_tree = NULL;
4659   GtkTreeIter iter;
4660   gint new_y;
4661   gint y_offset, cell_offset;
4662   gint max_height;
4663   gint depth;
4664   GdkRectangle background_area;
4665   GdkRectangle cell_area;
4666   GdkRectangle clip;
4667   guint flags;
4668   gint highlight_x;
4669   gint expander_cell_width;
4670   gint bin_window_width;
4671   gint bin_window_height;
4672   GtkTreePath *cursor_path;
4673   GtkTreePath *drag_dest_path;
4674   GList *first_column, *last_column;
4675   gint vertical_separator;
4676   gint horizontal_separator;
4677   gint focus_line_width;
4678   gboolean allow_rules;
4679   gboolean has_can_focus_cell;
4680   gboolean rtl;
4681   gint n_visible_columns;
4682   gint pointer_x, pointer_y;
4683   gint grid_line_width;
4684   gboolean got_pointer = FALSE;
4685   gboolean draw_vgrid_lines, draw_hgrid_lines;
4686   GtkStyleContext *context;
4687   GtkStateFlags state;
4688
4689   rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
4690   context = gtk_widget_get_style_context (widget);
4691   state = gtk_widget_get_state_flags (widget);
4692
4693   gtk_widget_style_get (widget,
4694                         "horizontal-separator", &horizontal_separator,
4695                         "vertical-separator", &vertical_separator,
4696                         "allow-rules", &allow_rules,
4697                         "focus-line-width", &focus_line_width,
4698                         NULL);
4699
4700   if (tree_view->priv->tree == NULL)
4701     {
4702       draw_empty_focus (tree_view, cr);
4703       return TRUE;
4704     }
4705
4706   bin_window_width = gdk_window_get_width (tree_view->priv->bin_window);
4707   bin_window_height = gdk_window_get_height (tree_view->priv->bin_window);
4708   cairo_rectangle (cr, 0, 0, bin_window_width, bin_window_height);
4709   cairo_clip (cr);
4710   if (!gdk_cairo_get_clip_rectangle (cr, &clip))
4711     return TRUE;
4712
4713   new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, clip.y);
4714
4715   if (new_y < 0)
4716     new_y = 0;
4717   y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
4718
4719   if (tree_view->priv->height < bin_window_height)
4720     {
4721       gtk_style_context_save (context);
4722       gtk_style_context_set_state (context, state);
4723       gtk_style_context_add_class (context, GTK_STYLE_CLASS_CELL);
4724
4725       gtk_render_background (context, cr,
4726                              0, tree_view->priv->height,
4727                              bin_window_width,
4728                              bin_window_height - tree_view->priv->height);
4729
4730       gtk_style_context_restore (context);
4731     }
4732
4733   if (node == NULL)
4734     return TRUE;
4735
4736   /* find the path for the node */
4737   path = _gtk_tree_view_find_path ((GtkTreeView *)widget,
4738                                    tree,
4739                                    node);
4740   gtk_tree_model_get_iter (tree_view->priv->model,
4741                            &iter,
4742                            path);
4743   depth = gtk_tree_path_get_depth (path);
4744   gtk_tree_path_free (path);
4745   
4746   cursor_path = NULL;
4747   drag_dest_path = NULL;
4748
4749   if (tree_view->priv->cursor)
4750     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
4751
4752   if (cursor_path)
4753     _gtk_tree_view_find_node (tree_view, cursor_path,
4754                               &cursor_tree, &cursor);
4755
4756   if (tree_view->priv->drag_dest_row)
4757     drag_dest_path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
4758
4759   if (drag_dest_path)
4760     _gtk_tree_view_find_node (tree_view, drag_dest_path,
4761                               &drag_highlight_tree, &drag_highlight);
4762
4763   draw_vgrid_lines =
4764     tree_view->priv->grid_lines == GTK_TREE_VIEW_GRID_LINES_VERTICAL
4765     || tree_view->priv->grid_lines == GTK_TREE_VIEW_GRID_LINES_BOTH;
4766   draw_hgrid_lines =
4767     tree_view->priv->grid_lines == GTK_TREE_VIEW_GRID_LINES_HORIZONTAL
4768     || tree_view->priv->grid_lines == GTK_TREE_VIEW_GRID_LINES_BOTH;
4769
4770   if (draw_vgrid_lines || draw_hgrid_lines)
4771     gtk_widget_style_get (widget, "grid-line-width", &grid_line_width, NULL);
4772   
4773   n_visible_columns = 0;
4774   for (list = tree_view->priv->columns; list; list = list->next)
4775     {
4776       if (!gtk_tree_view_column_get_visible (GTK_TREE_VIEW_COLUMN (list->data)))
4777         continue;
4778       n_visible_columns ++;
4779     }
4780
4781   /* Find the last column */
4782   for (last_column = g_list_last (tree_view->priv->columns);
4783        last_column &&
4784        !(gtk_tree_view_column_get_visible (GTK_TREE_VIEW_COLUMN (last_column->data)));
4785        last_column = last_column->prev)
4786     ;
4787
4788   /* and the first */
4789   for (first_column = g_list_first (tree_view->priv->columns);
4790        first_column &&
4791        !(gtk_tree_view_column_get_visible (GTK_TREE_VIEW_COLUMN (first_column->data)));
4792        first_column = first_column->next)
4793     ;
4794
4795   /* Actually process the expose event.  To do this, we want to
4796    * start at the first node of the event, and walk the tree in
4797    * order, drawing each successive node.
4798    */
4799
4800   do
4801     {
4802       gboolean parity;
4803       gboolean is_separator = FALSE;
4804       gboolean is_first = FALSE;
4805       gboolean is_last = FALSE;
4806       gint n_col = 0;
4807
4808       is_separator = row_is_separator (tree_view, &iter, NULL);
4809
4810       max_height = gtk_tree_view_get_row_height (tree_view, node);
4811
4812       cell_offset = 0;
4813       highlight_x = 0; /* should match x coord of first cell */
4814       expander_cell_width = 0;
4815
4816       background_area.y = y_offset + clip.y;
4817       background_area.height = max_height;
4818
4819       flags = 0;
4820
4821       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PRELIT))
4822         flags |= GTK_CELL_RENDERER_PRELIT;
4823
4824       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
4825         flags |= GTK_CELL_RENDERER_SELECTED;
4826
4827       parity = _gtk_rbtree_node_find_parity (tree, node);
4828
4829       /* we *need* to set cell data on all cells before the call
4830        * to _has_can_focus_cell, else _has_can_focus_cell() does not
4831        * return a correct value.
4832        */
4833       for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
4834            list;
4835            list = (rtl ? list->prev : list->next))
4836         {
4837           GtkTreeViewColumn *column = list->data;
4838           gtk_tree_view_column_cell_set_cell_data (column,
4839                                                    tree_view->priv->model,
4840                                                    &iter,
4841                                                    GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
4842                                                    node->children?TRUE:FALSE);
4843         }
4844
4845       has_can_focus_cell = gtk_tree_view_has_can_focus_cell (tree_view);
4846
4847       for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
4848            list;
4849            list = (rtl ? list->prev : list->next))
4850         {
4851           GtkTreeViewColumn *column = list->data;
4852           GtkRegionFlags row_flags = 0, column_flags = 0;
4853           GtkStateFlags state = 0;
4854           gint width;
4855           gboolean draw_focus;
4856
4857           if (!gtk_tree_view_column_get_visible (column))
4858             continue;
4859
4860           n_col++;
4861           width = gtk_tree_view_column_get_width (column);
4862
4863           if (cell_offset > clip.x + clip.width ||
4864               cell_offset + width < clip.x)
4865             {
4866               cell_offset += width;
4867               continue;
4868             }
4869
4870           if (gtk_tree_view_column_get_sort_indicator (column))
4871             flags |= GTK_CELL_RENDERER_SORTED;
4872           else
4873             flags &= ~GTK_CELL_RENDERER_SORTED;
4874
4875           if (cursor == node)
4876             flags |= GTK_CELL_RENDERER_FOCUSED;
4877           else
4878             flags &= ~GTK_CELL_RENDERER_FOCUSED;
4879
4880           background_area.x = cell_offset;
4881           background_area.width = width;
4882
4883           cell_area = background_area;
4884           cell_area.y += vertical_separator / 2;
4885           cell_area.x += horizontal_separator / 2;
4886           cell_area.height -= vertical_separator;
4887           cell_area.width -= horizontal_separator;
4888
4889           if (draw_vgrid_lines)
4890             {
4891               if (list == first_column)
4892                 {
4893                   cell_area.width -= grid_line_width / 2;
4894                 }
4895               else if (list == last_column)
4896                 {
4897                   cell_area.x += grid_line_width / 2;
4898                   cell_area.width -= grid_line_width / 2;
4899                 }
4900               else
4901                 {
4902                   cell_area.x += grid_line_width / 2;
4903                   cell_area.width -= grid_line_width;
4904                 }
4905             }
4906
4907           if (draw_hgrid_lines)
4908             {
4909               cell_area.y += grid_line_width / 2;
4910               cell_area.height -= grid_line_width;
4911             }
4912
4913           if (!gdk_rectangle_intersect (&clip, &background_area, NULL))
4914             {
4915               cell_offset += gtk_tree_view_column_get_width (column);
4916               continue;
4917             }
4918
4919           gtk_tree_view_column_cell_set_cell_data (column,
4920                                                    tree_view->priv->model,
4921                                                    &iter,
4922                                                    GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
4923                                                    node->children?TRUE:FALSE);
4924
4925           /* Select the detail for drawing the cell.  relevant
4926            * factors are parity, sortedness, and whether to
4927            * display rules.
4928            */
4929           if (allow_rules && tree_view->priv->has_rules)
4930             {
4931               if (parity)
4932                 row_flags |= GTK_REGION_ODD;
4933               else
4934                 row_flags |= GTK_REGION_EVEN;
4935             }
4936
4937           if ((flags & GTK_CELL_RENDERER_SORTED) &&
4938               n_visible_columns >= 3)
4939             column_flags |= GTK_REGION_SORTED;
4940
4941           is_first = (rtl ? !list->next : !list->prev);
4942           is_last = (rtl ? !list->prev : !list->next);
4943
4944           if (is_first)
4945             column_flags |= GTK_REGION_FIRST;
4946
4947           if (is_last)
4948             column_flags |= GTK_REGION_LAST;
4949
4950           if ((n_col % 2) == 0)
4951             column_flags |= GTK_REGION_EVEN;
4952           else
4953             column_flags |= GTK_REGION_ODD;
4954
4955           gtk_style_context_save (context);
4956
4957           state = gtk_cell_renderer_get_state (NULL, widget, flags);
4958           gtk_style_context_set_state (context, state);
4959
4960           gtk_style_context_add_class (context, GTK_STYLE_CLASS_CELL);
4961           gtk_style_context_add_region (context, GTK_STYLE_REGION_ROW, row_flags);
4962           gtk_style_context_add_region (context, GTK_STYLE_REGION_COLUMN, column_flags);
4963
4964           if (node == cursor && has_can_focus_cell
4965               && ((column == tree_view->priv->focus_column
4966                    && tree_view->priv->draw_keyfocus &&
4967                    gtk_widget_has_visible_focus (widget))
4968                   || (column == tree_view->priv->edited_column)))
4969             draw_focus = TRUE;
4970           else
4971             draw_focus = FALSE;
4972
4973           /* Draw background */
4974           gtk_render_background (context, cr,
4975                                  background_area.x,
4976                                  background_area.y,
4977                                  background_area.width,
4978                                  background_area.height);
4979
4980           /* Draw frame */
4981           gtk_render_frame (context, cr,
4982                             background_area.x,
4983                             background_area.y,
4984                             background_area.width,
4985                             background_area.height);
4986
4987           if (gtk_tree_view_is_expander_column (tree_view, column))
4988             {
4989               if (!rtl)
4990                 cell_area.x += (depth - 1) * tree_view->priv->level_indentation;
4991               cell_area.width -= (depth - 1) * tree_view->priv->level_indentation;
4992
4993               if (gtk_tree_view_draw_expanders (tree_view))
4994                 {
4995                   if (!rtl)
4996                     cell_area.x += depth * tree_view->priv->expander_size;
4997                   cell_area.width -= depth * tree_view->priv->expander_size;
4998                 }
4999
5000               /* If we have an expander column, the highlight underline
5001                * starts with that column, so that it indicates which
5002                * level of the tree we're dropping at.
5003                */
5004               highlight_x = cell_area.x;
5005               expander_cell_width = cell_area.width;
5006
5007               if (is_separator)
5008                 gtk_render_line (context, cr,
5009                                  cell_area.x,
5010                                  cell_area.y + cell_area.height / 2,
5011                                  cell_area.x + cell_area.width,
5012                                  cell_area.y + cell_area.height / 2);
5013               else
5014                 _gtk_tree_view_column_cell_render (column,
5015                                                    cr,
5016                                                    &background_area,
5017                                                    &cell_area,
5018                                                    flags,
5019                                                    draw_focus);
5020               if (gtk_tree_view_draw_expanders (tree_view)
5021                   && (node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT)
5022                 {
5023                   if (!got_pointer)
5024                     {
5025                       gdk_window_get_pointer (tree_view->priv->bin_window, 
5026                                               &pointer_x, &pointer_y, NULL);
5027                       got_pointer = TRUE;
5028                     }
5029
5030                   gtk_tree_view_draw_arrow (GTK_TREE_VIEW (widget),
5031                                             cr,
5032                                             tree,
5033                                             node,
5034                                             pointer_x, pointer_y);
5035                 }
5036             }
5037           else
5038             {
5039               if (is_separator)
5040                 {
5041                   gtk_style_context_save (context);
5042                   gtk_style_context_add_class (context, GTK_STYLE_CLASS_SEPARATOR);
5043
5044                   gtk_render_line (context, cr,
5045                                    cell_area.x,
5046                                    cell_area.y + cell_area.height / 2,
5047                                    cell_area.x + cell_area.width,
5048                                    cell_area.y + cell_area.height / 2);
5049
5050                   gtk_style_context_restore (context);
5051                 }
5052               else
5053                 _gtk_tree_view_column_cell_render (column,
5054                                                    cr,
5055                                                    &background_area,
5056                                                    &cell_area,
5057                                                    flags,
5058                                                    draw_focus);
5059             }
5060
5061           if (draw_hgrid_lines)
5062             {
5063               if (background_area.y > 0)
5064                 gtk_tree_view_draw_line (tree_view, cr,
5065                                          GTK_TREE_VIEW_GRID_LINE,
5066                                          background_area.x, background_area.y,
5067                                          background_area.x + background_area.width,
5068                                          background_area.y);
5069
5070               if (y_offset + max_height >= clip.height)
5071                 gtk_tree_view_draw_line (tree_view, cr,
5072                                          GTK_TREE_VIEW_GRID_LINE,
5073                                          background_area.x, background_area.y + max_height,
5074                                          background_area.x + background_area.width,
5075                                          background_area.y + max_height);
5076             }
5077
5078           if (gtk_tree_view_is_expander_column (tree_view, column) &&
5079               tree_view->priv->tree_lines_enabled)
5080             {
5081               gint x = background_area.x;
5082               gint mult = rtl ? -1 : 1;
5083               gint y0 = background_area.y;
5084               gint y1 = background_area.y + background_area.height/2;
5085               gint y2 = background_area.y + background_area.height;
5086
5087               if (rtl)
5088                 x += background_area.width - 1;
5089
5090               if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT
5091                   && depth > 1)
5092                 {
5093                   gtk_tree_view_draw_line (tree_view, cr,
5094                                            GTK_TREE_VIEW_TREE_LINE,
5095                                            x + tree_view->priv->expander_size * (depth - 1.5) * mult,
5096                                            y1,
5097                                            x + tree_view->priv->expander_size * (depth - 1.1) * mult,
5098                                            y1);
5099                 }
5100               else if (depth > 1)
5101                 {
5102                   gtk_tree_view_draw_line (tree_view, cr,
5103                                            GTK_TREE_VIEW_TREE_LINE,
5104                                            x + tree_view->priv->expander_size * (depth - 1.5) * mult,
5105                                            y1,
5106                                            x + tree_view->priv->expander_size * (depth - 0.5) * mult,
5107                                            y1);
5108                 }
5109
5110               if (depth > 1)
5111                 {
5112                   gint i;
5113                   GtkRBNode *tmp_node;
5114                   GtkRBTree *tmp_tree;
5115
5116                   if (!_gtk_rbtree_next (tree, node))
5117                     gtk_tree_view_draw_line (tree_view, cr,
5118                                              GTK_TREE_VIEW_TREE_LINE,
5119                                              x + tree_view->priv->expander_size * (depth - 1.5) * mult,
5120                                              y0,
5121                                              x + tree_view->priv->expander_size * (depth - 1.5) * mult,
5122                                              y1);
5123                   else
5124                     gtk_tree_view_draw_line (tree_view, cr,
5125                                              GTK_TREE_VIEW_TREE_LINE,
5126                                              x + tree_view->priv->expander_size * (depth - 1.5) * mult,
5127                                              y0,
5128                                              x + tree_view->priv->expander_size * (depth - 1.5) * mult,
5129                                              y2);
5130
5131                   tmp_node = tree->parent_node;
5132                   tmp_tree = tree->parent_tree;
5133
5134                   for (i = depth - 2; i > 0; i--)
5135                     {
5136                       if (_gtk_rbtree_next (tmp_tree, tmp_node))
5137                         gtk_tree_view_draw_line (tree_view, cr,
5138                                                  GTK_TREE_VIEW_TREE_LINE,
5139                                                  x + tree_view->priv->expander_size * (i - 0.5) * mult,
5140                                                  y0,
5141                                                  x + tree_view->priv->expander_size * (i - 0.5) * mult,
5142                                                  y2);
5143
5144                       tmp_node = tmp_tree->parent_node;
5145                       tmp_tree = tmp_tree->parent_tree;
5146                     }
5147                 }
5148             }
5149
5150           gtk_style_context_restore (context);
5151           cell_offset += gtk_tree_view_column_get_width (column);
5152         }
5153
5154       if (node == drag_highlight)
5155         {
5156           /* Draw indicator for the drop
5157            */
5158           gint highlight_y = -1;
5159           GtkRBTree *tree = NULL;
5160           GtkRBNode *node = NULL;
5161
5162           switch (tree_view->priv->drag_dest_pos)
5163             {
5164             case GTK_TREE_VIEW_DROP_BEFORE:
5165               highlight_y = background_area.y - 1;
5166               if (highlight_y < 0)
5167                       highlight_y = 0;
5168               break;
5169
5170             case GTK_TREE_VIEW_DROP_AFTER:
5171               highlight_y = background_area.y + background_area.height - 1;
5172               break;
5173
5174             case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
5175             case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
5176               _gtk_tree_view_find_node (tree_view, drag_dest_path, &tree, &node);
5177
5178               if (tree == NULL)
5179                 break;
5180
5181               gtk_render_focus (context, cr,
5182                                 0, gtk_tree_view_get_row_y_offset (tree_view, tree, node)
5183                                    - focus_line_width / 2,
5184                                 gdk_window_get_width (tree_view->priv->bin_window),
5185                                 gtk_tree_view_get_row_height (tree_view, node)
5186                                    - focus_line_width + 1);
5187               break;
5188             }
5189
5190           if (highlight_y >= 0)
5191             {
5192               gtk_tree_view_draw_line (tree_view, cr,
5193                                        GTK_TREE_VIEW_FOREGROUND_LINE,
5194                                        rtl ? highlight_x + expander_cell_width : highlight_x,
5195                                        highlight_y,
5196                                        rtl ? 0 : bin_window_width,
5197                                        highlight_y);
5198             }
5199         }
5200
5201       /* draw the big row-spanning focus rectangle, if needed */
5202       if (!has_can_focus_cell && node == cursor &&
5203           tree_view->priv->draw_keyfocus &&
5204           gtk_widget_has_visible_focus (widget))
5205         {
5206           gint tmp_y, tmp_height;
5207           GtkStateFlags focus_rect_state = 0;
5208
5209           gtk_style_context_save (context);
5210
5211           focus_rect_state = gtk_cell_renderer_get_state (NULL, widget, flags);
5212           gtk_style_context_set_state (context, focus_rect_state);
5213
5214           if (draw_hgrid_lines)
5215             {
5216               tmp_y = gtk_tree_view_get_row_y_offset (tree_view, tree, node) + grid_line_width / 2;
5217               tmp_height = gtk_tree_view_get_row_height (tree_view, node) - grid_line_width;
5218             }
5219           else
5220             {
5221               tmp_y = gtk_tree_view_get_row_y_offset (tree_view, tree, node);
5222               tmp_height = gtk_tree_view_get_row_height (tree_view, node);
5223             }
5224
5225           gtk_render_focus (context, cr,
5226                             0, tmp_y,
5227                             gdk_window_get_width (tree_view->priv->bin_window),
5228                             tmp_height);
5229
5230           gtk_style_context_restore (context);
5231         }
5232
5233       y_offset += max_height;
5234       if (node->children)
5235         {
5236           GtkTreeIter parent = iter;
5237           gboolean has_child;
5238
5239           tree = node->children;
5240           node = tree->root;
5241
5242           g_assert (node != tree->nil);
5243
5244           while (node->left != tree->nil)
5245             node = node->left;
5246           has_child = gtk_tree_model_iter_children (tree_view->priv->model,
5247                                                     &iter,
5248                                                     &parent);
5249           depth++;
5250
5251           /* Sanity Check! */
5252           TREE_VIEW_INTERNAL_ASSERT (has_child, FALSE);
5253         }
5254       else
5255         {
5256           gboolean done = FALSE;
5257
5258           do
5259             {
5260               node = _gtk_rbtree_next (tree, node);
5261               if (node != NULL)
5262                 {
5263                   gboolean has_next = gtk_tree_model_iter_next (tree_view->priv->model, &iter);
5264                   done = TRUE;
5265
5266                   /* Sanity Check! */
5267                   TREE_VIEW_INTERNAL_ASSERT (has_next, FALSE);
5268                 }
5269               else
5270                 {
5271                   GtkTreeIter parent_iter = iter;
5272                   gboolean has_parent;
5273
5274                   node = tree->parent_node;
5275                   tree = tree->parent_tree;
5276                   if (tree == NULL)
5277                     /* we should go to done to free some memory */
5278                     goto done;
5279                   has_parent = gtk_tree_model_iter_parent (tree_view->priv->model,
5280                                                            &iter,
5281                                                            &parent_iter);
5282                   depth--;
5283
5284                   /* Sanity check */
5285                   TREE_VIEW_INTERNAL_ASSERT (has_parent, FALSE);
5286                 }
5287             }
5288           while (!done);
5289         }
5290     }
5291   while (y_offset < clip.height);
5292
5293 done:
5294   gtk_tree_view_draw_grid_lines (tree_view, cr, n_visible_columns);
5295
5296   if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
5297     gtk_tree_view_paint_rubber_band (tree_view, cr);
5298
5299   if (cursor_path)
5300     gtk_tree_path_free (cursor_path);
5301
5302   if (drag_dest_path)
5303     gtk_tree_path_free (drag_dest_path);
5304
5305   return FALSE;
5306 }
5307
5308 static gboolean
5309 gtk_tree_view_draw (GtkWidget *widget,
5310                     cairo_t   *cr)
5311 {
5312   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
5313   GtkWidget   *button;
5314
5315   if (gtk_cairo_should_draw_window (cr, tree_view->priv->bin_window))
5316     {
5317       GtkStyleContext *context;
5318       GList *tmp_list;
5319
5320       context = gtk_widget_get_style_context (widget);
5321
5322       cairo_save (cr);
5323
5324       gtk_style_context_save (context);
5325       gtk_style_context_add_class (context, GTK_STYLE_CLASS_VIEW);
5326
5327       gtk_cairo_transform_to_window (cr, widget, tree_view->priv->bin_window);
5328
5329       gtk_tree_view_bin_draw (widget, cr);
5330
5331       gtk_style_context_restore (context);
5332       cairo_restore (cr);
5333
5334       /* We can't just chain up to Container::draw as it will try to send the
5335        * event to the headers, so we handle propagating it to our children
5336        * (eg. widgets being edited) ourselves.
5337        */
5338       tmp_list = tree_view->priv->children;
5339       while (tmp_list)
5340         {
5341           GtkTreeViewChild *child = tmp_list->data;
5342           tmp_list = tmp_list->next;
5343
5344           gtk_container_propagate_draw (GTK_CONTAINER (tree_view), child->widget, cr);
5345         }
5346     }
5347
5348   if (gtk_cairo_should_draw_window (cr, tree_view->priv->header_window))
5349     {
5350       GList *list;
5351       
5352       for (list = tree_view->priv->columns; list != NULL; list = list->next)
5353         {
5354           GtkTreeViewColumn *column = list->data;
5355
5356           if (column == tree_view->priv->drag_column)
5357             continue;
5358
5359           if (gtk_tree_view_column_get_visible (column))
5360             {
5361               button = gtk_tree_view_column_get_button (column);
5362               gtk_container_propagate_draw (GTK_CONTAINER (tree_view),
5363                                             button, cr);
5364             }
5365         }
5366     }
5367   
5368   if (tree_view->priv->drag_window &&
5369       gtk_cairo_should_draw_window (cr, tree_view->priv->drag_window))
5370     {
5371       button = gtk_tree_view_column_get_button (tree_view->priv->drag_column);
5372       gtk_container_propagate_draw (GTK_CONTAINER (tree_view),
5373                                     button, cr);
5374     }
5375
5376   return TRUE;
5377 }
5378
5379 enum
5380 {
5381   DROP_HOME,
5382   DROP_RIGHT,
5383   DROP_LEFT,
5384   DROP_END
5385 };
5386
5387 /* returns 0x1 when no column has been found -- yes it's hackish */
5388 static GtkTreeViewColumn *
5389 gtk_tree_view_get_drop_column (GtkTreeView       *tree_view,
5390                                GtkTreeViewColumn *column,
5391                                gint               drop_position)
5392 {
5393   GtkTreeViewColumn *left_column = NULL;
5394   GtkTreeViewColumn *cur_column = NULL;
5395   GList *tmp_list;
5396
5397   if (!gtk_tree_view_column_get_reorderable (column))
5398     return (GtkTreeViewColumn *)0x1;
5399
5400   switch (drop_position)
5401     {
5402       case DROP_HOME:
5403         /* find first column where we can drop */
5404         tmp_list = tree_view->priv->columns;
5405         if (column == GTK_TREE_VIEW_COLUMN (tmp_list->data))
5406           return (GtkTreeViewColumn *)0x1;
5407
5408         while (tmp_list)
5409           {
5410             g_assert (tmp_list);
5411
5412             cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
5413             tmp_list = tmp_list->next;
5414
5415             if (left_column &&
5416                 gtk_tree_view_column_get_visible (left_column) == FALSE)
5417               continue;
5418
5419             if (!tree_view->priv->column_drop_func)
5420               return left_column;
5421
5422             if (!tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
5423               {
5424                 left_column = cur_column;
5425                 continue;
5426               }
5427
5428             return left_column;
5429           }
5430
5431         if (!tree_view->priv->column_drop_func)
5432           return left_column;
5433
5434         if (tree_view->priv->column_drop_func (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data))
5435           return left_column;
5436         else
5437           return (GtkTreeViewColumn *)0x1;
5438         break;
5439
5440       case DROP_RIGHT:
5441         /* find first column after column where we can drop */
5442         tmp_list = tree_view->priv->columns;
5443
5444         for (; tmp_list; tmp_list = tmp_list->next)
5445           if (GTK_TREE_VIEW_COLUMN (tmp_list->data) == column)
5446             break;
5447
5448         if (!tmp_list || !tmp_list->next)
5449           return (GtkTreeViewColumn *)0x1;
5450
5451         tmp_list = tmp_list->next;
5452         left_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
5453         tmp_list = tmp_list->next;
5454
5455         while (tmp_list)
5456           {
5457             g_assert (tmp_list);
5458
5459             cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
5460             tmp_list = tmp_list->next;
5461
5462             if (left_column &&
5463                 gtk_tree_view_column_get_visible (left_column) == FALSE)
5464               {
5465                 left_column = cur_column;
5466                 if (tmp_list)
5467                   tmp_list = tmp_list->next;
5468                 continue;
5469               }
5470
5471             if (!tree_view->priv->column_drop_func)
5472               return left_column;
5473
5474             if (!tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
5475               {
5476                 left_column = cur_column;
5477                 continue;
5478               }
5479
5480             return left_column;
5481           }
5482
5483         if (!tree_view->priv->column_drop_func)
5484           return left_column;
5485
5486         if (tree_view->priv->column_drop_func (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data))
5487           return left_column;
5488         else
5489           return (GtkTreeViewColumn *)0x1;
5490         break;
5491
5492       case DROP_LEFT:
5493         /* find first column before column where we can drop */
5494         tmp_list = tree_view->priv->columns;
5495
5496         for (; tmp_list; tmp_list = tmp_list->next)
5497           if (GTK_TREE_VIEW_COLUMN (tmp_list->data) == column)
5498             break;
5499
5500         if (!tmp_list || !tmp_list->prev)
5501           return (GtkTreeViewColumn *)0x1;
5502
5503         tmp_list = tmp_list->prev;
5504         cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
5505         tmp_list = tmp_list->prev;
5506
5507         while (tmp_list)
5508           {
5509             g_assert (tmp_list);
5510
5511             left_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
5512
5513             if (left_column &&
5514                 gtk_tree_view_column_get_visible (left_column) == FALSE)
5515               {
5516                 /*if (!tmp_list->prev)
5517                   return (GtkTreeViewColumn *)0x1;
5518                   */
5519 /*
5520                 cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->prev->data);
5521                 tmp_list = tmp_list->prev->prev;
5522                 continue;*/
5523
5524                 cur_column = left_column;
5525                 if (tmp_list)
5526                   tmp_list = tmp_list->prev;
5527                 continue;
5528               }
5529
5530             if (!tree_view->priv->column_drop_func)
5531               return left_column;
5532
5533             if (tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
5534               return left_column;
5535
5536             cur_column = left_column;
5537             tmp_list = tmp_list->prev;
5538           }
5539
5540         if (!tree_view->priv->column_drop_func)
5541           return NULL;
5542
5543         if (tree_view->priv->column_drop_func (tree_view, column, NULL, cur_column, tree_view->priv->column_drop_func_data))
5544           return NULL;
5545         else
5546           return (GtkTreeViewColumn *)0x1;
5547         break;
5548
5549       case DROP_END:
5550         /* same as DROP_HOME case, but doing it backwards */
5551         tmp_list = g_list_last (tree_view->priv->columns);
5552         cur_column = NULL;
5553
5554         if (column == GTK_TREE_VIEW_COLUMN (tmp_list->data))
5555           return (GtkTreeViewColumn *)0x1;
5556
5557         while (tmp_list)
5558           {
5559             g_assert (tmp_list);
5560
5561             left_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
5562
5563             if (left_column &&
5564                 gtk_tree_view_column_get_visible (left_column) == FALSE)
5565               {
5566                 cur_column = left_column;
5567                 tmp_list = tmp_list->prev;
5568               }
5569
5570             if (!tree_view->priv->column_drop_func)
5571               return left_column;
5572
5573             if (tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
5574               return left_column;
5575
5576             cur_column = left_column;
5577             tmp_list = tmp_list->prev;
5578           }
5579
5580         if (!tree_view->priv->column_drop_func)
5581           return NULL;
5582
5583         if (tree_view->priv->column_drop_func (tree_view, column, NULL, cur_column, tree_view->priv->column_drop_func_data))
5584           return NULL;
5585         else
5586           return (GtkTreeViewColumn *)0x1;
5587         break;
5588     }
5589
5590   return (GtkTreeViewColumn *)0x1;
5591 }
5592
5593 static gboolean
5594 gtk_tree_view_key_press (GtkWidget   *widget,
5595                          GdkEventKey *event)
5596 {
5597   GtkTreeView *tree_view = (GtkTreeView *) widget;
5598   GtkWidget   *button;
5599
5600   if (tree_view->priv->rubber_band_status)
5601     {
5602       if (event->keyval == GDK_KEY_Escape)
5603         gtk_tree_view_stop_rubber_band (tree_view);
5604
5605       return TRUE;
5606     }
5607
5608   if (tree_view->priv->in_column_drag)
5609     {
5610       if (event->keyval == GDK_KEY_Escape)
5611         {
5612           tree_view->priv->cur_reorder = NULL;
5613           gtk_tree_view_button_release_drag_column (widget, NULL);
5614         }
5615       return TRUE;
5616     }
5617
5618   if (tree_view->priv->headers_visible)
5619     {
5620       GList *focus_column;
5621       gboolean rtl;
5622
5623       rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
5624
5625       for (focus_column = tree_view->priv->columns;
5626            focus_column;
5627            focus_column = focus_column->next)
5628         {
5629           GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (focus_column->data);
5630           
5631           button = gtk_tree_view_column_get_button (column);
5632           if (gtk_widget_has_focus (button))
5633             break;
5634         }
5635
5636       if (focus_column &&
5637           (event->state & GDK_SHIFT_MASK) && (event->state & GDK_MOD1_MASK) &&
5638           (event->keyval == GDK_KEY_Left || event->keyval == GDK_KEY_KP_Left
5639            || event->keyval == GDK_KEY_Right || event->keyval == GDK_KEY_KP_Right))
5640         {
5641           GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (focus_column->data);
5642           gint max_width, min_width;
5643
5644           if (!gtk_tree_view_column_get_resizable (column))
5645             {
5646               gtk_widget_error_bell (widget);
5647               return TRUE;
5648             }
5649
5650           if (event->keyval == (rtl ? GDK_KEY_Right : GDK_KEY_Left)
5651               || event->keyval == (rtl ? GDK_KEY_KP_Right : GDK_KEY_KP_Left))
5652             {
5653               GtkRequisition button_req;
5654               gint old_width = _gtk_tree_view_column_get_resized_width (column);
5655               gint new_width;
5656
5657               button = gtk_tree_view_column_get_button (column);
5658
5659               gtk_widget_get_preferred_size (button, &button_req, NULL);
5660
5661               new_width = MAX (old_width, gtk_tree_view_column_get_width (column));
5662               new_width -= 2;
5663               if (new_width < 0)
5664                 new_width = 0;
5665
5666               _gtk_tree_view_column_set_resized_width (column, new_width);
5667
5668               min_width = gtk_tree_view_column_get_min_width (column);
5669               if (min_width == -1)
5670                 new_width = MAX (button_req.width, new_width);
5671               else
5672                 {
5673                   new_width = MAX (min_width, new_width);
5674                 }
5675
5676               max_width = gtk_tree_view_column_get_max_width (column);
5677               if (max_width != -1)
5678                 new_width = MIN (new_width, max_width);
5679
5680               _gtk_tree_view_column_set_use_resized_width (column, TRUE);
5681
5682               if (new_width != old_width)
5683                 {
5684                   _gtk_tree_view_column_set_resized_width (column, new_width);
5685                   gtk_widget_queue_resize (widget);
5686                 }
5687               else
5688                 gtk_widget_error_bell (widget);
5689             }
5690           else if (event->keyval == (rtl ? GDK_KEY_Left : GDK_KEY_Right)
5691                    || event->keyval == (rtl ? GDK_KEY_KP_Left : GDK_KEY_KP_Right))
5692             {
5693               gint old_width = _gtk_tree_view_column_get_resized_width (column);
5694               gint new_width;
5695
5696               new_width = MAX (old_width, gtk_tree_view_column_get_width (column));
5697               new_width += 2;
5698
5699               max_width = gtk_tree_view_column_get_max_width (column);
5700               if (max_width != -1)
5701                 new_width = MIN (new_width, max_width);
5702
5703               _gtk_tree_view_column_set_use_resized_width (column, TRUE);
5704
5705               if (new_width != old_width)
5706                 {
5707                   _gtk_tree_view_column_set_resized_width (column, new_width);
5708                   gtk_widget_queue_resize (widget);
5709                 }
5710               else
5711                 gtk_widget_error_bell (widget);
5712             }
5713
5714           return TRUE;
5715         }
5716
5717       if (focus_column &&
5718           (event->state & GDK_MOD1_MASK) &&
5719           (event->keyval == GDK_KEY_Left || event->keyval == GDK_KEY_KP_Left
5720            || event->keyval == GDK_KEY_Right || event->keyval == GDK_KEY_KP_Right
5721            || event->keyval == GDK_KEY_Home || event->keyval == GDK_KEY_KP_Home
5722            || event->keyval == GDK_KEY_End || event->keyval == GDK_KEY_KP_End))
5723         {
5724           GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (focus_column->data);
5725
5726           if (event->keyval == (rtl ? GDK_KEY_Right : GDK_KEY_Left)
5727               || event->keyval == (rtl ? GDK_KEY_KP_Right : GDK_KEY_KP_Left))
5728             {
5729               GtkTreeViewColumn *col;
5730               col = gtk_tree_view_get_drop_column (tree_view, column, DROP_LEFT);
5731               if (col != (GtkTreeViewColumn *)0x1)
5732                 gtk_tree_view_move_column_after (tree_view, column, col);
5733               else
5734                 gtk_widget_error_bell (widget);
5735             }
5736           else if (event->keyval == (rtl ? GDK_KEY_Left : GDK_KEY_Right)
5737                    || event->keyval == (rtl ? GDK_KEY_KP_Left : GDK_KEY_KP_Right))
5738             {
5739               GtkTreeViewColumn *col;
5740               col = gtk_tree_view_get_drop_column (tree_view, column, DROP_RIGHT);
5741               if (col != (GtkTreeViewColumn *)0x1)
5742                 gtk_tree_view_move_column_after (tree_view, column, col);
5743               else
5744                 gtk_widget_error_bell (widget);
5745             }
5746           else if (event->keyval == GDK_KEY_Home || event->keyval == GDK_KEY_KP_Home)
5747             {
5748               GtkTreeViewColumn *col;
5749               col = gtk_tree_view_get_drop_column (tree_view, column, DROP_HOME);
5750               if (col != (GtkTreeViewColumn *)0x1)
5751                 gtk_tree_view_move_column_after (tree_view, column, col);
5752               else
5753                 gtk_widget_error_bell (widget);
5754             }
5755           else if (event->keyval == GDK_KEY_End || event->keyval == GDK_KEY_KP_End)
5756             {
5757               GtkTreeViewColumn *col;
5758               col = gtk_tree_view_get_drop_column (tree_view, column, DROP_END);
5759               if (col != (GtkTreeViewColumn *)0x1)
5760                 gtk_tree_view_move_column_after (tree_view, column, col);
5761               else
5762                 gtk_widget_error_bell (widget);
5763             }
5764
5765           return TRUE;
5766         }
5767     }
5768
5769   /* Chain up to the parent class.  It handles the keybindings. */
5770   if (GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->key_press_event (widget, event))
5771     return TRUE;
5772
5773   if (tree_view->priv->search_entry_avoid_unhandled_binding)
5774     {
5775       tree_view->priv->search_entry_avoid_unhandled_binding = FALSE;
5776       return FALSE;
5777     }
5778
5779   /* We pass the event to the search_entry.  If its text changes, then we start
5780    * the typeahead find capabilities. */
5781   if (gtk_widget_has_focus (GTK_WIDGET (tree_view))
5782       && tree_view->priv->enable_search
5783       && !tree_view->priv->search_custom_entry_set)
5784     {
5785       GdkEvent *new_event;
5786       char *old_text;
5787       const char *new_text;
5788       gboolean retval;
5789       GdkScreen *screen;
5790       gboolean text_modified;
5791       gulong popup_menu_id;
5792
5793       gtk_tree_view_ensure_interactive_directory (tree_view);
5794
5795       /* Make a copy of the current text */
5796       old_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry)));
5797       new_event = gdk_event_copy ((GdkEvent *) event);
5798       g_object_unref (((GdkEventKey *) new_event)->window);
5799       ((GdkEventKey *) new_event)->window = g_object_ref (gtk_widget_get_window (tree_view->priv->search_window));
5800       gtk_widget_realize (tree_view->priv->search_window);
5801
5802       popup_menu_id = g_signal_connect (tree_view->priv->search_entry, 
5803                                         "popup-menu", G_CALLBACK (gtk_true),
5804                                         NULL);
5805
5806       /* Move the entry off screen */
5807       screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
5808       gtk_window_move (GTK_WINDOW (tree_view->priv->search_window),
5809                        gdk_screen_get_width (screen) + 1,
5810                        gdk_screen_get_height (screen) + 1);
5811       gtk_widget_show (tree_view->priv->search_window);
5812
5813       /* Send the event to the window.  If the preedit_changed signal is emitted
5814        * during this event, we will set priv->imcontext_changed  */
5815       tree_view->priv->imcontext_changed = FALSE;
5816       retval = gtk_widget_event (tree_view->priv->search_window, new_event);
5817       gdk_event_free (new_event);
5818       gtk_widget_hide (tree_view->priv->search_window);
5819
5820       g_signal_handler_disconnect (tree_view->priv->search_entry, 
5821                                    popup_menu_id);
5822
5823       /* We check to make sure that the entry tried to handle the text, and that
5824        * the text has changed.
5825        */
5826       new_text = gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry));
5827       text_modified = strcmp (old_text, new_text) != 0;
5828       g_free (old_text);
5829       if (tree_view->priv->imcontext_changed ||    /* we're in a preedit */
5830           (retval && text_modified))               /* ...or the text was modified */
5831         {
5832           if (gtk_tree_view_real_start_interactive_search (tree_view,
5833                                                            gdk_event_get_device ((GdkEvent *) event),
5834                                                            FALSE))
5835             {
5836               gtk_widget_grab_focus (GTK_WIDGET (tree_view));
5837               return TRUE;
5838             }
5839           else
5840             {
5841               gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
5842               return FALSE;
5843             }
5844         }
5845     }
5846
5847   return FALSE;
5848 }
5849
5850 static gboolean
5851 gtk_tree_view_key_release (GtkWidget   *widget,
5852                            GdkEventKey *event)
5853 {
5854   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
5855
5856   if (tree_view->priv->rubber_band_status)
5857     return TRUE;
5858
5859   return GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->key_release_event (widget, event);
5860 }
5861
5862 /* FIXME Is this function necessary? Can I get an enter_notify event
5863  * w/o either an expose event or a mouse motion event?
5864  */
5865 static gboolean
5866 gtk_tree_view_enter_notify (GtkWidget        *widget,
5867                             GdkEventCrossing *event)
5868 {
5869   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
5870   GtkRBTree *tree;
5871   GtkRBNode *node;
5872   gint new_y;
5873
5874   /* Sanity check it */
5875   if (event->window != tree_view->priv->bin_window)
5876     return FALSE;
5877
5878   if (tree_view->priv->tree == NULL)
5879     return FALSE;
5880
5881   if (event->mode == GDK_CROSSING_GRAB ||
5882       event->mode == GDK_CROSSING_GTK_GRAB ||
5883       event->mode == GDK_CROSSING_GTK_UNGRAB ||
5884       event->mode == GDK_CROSSING_STATE_CHANGED)
5885     return TRUE;
5886
5887   /* find the node internally */
5888   new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
5889   if (new_y < 0)
5890     new_y = 0;
5891   _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
5892
5893   tree_view->priv->event_last_x = event->x;
5894   tree_view->priv->event_last_y = event->y;
5895
5896   if ((tree_view->priv->button_pressed_node == NULL) ||
5897       (tree_view->priv->button_pressed_node == node))
5898     prelight_or_select (tree_view, tree, node, event->x, event->y);
5899
5900   return TRUE;
5901 }
5902
5903 static gboolean
5904 gtk_tree_view_leave_notify (GtkWidget        *widget,
5905                             GdkEventCrossing *event)
5906 {
5907   GtkTreeView *tree_view;
5908
5909   if (event->mode == GDK_CROSSING_GRAB)
5910     return TRUE;
5911
5912   tree_view = GTK_TREE_VIEW (widget);
5913
5914   if (tree_view->priv->prelight_node)
5915     _gtk_tree_view_queue_draw_node (tree_view,
5916                                    tree_view->priv->prelight_tree,
5917                                    tree_view->priv->prelight_node,
5918                                    NULL);
5919
5920   tree_view->priv->event_last_x = -10000;
5921   tree_view->priv->event_last_y = -10000;
5922
5923   prelight_or_select (tree_view,
5924                       NULL, NULL,
5925                       -1000, -1000); /* coords not possibly over an arrow */
5926
5927   return TRUE;
5928 }
5929
5930
5931 static gint
5932 gtk_tree_view_focus_out (GtkWidget     *widget,
5933                          GdkEventFocus *event)
5934 {
5935   GtkTreeView *tree_view;
5936
5937   tree_view = GTK_TREE_VIEW (widget);
5938
5939   gtk_widget_queue_draw (widget);
5940
5941   /* destroy interactive search dialog */
5942   if (tree_view->priv->search_window)
5943     gtk_tree_view_search_dialog_hide (tree_view->priv->search_window, tree_view,
5944                                       gdk_event_get_device ((GdkEvent *) event));
5945
5946   return FALSE;
5947 }
5948
5949
5950 /* Incremental Reflow
5951  */
5952
5953 static void
5954 gtk_tree_view_node_queue_redraw (GtkTreeView *tree_view,
5955                                  GtkRBTree   *tree,
5956                                  GtkRBNode   *node)
5957 {
5958   GtkAllocation allocation;
5959   gint y;
5960
5961   y = _gtk_rbtree_node_find_offset (tree, node)
5962     - gtk_adjustment_get_value (tree_view->priv->vadjustment)
5963     + gtk_tree_view_get_effective_header_height (tree_view);
5964
5965   gtk_widget_get_allocation (GTK_WIDGET (tree_view), &allocation);
5966   gtk_widget_queue_draw_area (GTK_WIDGET (tree_view),
5967                               0, y,
5968                               allocation.width,
5969                               GTK_RBNODE_GET_HEIGHT (node));
5970 }
5971
5972 static gboolean
5973 node_is_visible (GtkTreeView *tree_view,
5974                  GtkRBTree   *tree,
5975                  GtkRBNode   *node)
5976 {
5977   int y;
5978   int height;
5979
5980   y = _gtk_rbtree_node_find_offset (tree, node);
5981   height = gtk_tree_view_get_row_height (tree_view, node);
5982
5983   if (y >= gtk_adjustment_get_value (tree_view->priv->vadjustment) &&
5984       y + height <= (gtk_adjustment_get_value (tree_view->priv->vadjustment)
5985                      + gtk_adjustment_get_page_size (tree_view->priv->vadjustment)))
5986     return TRUE;
5987
5988   return FALSE;
5989 }
5990
5991 /* Returns TRUE if it updated the size
5992  */
5993 static gboolean
5994 validate_row (GtkTreeView *tree_view,
5995               GtkRBTree   *tree,
5996               GtkRBNode   *node,
5997               GtkTreeIter *iter,
5998               GtkTreePath *path)
5999 {
6000   GtkTreeViewColumn *column;
6001   GList *list, *first_column, *last_column;
6002   gint height = 0;
6003   gint horizontal_separator;
6004   gint vertical_separator;
6005   gint depth = gtk_tree_path_get_depth (path);
6006   gboolean retval = FALSE;
6007   gboolean is_separator = FALSE;
6008   gboolean draw_vgrid_lines, draw_hgrid_lines;
6009   gint focus_pad;
6010   gint grid_line_width;
6011   gboolean wide_separators;
6012   gint separator_height;
6013
6014   /* double check the row needs validating */
6015   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) &&
6016       ! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
6017     return FALSE;
6018
6019   is_separator = row_is_separator (tree_view, iter, NULL);
6020
6021   gtk_widget_style_get (GTK_WIDGET (tree_view),
6022                         "focus-padding", &focus_pad,
6023                         "horizontal-separator", &horizontal_separator,
6024                         "vertical-separator", &vertical_separator,
6025                         "grid-line-width", &grid_line_width,
6026                         "wide-separators",  &wide_separators,
6027                         "separator-height", &separator_height,
6028                         NULL);
6029   
6030   draw_vgrid_lines =
6031     tree_view->priv->grid_lines == GTK_TREE_VIEW_GRID_LINES_VERTICAL
6032     || tree_view->priv->grid_lines == GTK_TREE_VIEW_GRID_LINES_BOTH;
6033   draw_hgrid_lines =
6034     tree_view->priv->grid_lines == GTK_TREE_VIEW_GRID_LINES_HORIZONTAL
6035     || tree_view->priv->grid_lines == GTK_TREE_VIEW_GRID_LINES_BOTH;
6036
6037   for (last_column = g_list_last (tree_view->priv->columns);
6038        last_column &&
6039        !(gtk_tree_view_column_get_visible (GTK_TREE_VIEW_COLUMN (last_column->data)));
6040        last_column = last_column->prev)
6041     ;
6042
6043   for (first_column = g_list_first (tree_view->priv->columns);
6044        first_column &&
6045        !(gtk_tree_view_column_get_visible (GTK_TREE_VIEW_COLUMN (first_column->data)));
6046        first_column = first_column->next)
6047     ;
6048
6049   for (list = tree_view->priv->columns; list; list = list->next)
6050     {
6051       gint padding = 0;
6052       gint original_width;
6053       gint new_width;
6054       gint row_height;
6055
6056       column = list->data;
6057
6058       if (!gtk_tree_view_column_get_visible (column))
6059         continue;
6060
6061       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID) && 
6062           !_gtk_tree_view_column_cell_get_dirty (column))
6063         continue;
6064
6065       original_width = _gtk_tree_view_column_get_requested_width (column);
6066
6067       gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, iter,
6068                                                GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
6069                                                node->children?TRUE:FALSE);
6070       gtk_tree_view_column_cell_get_size (column,
6071                                           NULL, NULL, NULL,
6072                                           NULL, &row_height);
6073
6074       if (!is_separator)
6075         {
6076           row_height += vertical_separator;
6077           height = MAX (height, row_height);
6078           height = MAX (height, tree_view->priv->expander_size);
6079         }
6080       else
6081         {
6082           if (wide_separators)
6083             height = separator_height + 2 * focus_pad;
6084           else
6085             height = 2 + 2 * focus_pad;
6086         }
6087
6088       if (gtk_tree_view_is_expander_column (tree_view, column))
6089         {
6090           padding += horizontal_separator + (depth - 1) * tree_view->priv->level_indentation;
6091
6092           if (gtk_tree_view_draw_expanders (tree_view))
6093             padding += depth * tree_view->priv->expander_size;
6094         }
6095       else
6096         padding += horizontal_separator;
6097
6098       if (draw_vgrid_lines)
6099         {
6100           if (list->data == first_column || list->data == last_column)
6101             padding += grid_line_width / 2.0;
6102           else
6103             padding += grid_line_width;
6104         }
6105
6106       /* Update the padding for the column */
6107       _gtk_tree_view_column_push_padding (column, padding);
6108       new_width = _gtk_tree_view_column_get_requested_width (column);
6109
6110       if (new_width > original_width)
6111         retval = TRUE;
6112     }
6113
6114   if (draw_hgrid_lines)
6115     height += grid_line_width;
6116
6117   if (height != GTK_RBNODE_GET_HEIGHT (node))
6118     {
6119       retval = TRUE;
6120       _gtk_rbtree_node_set_height (tree, node, height);
6121     }
6122   _gtk_rbtree_node_mark_valid (tree, node);
6123   tree_view->priv->post_validation_flag = TRUE;
6124
6125   return retval;
6126 }
6127
6128
6129 static void
6130 validate_visible_area (GtkTreeView *tree_view)
6131 {
6132   GtkAllocation allocation;
6133   GtkTreePath *path = NULL;
6134   GtkTreePath *above_path = NULL;
6135   GtkTreeIter iter;
6136   GtkRBTree *tree = NULL;
6137   GtkRBNode *node = NULL;
6138   gboolean need_redraw = FALSE;
6139   gboolean size_changed = FALSE;
6140   gint total_height;
6141   gint area_above = 0;
6142   gint area_below = 0;
6143
6144   if (tree_view->priv->tree == NULL)
6145     return;
6146
6147   if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID) &&
6148       tree_view->priv->scroll_to_path == NULL)
6149     return;
6150
6151   gtk_widget_get_allocation (GTK_WIDGET (tree_view), &allocation);
6152   total_height = allocation.height - gtk_tree_view_get_effective_header_height (tree_view);
6153
6154   if (total_height == 0)
6155     return;
6156
6157   /* First, we check to see if we need to scroll anywhere
6158    */
6159   if (tree_view->priv->scroll_to_path)
6160     {
6161       path = gtk_tree_row_reference_get_path (tree_view->priv->scroll_to_path);
6162       if (path && !_gtk_tree_view_find_node (tree_view, path, &tree, &node))
6163         {
6164           /* we are going to scroll, and will update dy */
6165           gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
6166           if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
6167               GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
6168             {
6169               _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
6170               if (validate_row (tree_view, tree, node, &iter, path))
6171                 size_changed = TRUE;
6172             }
6173
6174           if (tree_view->priv->scroll_to_use_align)
6175             {
6176               gint height = gtk_tree_view_get_row_height (tree_view, node);
6177               area_above = (total_height - height) *
6178                 tree_view->priv->scroll_to_row_align;
6179               area_below = total_height - area_above - height;
6180               area_above = MAX (area_above, 0);
6181               area_below = MAX (area_below, 0);
6182             }
6183           else
6184             {
6185               /* two cases:
6186                * 1) row not visible
6187                * 2) row visible
6188                */
6189               gint dy;
6190               gint height = gtk_tree_view_get_row_height (tree_view, node);
6191
6192               dy = _gtk_rbtree_node_find_offset (tree, node);
6193
6194               if (dy >= gtk_adjustment_get_value (tree_view->priv->vadjustment) &&
6195                   dy + height <= (gtk_adjustment_get_value (tree_view->priv->vadjustment)
6196                                   + gtk_adjustment_get_page_size (tree_view->priv->vadjustment)))
6197                 {
6198                   /* row visible: keep the row at the same position */
6199                   area_above = dy - gtk_adjustment_get_value (tree_view->priv->vadjustment);
6200                   area_below = (gtk_adjustment_get_value (tree_view->priv->vadjustment) +
6201                                 gtk_adjustment_get_page_size (tree_view->priv->vadjustment))
6202                                - dy - height;
6203                 }
6204               else
6205                 {
6206                   /* row not visible */
6207                   if (dy >= 0
6208                       && dy + height <= gtk_adjustment_get_page_size (tree_view->priv->vadjustment))
6209                     {
6210                       /* row at the beginning -- fixed */
6211                       area_above = dy;
6212                       area_below = gtk_adjustment_get_page_size (tree_view->priv->vadjustment)
6213                                    - area_above - height;
6214                     }
6215                   else if (dy >= (gtk_adjustment_get_upper (tree_view->priv->vadjustment) -
6216                                   gtk_adjustment_get_page_size (tree_view->priv->vadjustment)))
6217                     {
6218                       /* row at the end -- fixed */
6219                       area_above = dy - (gtk_adjustment_get_upper (tree_view->priv->vadjustment) -
6220                                    gtk_adjustment_get_page_size (tree_view->priv->vadjustment));
6221                       area_below = gtk_adjustment_get_page_size (tree_view->priv->vadjustment) -
6222                                    area_above - height;
6223
6224                       if (area_below < 0)
6225                         {
6226                           area_above = gtk_adjustment_get_page_size (tree_view->priv->vadjustment) - height;
6227                           area_below = 0;
6228                         }
6229                     }
6230                   else
6231                     {
6232                       /* row somewhere in the middle, bring it to the top
6233                        * of the view
6234                        */
6235                       area_above = 0;
6236                       area_below = total_height - height;
6237                     }
6238                 }
6239             }
6240         }
6241       else
6242         /* the scroll to isn't valid; ignore it.
6243          */
6244         {
6245           if (tree_view->priv->scroll_to_path && !path)
6246             {
6247               gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
6248               tree_view->priv->scroll_to_path = NULL;
6249             }
6250           if (path)
6251             gtk_tree_path_free (path);
6252           path = NULL;
6253         }      
6254     }
6255
6256   /* We didn't have a scroll_to set, so we just handle things normally
6257    */
6258   if (path == NULL)
6259     {
6260       gint offset;
6261
6262       offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
6263                                         TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, 0),
6264                                         &tree, &node);
6265       if (node == NULL)
6266         {
6267           /* In this case, nothing has been validated */
6268           path = gtk_tree_path_new_first ();
6269           _gtk_tree_view_find_node (tree_view, path, &tree, &node);
6270         }
6271       else
6272         {
6273           path = _gtk_tree_view_find_path (tree_view, tree, node);
6274           total_height += offset;
6275         }
6276
6277       gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
6278
6279       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
6280           GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
6281         {
6282           _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
6283           if (validate_row (tree_view, tree, node, &iter, path))
6284             size_changed = TRUE;
6285         }
6286       area_above = 0;
6287       area_below = total_height - gtk_tree_view_get_row_height (tree_view, node);
6288     }
6289
6290   above_path = gtk_tree_path_copy (path);
6291
6292   /* if we do not validate any row above the new top_row, we will make sure
6293    * that the row immediately above top_row has been validated. (if we do not
6294    * do this, _gtk_rbtree_find_offset will find the row above top_row, because
6295    * when invalidated that row's height will be zero. and this will mess up
6296    * scrolling).
6297    */
6298   if (area_above == 0)
6299     {
6300       GtkRBTree *tmptree;
6301       GtkRBNode *tmpnode;
6302
6303       _gtk_tree_view_find_node (tree_view, above_path, &tmptree, &tmpnode);
6304       _gtk_rbtree_prev_full (tmptree, tmpnode, &tmptree, &tmpnode);
6305
6306       if (tmpnode)
6307         {
6308           GtkTreePath *tmppath;
6309           GtkTreeIter tmpiter;
6310
6311           tmppath = _gtk_tree_view_find_path (tree_view, tmptree, tmpnode);
6312           gtk_tree_model_get_iter (tree_view->priv->model, &tmpiter, tmppath);
6313
6314           if (GTK_RBNODE_FLAG_SET (tmpnode, GTK_RBNODE_INVALID) ||
6315               GTK_RBNODE_FLAG_SET (tmpnode, GTK_RBNODE_COLUMN_INVALID))
6316             {
6317               _gtk_tree_view_queue_draw_node (tree_view, tmptree, tmpnode, NULL);
6318               if (validate_row (tree_view, tmptree, tmpnode, &tmpiter, tmppath))
6319                 size_changed = TRUE;
6320             }
6321
6322           gtk_tree_path_free (tmppath);
6323         }
6324     }
6325
6326   /* Now, we walk forwards and backwards, measuring rows. Unfortunately,
6327    * backwards is much slower then forward, as there is no iter_prev function.
6328    * We go forwards first in case we run out of tree.  Then we go backwards to
6329    * fill out the top.
6330    */
6331   while (node && area_below > 0)
6332     {
6333       if (node->children)
6334         {
6335           GtkTreeIter parent = iter;
6336           gboolean has_child;
6337
6338           tree = node->children;
6339           node = tree->root;
6340
6341           g_assert (node != tree->nil);
6342
6343           while (node->left != tree->nil)
6344             node = node->left;
6345           has_child = gtk_tree_model_iter_children (tree_view->priv->model,
6346                                                     &iter,
6347                                                     &parent);
6348           TREE_VIEW_INTERNAL_ASSERT_VOID (has_child);
6349           gtk_tree_path_down (path);
6350         }
6351       else
6352         {
6353           gboolean done = FALSE;
6354           do
6355             {
6356               node = _gtk_rbtree_next (tree, node);
6357               if (node != NULL)
6358                 {
6359                   gboolean has_next = gtk_tree_model_iter_next (tree_view->priv->model, &iter);
6360                   done = TRUE;
6361                   gtk_tree_path_next (path);
6362
6363                   /* Sanity Check! */
6364                   TREE_VIEW_INTERNAL_ASSERT_VOID (has_next);
6365                 }
6366               else
6367                 {
6368                   GtkTreeIter parent_iter = iter;
6369                   gboolean has_parent;
6370
6371                   node = tree->parent_node;
6372                   tree = tree->parent_tree;
6373                   if (tree == NULL)
6374                     break;
6375                   has_parent = gtk_tree_model_iter_parent (tree_view->priv->model,
6376                                                            &iter,
6377                                                            &parent_iter);
6378                   gtk_tree_path_up (path);
6379
6380                   /* Sanity check */
6381                   TREE_VIEW_INTERNAL_ASSERT_VOID (has_parent);
6382                 }
6383             }
6384           while (!done);
6385         }
6386
6387       if (!node)
6388         break;
6389
6390       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
6391           GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
6392         {
6393           _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
6394           if (validate_row (tree_view, tree, node, &iter, path))
6395               size_changed = TRUE;
6396         }
6397
6398       area_below -= gtk_tree_view_get_row_height (tree_view, node);
6399     }
6400   gtk_tree_path_free (path);
6401
6402   /* If we ran out of tree, and have extra area_below left, we need to add it
6403    * to area_above */
6404   if (area_below > 0)
6405     area_above += area_below;
6406
6407   _gtk_tree_view_find_node (tree_view, above_path, &tree, &node);
6408
6409   /* We walk backwards */
6410   while (area_above > 0)
6411     {
6412       _gtk_rbtree_prev_full (tree, node, &tree, &node);
6413
6414       /* Always find the new path in the tree.  We cannot just assume
6415        * a gtk_tree_path_prev() is enough here, as there might be children
6416        * in between this node and the previous sibling node.  If this
6417        * appears to be a performance hotspot in profiles, we can look into
6418        * intrigate logic for keeping path, node and iter in sync like
6419        * we do for forward walks.  (Which will be hard because of the lacking
6420        * iter_prev).
6421        */
6422
6423       if (node == NULL)
6424         break;
6425
6426       gtk_tree_path_free (above_path);
6427       above_path = _gtk_tree_view_find_path (tree_view, tree, node);
6428
6429       gtk_tree_model_get_iter (tree_view->priv->model, &iter, above_path);
6430
6431       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
6432           GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
6433         {
6434           _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
6435           if (validate_row (tree_view, tree, node, &iter, above_path))
6436             size_changed = TRUE;
6437         }
6438       area_above -= gtk_tree_view_get_row_height (tree_view, node);
6439     }
6440
6441   /* if we scrolled to a path, we need to set the dy here,
6442    * and sync the top row accordingly
6443    */
6444   if (tree_view->priv->scroll_to_path)
6445     {
6446       gtk_tree_view_set_top_row (tree_view, above_path, -area_above);
6447       gtk_tree_view_top_row_to_dy (tree_view);
6448
6449       need_redraw = TRUE;
6450     }
6451   else if (tree_view->priv->height <= gtk_adjustment_get_page_size (tree_view->priv->vadjustment))
6452     {
6453       /* when we are not scrolling, we should never set dy to something
6454        * else than zero. we update top_row to be in sync with dy = 0.
6455        */
6456       gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), 0);
6457       gtk_tree_view_dy_to_top_row (tree_view);
6458     }
6459   else if (gtk_adjustment_get_value (tree_view->priv->vadjustment) + gtk_adjustment_get_page_size (tree_view->priv->vadjustment) > tree_view->priv->height)
6460     {
6461       gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), tree_view->priv->height - gtk_adjustment_get_page_size (tree_view->priv->vadjustment));
6462       gtk_tree_view_dy_to_top_row (tree_view);
6463     }
6464   else
6465     gtk_tree_view_top_row_to_dy (tree_view);
6466
6467   /* update width/height and queue a resize */
6468   if (size_changed)
6469     {
6470       GtkRequisition requisition;
6471
6472       /* We temporarily guess a size, under the assumption that it will be the
6473        * same when we get our next size_allocate.  If we don't do this, we'll be
6474        * in an inconsistent state if we call top_row_to_dy. */
6475
6476       gtk_widget_get_preferred_size (GTK_WIDGET (tree_view),
6477                                      &requisition, NULL);
6478       gtk_adjustment_set_upper (tree_view->priv->hadjustment,
6479                                 MAX (gtk_adjustment_get_upper (tree_view->priv->hadjustment), requisition.width));
6480       gtk_adjustment_set_upper (tree_view->priv->vadjustment,
6481                                 MAX (gtk_adjustment_get_upper (tree_view->priv->vadjustment), requisition.height));
6482       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
6483     }
6484
6485   if (tree_view->priv->scroll_to_path)
6486     {
6487       gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
6488       tree_view->priv->scroll_to_path = NULL;
6489     }
6490
6491   if (above_path)
6492     gtk_tree_path_free (above_path);
6493
6494   if (tree_view->priv->scroll_to_column)
6495     {
6496       tree_view->priv->scroll_to_column = NULL;
6497     }
6498   if (need_redraw)
6499     gtk_widget_queue_draw (GTK_WIDGET (tree_view));
6500 }
6501
6502 static void
6503 initialize_fixed_height_mode (GtkTreeView *tree_view)
6504 {
6505   if (!tree_view->priv->tree)
6506     return;
6507
6508   if (tree_view->priv->fixed_height < 0)
6509     {
6510       GtkTreeIter iter;
6511       GtkTreePath *path;
6512
6513       GtkRBTree *tree = NULL;
6514       GtkRBNode *node = NULL;
6515
6516       tree = tree_view->priv->tree;
6517       node = tree->root;
6518
6519       path = _gtk_tree_view_find_path (tree_view, tree, node);
6520       gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
6521
6522       validate_row (tree_view, tree, node, &iter, path);
6523
6524       gtk_tree_path_free (path);
6525
6526       tree_view->priv->fixed_height = gtk_tree_view_get_row_height (tree_view, node);
6527     }
6528
6529    _gtk_rbtree_set_fixed_height (tree_view->priv->tree,
6530                                  tree_view->priv->fixed_height, TRUE);
6531 }
6532
6533 /* Our strategy for finding nodes to validate is a little convoluted.  We find
6534  * the left-most uninvalidated node.  We then try walking right, validating
6535  * nodes.  Once we find a valid node, we repeat the previous process of finding
6536  * the first invalid node.
6537  */
6538
6539 static gboolean
6540 do_validate_rows (GtkTreeView *tree_view, gboolean queue_resize)
6541 {
6542   GtkRBTree *tree = NULL;
6543   GtkRBNode *node = NULL;
6544   gboolean validated_area = FALSE;
6545   gint retval = TRUE;
6546   GtkTreePath *path = NULL;
6547   GtkTreeIter iter;
6548   GTimer *timer;
6549   gint i = 0;
6550
6551   gint y = -1;
6552   gint prev_height = -1;
6553   gboolean fixed_height = TRUE;
6554
6555   g_assert (tree_view);
6556
6557   if (tree_view->priv->tree == NULL)
6558       return FALSE;
6559
6560   if (tree_view->priv->fixed_height_mode)
6561     {
6562       if (tree_view->priv->fixed_height < 0)
6563         initialize_fixed_height_mode (tree_view);
6564
6565       return FALSE;
6566     }
6567
6568   timer = g_timer_new ();
6569   g_timer_start (timer);
6570
6571   do
6572     {
6573       gboolean changed = FALSE;
6574
6575       if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
6576         {
6577           retval = FALSE;
6578           goto done;
6579         }
6580
6581       if (path != NULL)
6582         {
6583           node = _gtk_rbtree_next (tree, node);
6584           if (node != NULL)
6585             {
6586               TREE_VIEW_INTERNAL_ASSERT (gtk_tree_model_iter_next (tree_view->priv->model, &iter), FALSE);
6587               gtk_tree_path_next (path);
6588             }
6589           else
6590             {
6591               gtk_tree_path_free (path);
6592               path = NULL;
6593             }
6594         }
6595
6596       if (path == NULL)
6597         {
6598           tree = tree_view->priv->tree;
6599           node = tree_view->priv->tree->root;
6600
6601           g_assert (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_DESCENDANTS_INVALID));
6602
6603           do
6604             {
6605               if (node->left != tree->nil &&
6606                   GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID))
6607                 {
6608                   node = node->left;
6609                 }
6610               else if (node->right != tree->nil &&
6611                        GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID))
6612                 {
6613                   node = node->right;
6614                 }
6615               else if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
6616                        GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
6617                 {
6618                   break;
6619                 }
6620               else if (node->children != NULL)
6621                 {
6622                   tree = node->children;
6623                   node = tree->root;
6624                 }
6625               else
6626                 /* RBTree corruption!  All bad */
6627                 g_assert_not_reached ();
6628             }
6629           while (TRUE);
6630           path = _gtk_tree_view_find_path (tree_view, tree, node);
6631           gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
6632         }
6633
6634       changed = validate_row (tree_view, tree, node, &iter, path);
6635       validated_area = changed || validated_area;
6636
6637       if (changed)
6638         {
6639           gint offset = gtk_tree_view_get_row_y_offset (tree_view, tree, node);
6640
6641           if (y == -1 || y > offset)
6642             y = offset;
6643         }
6644
6645       if (!tree_view->priv->fixed_height_check)
6646         {
6647           gint height;
6648
6649           height = gtk_tree_view_get_row_height (tree_view, node);
6650           if (prev_height < 0)
6651             prev_height = height;
6652           else if (prev_height != height)
6653             fixed_height = FALSE;
6654         }
6655
6656       i++;
6657     }
6658   while (g_timer_elapsed (timer, NULL) < GTK_TREE_VIEW_TIME_MS_PER_IDLE / 1000.);
6659
6660   if (!tree_view->priv->fixed_height_check)
6661    {
6662      if (fixed_height)
6663        _gtk_rbtree_set_fixed_height (tree_view->priv->tree, prev_height, FALSE);
6664
6665      tree_view->priv->fixed_height_check = 1;
6666    }
6667   
6668  done:
6669   if (validated_area)
6670     {
6671       GtkRequisition requisition;
6672
6673       /* We temporarily guess a size, under the assumption that it will be the
6674        * same when we get our next size_allocate.  If we don't do this, we'll be
6675        * in an inconsistent state when we call top_row_to_dy. */
6676
6677       /* FIXME: This is called from size_request, for some reason it is not infinitely
6678        * recursing, we cannot call gtk_widget_get_preferred_size() here because that's
6679        * not allowed (from inside ->get_preferred_width/height() implementations, one
6680        * should call the vfuncs directly). However what is desired here is the full
6681        * size including any margins and limited by any alignment (i.e. after 
6682        * GtkWidget:adjust_size_request() is called).
6683        *
6684        * Currently bypassing this but the real solution is to not update the scroll adjustments
6685        * untill we've recieved an allocation (never update scroll adjustments from size-requests).
6686        */
6687       gtk_tree_view_size_request (GTK_WIDGET (tree_view), &requisition, FALSE);
6688
6689       /* If rows above the current position have changed height, this has
6690        * affected the current view and thus needs a redraw.
6691        */
6692       if (y != -1 && y < gtk_adjustment_get_value (tree_view->priv->vadjustment))
6693         gtk_widget_queue_draw (GTK_WIDGET (tree_view));
6694
6695       gtk_adjustment_set_upper (tree_view->priv->hadjustment,
6696                                 MAX (gtk_adjustment_get_upper (tree_view->priv->hadjustment), requisition.width));
6697       gtk_adjustment_set_upper (tree_view->priv->vadjustment,
6698                                 MAX (gtk_adjustment_get_upper (tree_view->priv->vadjustment), requisition.height));
6699
6700       if (queue_resize)
6701         gtk_widget_queue_resize_no_redraw (GTK_WIDGET (tree_view));
6702     }
6703
6704   if (path) gtk_tree_path_free (path);
6705   g_timer_destroy (timer);
6706
6707   return retval;
6708 }
6709
6710 static gboolean
6711 validate_rows (GtkTreeView *tree_view)
6712 {
6713   gboolean retval;
6714   
6715   retval = do_validate_rows (tree_view, TRUE);
6716   
6717   if (! retval && tree_view->priv->validate_rows_timer)
6718     {
6719       g_source_remove (tree_view->priv->validate_rows_timer);
6720       tree_view->priv->validate_rows_timer = 0;
6721     }
6722
6723   return retval;
6724 }
6725
6726 static gboolean
6727 validate_rows_handler (GtkTreeView *tree_view)
6728 {
6729   gboolean retval;
6730
6731   retval = do_validate_rows (tree_view, TRUE);
6732   if (! retval && tree_view->priv->validate_rows_timer)
6733     {
6734       g_source_remove (tree_view->priv->validate_rows_timer);
6735       tree_view->priv->validate_rows_timer = 0;
6736     }
6737
6738   return retval;
6739 }
6740
6741 static gboolean
6742 do_presize_handler (GtkTreeView *tree_view)
6743 {
6744   if (tree_view->priv->mark_rows_col_dirty)
6745     {
6746       if (tree_view->priv->tree)
6747         _gtk_rbtree_column_invalid (tree_view->priv->tree);
6748       tree_view->priv->mark_rows_col_dirty = FALSE;
6749     }
6750   validate_visible_area (tree_view);
6751   tree_view->priv->presize_handler_timer = 0;
6752
6753   if (tree_view->priv->fixed_height_mode)
6754     {
6755       GtkRequisition requisition;
6756
6757       gtk_widget_get_preferred_size (GTK_WIDGET (tree_view),
6758                                      &requisition, NULL);
6759
6760       gtk_adjustment_set_upper (tree_view->priv->hadjustment,
6761                                 MAX (gtk_adjustment_get_upper (tree_view->priv->hadjustment), requisition.width));
6762       gtk_adjustment_set_upper (tree_view->priv->vadjustment,
6763                                 MAX (gtk_adjustment_get_upper (tree_view->priv->vadjustment), requisition.height));
6764       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
6765     }
6766                    
6767   return FALSE;
6768 }
6769
6770 static gboolean
6771 presize_handler_callback (gpointer data)
6772 {
6773   do_presize_handler (GTK_TREE_VIEW (data));
6774                    
6775   return FALSE;
6776 }
6777
6778 static void
6779 install_presize_handler (GtkTreeView *tree_view)
6780 {
6781   if (! gtk_widget_get_realized (GTK_WIDGET (tree_view)))
6782     return;
6783
6784   if (! tree_view->priv->presize_handler_timer)
6785     {
6786       tree_view->priv->presize_handler_timer =
6787         gdk_threads_add_idle_full (GTK_PRIORITY_RESIZE - 2, presize_handler_callback, tree_view, NULL);
6788     }
6789   if (! tree_view->priv->validate_rows_timer)
6790     {
6791       tree_view->priv->validate_rows_timer =
6792         gdk_threads_add_idle_full (GTK_TREE_VIEW_PRIORITY_VALIDATE, (GSourceFunc) validate_rows_handler, tree_view, NULL);
6793     }
6794 }
6795
6796 static void
6797 gtk_tree_view_bin_process_updates (GtkTreeView *tree_view)
6798 {
6799   /* Prior to drawing, we make sure the visible area is validated. */
6800   if (tree_view->priv->presize_handler_timer)
6801     {
6802       g_source_remove (tree_view->priv->presize_handler_timer);
6803       tree_view->priv->presize_handler_timer = 0;
6804
6805       do_presize_handler (tree_view);
6806     }
6807
6808   gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
6809 }
6810
6811 static gboolean
6812 scroll_sync_handler (GtkTreeView *tree_view)
6813 {
6814   if (tree_view->priv->height <= gtk_adjustment_get_page_size (tree_view->priv->vadjustment))
6815     gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), 0);
6816   else if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
6817     gtk_tree_view_top_row_to_dy (tree_view);
6818   else
6819     gtk_tree_view_dy_to_top_row (tree_view);
6820
6821   tree_view->priv->scroll_sync_timer = 0;
6822
6823   return FALSE;
6824 }
6825
6826 static void
6827 install_scroll_sync_handler (GtkTreeView *tree_view)
6828 {
6829   if (!gtk_widget_get_realized (GTK_WIDGET (tree_view)))
6830     return;
6831
6832   if (!tree_view->priv->scroll_sync_timer)
6833     {
6834       tree_view->priv->scroll_sync_timer =
6835         gdk_threads_add_idle_full (GTK_TREE_VIEW_PRIORITY_SCROLL_SYNC, (GSourceFunc) scroll_sync_handler, tree_view, NULL);
6836     }
6837 }
6838
6839 static void
6840 gtk_tree_view_set_top_row (GtkTreeView *tree_view,
6841                            GtkTreePath *path,
6842                            gint         offset)
6843 {
6844   gtk_tree_row_reference_free (tree_view->priv->top_row);
6845
6846   if (!path)
6847     {
6848       tree_view->priv->top_row = NULL;
6849       tree_view->priv->top_row_dy = 0;
6850     }
6851   else
6852     {
6853       tree_view->priv->top_row = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
6854       tree_view->priv->top_row_dy = offset;
6855     }
6856 }
6857
6858 /* Always call this iff dy is in the visible range.  If the tree is empty, then
6859  * it's set to be NULL, and top_row_dy is 0;
6860  */
6861 static void
6862 gtk_tree_view_dy_to_top_row (GtkTreeView *tree_view)
6863 {
6864   gint offset;
6865   GtkTreePath *path;
6866   GtkRBTree *tree;
6867   GtkRBNode *node;
6868
6869   if (tree_view->priv->tree == NULL)
6870     {
6871       gtk_tree_view_set_top_row (tree_view, NULL, 0);
6872     }
6873   else
6874     {
6875       offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
6876                                         tree_view->priv->dy,
6877                                         &tree, &node);
6878
6879       if (tree == NULL)
6880         {
6881           gtk_tree_view_set_top_row (tree_view, NULL, 0);
6882         }
6883       else
6884         {
6885           path = _gtk_tree_view_find_path (tree_view, tree, node);
6886           gtk_tree_view_set_top_row (tree_view, path, offset);
6887           gtk_tree_path_free (path);
6888         }
6889     }
6890 }
6891
6892 static void
6893 gtk_tree_view_top_row_to_dy (GtkTreeView *tree_view)
6894 {
6895   GtkTreePath *path;
6896   GtkRBTree *tree;
6897   GtkRBNode *node;
6898   int new_dy;
6899
6900   /* Avoid recursive calls */
6901   if (tree_view->priv->in_top_row_to_dy)
6902     return;
6903
6904   if (tree_view->priv->top_row)
6905     path = gtk_tree_row_reference_get_path (tree_view->priv->top_row);
6906   else
6907     path = NULL;
6908
6909   if (!path)
6910     tree = NULL;
6911   else
6912     _gtk_tree_view_find_node (tree_view, path, &tree, &node);
6913
6914   if (path)
6915     gtk_tree_path_free (path);
6916
6917   if (tree == NULL)
6918     {
6919       /* keep dy and set new toprow */
6920       gtk_tree_row_reference_free (tree_view->priv->top_row);
6921       tree_view->priv->top_row = NULL;
6922       tree_view->priv->top_row_dy = 0;
6923       /* DO NOT install the idle handler */
6924       gtk_tree_view_dy_to_top_row (tree_view);
6925       return;
6926     }
6927
6928   if (gtk_tree_view_get_row_height (tree_view, node)
6929       < tree_view->priv->top_row_dy)
6930     {
6931       /* new top row -- do NOT install the idle handler */
6932       gtk_tree_view_dy_to_top_row (tree_view);
6933       return;
6934     }
6935
6936   new_dy = _gtk_rbtree_node_find_offset (tree, node);
6937   new_dy += tree_view->priv->top_row_dy;
6938
6939   if (new_dy + gtk_adjustment_get_page_size (tree_view->priv->vadjustment) > tree_view->priv->height)
6940     new_dy = tree_view->priv->height - gtk_adjustment_get_page_size (tree_view->priv->vadjustment);
6941
6942   new_dy = MAX (0, new_dy);
6943
6944   tree_view->priv->in_top_row_to_dy = TRUE;
6945   gtk_adjustment_set_value (tree_view->priv->vadjustment, (gdouble)new_dy);
6946   tree_view->priv->in_top_row_to_dy = FALSE;
6947 }
6948
6949
6950 void
6951 _gtk_tree_view_install_mark_rows_col_dirty (GtkTreeView *tree_view,
6952                                             gboolean     install_handler)
6953 {
6954   tree_view->priv->mark_rows_col_dirty = TRUE;
6955
6956   if (install_handler)
6957     install_presize_handler (tree_view);
6958 }
6959
6960 /*
6961  * This function works synchronously (due to the while (validate_rows...)
6962  * loop).
6963  *
6964  * There was a check for column_type != GTK_TREE_VIEW_COLUMN_AUTOSIZE
6965  * here. You now need to check that yourself.
6966  */
6967 void
6968 _gtk_tree_view_column_autosize (GtkTreeView *tree_view,
6969                                 GtkTreeViewColumn *column)
6970 {
6971   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6972   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column));
6973
6974   _gtk_tree_view_column_cell_set_dirty (column, FALSE);
6975
6976   do_presize_handler (tree_view);
6977   while (validate_rows (tree_view));
6978
6979   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
6980 }
6981
6982 /* Drag-and-drop */
6983
6984 static void
6985 set_source_row (GdkDragContext *context,
6986                 GtkTreeModel   *model,
6987                 GtkTreePath    *source_row)
6988 {
6989   g_object_set_data_full (G_OBJECT (context),
6990                           I_("gtk-tree-view-source-row"),
6991                           source_row ? gtk_tree_row_reference_new (model, source_row) : NULL,
6992                           (GDestroyNotify) (source_row ? gtk_tree_row_reference_free : NULL));
6993 }
6994
6995 static GtkTreePath*
6996 get_source_row (GdkDragContext *context)
6997 {
6998   GtkTreeRowReference *ref =
6999     g_object_get_data (G_OBJECT (context), "gtk-tree-view-source-row");
7000
7001   if (ref)
7002     return gtk_tree_row_reference_get_path (ref);
7003   else
7004     return NULL;
7005 }
7006
7007 typedef struct
7008 {
7009   GtkTreeRowReference *dest_row;
7010   guint                path_down_mode   : 1;
7011   guint                empty_view_drop  : 1;
7012   guint                drop_append_mode : 1;
7013 }
7014 DestRow;
7015
7016 static void
7017 dest_row_free (gpointer data)
7018 {
7019   DestRow *dr = (DestRow *)data;
7020
7021   gtk_tree_row_reference_free (dr->dest_row);
7022   g_slice_free (DestRow, dr);
7023 }
7024
7025 static void
7026 set_dest_row (GdkDragContext *context,
7027               GtkTreeModel   *model,
7028               GtkTreePath    *dest_row,
7029               gboolean        path_down_mode,
7030               gboolean        empty_view_drop,
7031               gboolean        drop_append_mode)
7032 {
7033   DestRow *dr;
7034
7035   if (!dest_row)
7036     {
7037       g_object_set_data_full (G_OBJECT (context), I_("gtk-tree-view-dest-row"),
7038                               NULL, NULL);
7039       return;
7040     }
7041
7042   dr = g_slice_new (DestRow);
7043
7044   dr->dest_row = gtk_tree_row_reference_new (model, dest_row);
7045   dr->path_down_mode = path_down_mode != FALSE;
7046   dr->empty_view_drop = empty_view_drop != FALSE;
7047   dr->drop_append_mode = drop_append_mode != FALSE;
7048
7049   g_object_set_data_full (G_OBJECT (context), I_("gtk-tree-view-dest-row"),
7050                           dr, (GDestroyNotify) dest_row_free);
7051 }
7052
7053 static GtkTreePath*
7054 get_dest_row (GdkDragContext *context,
7055               gboolean       *path_down_mode)
7056 {
7057   DestRow *dr =
7058     g_object_get_data (G_OBJECT (context), "gtk-tree-view-dest-row");
7059
7060   if (dr)
7061     {
7062       GtkTreePath *path = NULL;
7063
7064       if (path_down_mode)
7065         *path_down_mode = dr->path_down_mode;
7066
7067       if (dr->dest_row)
7068         path = gtk_tree_row_reference_get_path (dr->dest_row);
7069       else if (dr->empty_view_drop)
7070         path = gtk_tree_path_new_from_indices (0, -1);
7071       else
7072         path = NULL;
7073
7074       if (path && dr->drop_append_mode)
7075         gtk_tree_path_next (path);
7076
7077       return path;
7078     }
7079   else
7080     return NULL;
7081 }
7082
7083 /* Get/set whether drag_motion requested the drag data and
7084  * drag_data_received should thus not actually insert the data,
7085  * since the data doesn't result from a drop.
7086  */
7087 static void
7088 set_status_pending (GdkDragContext *context,
7089                     GdkDragAction   suggested_action)
7090 {
7091   g_object_set_data (G_OBJECT (context),
7092                      I_("gtk-tree-view-status-pending"),
7093                      GINT_TO_POINTER (suggested_action));
7094 }
7095
7096 static GdkDragAction
7097 get_status_pending (GdkDragContext *context)
7098 {
7099   return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
7100                                              "gtk-tree-view-status-pending"));
7101 }
7102
7103 static TreeViewDragInfo*
7104 get_info (GtkTreeView *tree_view)
7105 {
7106   return g_object_get_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info");
7107 }
7108
7109 static void
7110 destroy_info (TreeViewDragInfo *di)
7111 {
7112   g_slice_free (TreeViewDragInfo, di);
7113 }
7114
7115 static TreeViewDragInfo*
7116 ensure_info (GtkTreeView *tree_view)
7117 {
7118   TreeViewDragInfo *di;
7119
7120   di = get_info (tree_view);
7121
7122   if (di == NULL)
7123     {
7124       di = g_slice_new0 (TreeViewDragInfo);
7125
7126       g_object_set_data_full (G_OBJECT (tree_view),
7127                               I_("gtk-tree-view-drag-info"),
7128                               di,
7129                               (GDestroyNotify) destroy_info);
7130     }
7131
7132   return di;
7133 }
7134
7135 static void
7136 remove_info (GtkTreeView *tree_view)
7137 {
7138   g_object_set_data (G_OBJECT (tree_view), I_("gtk-tree-view-drag-info"), NULL);
7139 }
7140
7141 #if 0
7142 static gint
7143 drag_scan_timeout (gpointer data)
7144 {
7145   GtkTreeView *tree_view;
7146   gint x, y;
7147   GdkModifierType state;
7148   GtkTreePath *path = NULL;
7149   GtkTreeViewColumn *column = NULL;
7150   GdkRectangle visible_rect;
7151
7152   GDK_THREADS_ENTER ();
7153
7154   tree_view = GTK_TREE_VIEW (data);
7155
7156   gdk_window_get_pointer (tree_view->priv->bin_window,
7157                           &x, &y, &state);
7158
7159   gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
7160
7161   /* See if we are near the edge. */
7162   if ((x - visible_rect.x) < SCROLL_EDGE_SIZE ||
7163       (visible_rect.x + visible_rect.width - x) < SCROLL_EDGE_SIZE ||
7164       (y - visible_rect.y) < SCROLL_EDGE_SIZE ||
7165       (visible_rect.y + visible_rect.height - y) < SCROLL_EDGE_SIZE)
7166     {
7167       gtk_tree_view_get_path_at_pos (tree_view,
7168                                      tree_view->priv->bin_window,
7169                                      x, y,
7170                                      &path,
7171                                      &column,
7172                                      NULL,
7173                                      NULL);
7174
7175       if (path != NULL)
7176         {
7177           gtk_tree_view_scroll_to_cell (tree_view,
7178                                         path,
7179                                         column,
7180                                         TRUE,
7181                                         0.5, 0.5);
7182
7183           gtk_tree_path_free (path);
7184         }
7185     }
7186
7187   GDK_THREADS_LEAVE ();
7188
7189   return TRUE;
7190 }
7191 #endif /* 0 */
7192
7193 static void
7194 add_scroll_timeout (GtkTreeView *tree_view)
7195 {
7196   if (tree_view->priv->scroll_timeout == 0)
7197     {
7198       tree_view->priv->scroll_timeout =
7199         gdk_threads_add_timeout (150, scroll_row_timeout, tree_view);
7200     }
7201 }
7202
7203 static void
7204 remove_scroll_timeout (GtkTreeView *tree_view)
7205 {
7206   if (tree_view->priv->scroll_timeout != 0)
7207     {
7208       g_source_remove (tree_view->priv->scroll_timeout);
7209       tree_view->priv->scroll_timeout = 0;
7210     }
7211 }
7212
7213 static gboolean
7214 check_model_dnd (GtkTreeModel *model,
7215                  GType         required_iface,
7216                  const gchar  *signal)
7217 {
7218   if (model == NULL || !G_TYPE_CHECK_INSTANCE_TYPE ((model), required_iface))
7219     {
7220       g_warning ("You must override the default '%s' handler "
7221                  "on GtkTreeView when using models that don't support "
7222                  "the %s interface and enabling drag-and-drop. The simplest way to do this "
7223                  "is to connect to '%s' and call "
7224                  "g_signal_stop_emission_by_name() in your signal handler to prevent "
7225                  "the default handler from running. Look at the source code "
7226                  "for the default handler in gtktreeview.c to get an idea what "
7227                  "your handler should do. (gtktreeview.c is in the GTK source "
7228                  "code.) If you're using GTK from a language other than C, "
7229                  "there may be a more natural way to override default handlers, e.g. via derivation.",
7230                  signal, g_type_name (required_iface), signal);
7231       return FALSE;
7232     }
7233   else
7234     return TRUE;
7235 }
7236
7237 static void
7238 remove_open_timeout (GtkTreeView *tree_view)
7239 {
7240   if (tree_view->priv->open_dest_timeout != 0)
7241     {
7242       g_source_remove (tree_view->priv->open_dest_timeout);
7243       tree_view->priv->open_dest_timeout = 0;
7244     }
7245 }
7246
7247
7248 static gint
7249 open_row_timeout (gpointer data)
7250 {
7251   GtkTreeView *tree_view = data;
7252   GtkTreePath *dest_path = NULL;
7253   GtkTreeViewDropPosition pos;
7254   gboolean result = FALSE;
7255
7256   gtk_tree_view_get_drag_dest_row (tree_view,
7257                                    &dest_path,
7258                                    &pos);
7259
7260   if (dest_path &&
7261       (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
7262        pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE))
7263     {
7264       gtk_tree_view_expand_row (tree_view, dest_path, FALSE);
7265       tree_view->priv->open_dest_timeout = 0;
7266
7267       gtk_tree_path_free (dest_path);
7268     }
7269   else
7270     {
7271       if (dest_path)
7272         gtk_tree_path_free (dest_path);
7273
7274       result = TRUE;
7275     }
7276
7277   return result;
7278 }
7279
7280 static gboolean
7281 scroll_row_timeout (gpointer data)
7282 {
7283   GtkTreeView *tree_view = data;
7284
7285   gtk_tree_view_vertical_autoscroll (tree_view);
7286
7287   if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
7288     gtk_tree_view_update_rubber_band (tree_view);
7289
7290   return TRUE;
7291 }
7292
7293 /* Returns TRUE if event should not be propagated to parent widgets */
7294 static gboolean
7295 set_destination_row (GtkTreeView    *tree_view,
7296                      GdkDragContext *context,
7297                      /* coordinates relative to the widget */
7298                      gint            x,
7299                      gint            y,
7300                      GdkDragAction  *suggested_action,
7301                      GdkAtom        *target)
7302 {
7303   GtkTreePath *path = NULL;
7304   GtkTreeViewDropPosition pos;
7305   GtkTreeViewDropPosition old_pos;
7306   TreeViewDragInfo *di;
7307   GtkWidget *widget;
7308   GtkTreePath *old_dest_path = NULL;
7309   gboolean can_drop = FALSE;
7310
7311   *suggested_action = 0;
7312   *target = GDK_NONE;
7313
7314   widget = GTK_WIDGET (tree_view);
7315
7316   di = get_info (tree_view);
7317
7318   if (di == NULL || y - gtk_tree_view_get_effective_header_height (tree_view) < 0)
7319     {
7320       /* someone unset us as a drag dest, note that if
7321        * we return FALSE drag_leave isn't called
7322        */
7323
7324       gtk_tree_view_set_drag_dest_row (tree_view,
7325                                        NULL,
7326                                        GTK_TREE_VIEW_DROP_BEFORE);
7327
7328       remove_scroll_timeout (GTK_TREE_VIEW (widget));
7329       remove_open_timeout (GTK_TREE_VIEW (widget));
7330
7331       return FALSE; /* no longer a drop site */
7332     }
7333
7334   *target = gtk_drag_dest_find_target (widget, context,
7335                                        gtk_drag_dest_get_target_list (widget));
7336   if (*target == GDK_NONE)
7337     {
7338       return FALSE;
7339     }
7340
7341   if (!gtk_tree_view_get_dest_row_at_pos (tree_view,
7342                                           x, y,
7343                                           &path,
7344                                           &pos))
7345     {
7346       gint n_children;
7347       GtkTreeModel *model;
7348
7349       remove_open_timeout (tree_view);
7350
7351       /* the row got dropped on empty space, let's setup a special case
7352        */
7353
7354       if (path)
7355         gtk_tree_path_free (path);
7356
7357       model = gtk_tree_view_get_model (tree_view);
7358
7359       n_children = gtk_tree_model_iter_n_children (model, NULL);
7360       if (n_children)
7361         {
7362           pos = GTK_TREE_VIEW_DROP_AFTER;
7363           path = gtk_tree_path_new_from_indices (n_children - 1, -1);
7364         }
7365       else
7366         {
7367           pos = GTK_TREE_VIEW_DROP_BEFORE;
7368           path = gtk_tree_path_new_from_indices (0, -1);
7369         }
7370
7371       can_drop = TRUE;
7372
7373       goto out;
7374     }
7375
7376   g_assert (path);
7377
7378   /* If we left the current row's "open" zone, unset the timeout for
7379    * opening the row
7380    */
7381   gtk_tree_view_get_drag_dest_row (tree_view,
7382                                    &old_dest_path,
7383                                    &old_pos);
7384
7385   if (old_dest_path &&
7386       (gtk_tree_path_compare (path, old_dest_path) != 0 ||
7387        !(pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
7388          pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)))
7389     remove_open_timeout (tree_view);
7390
7391   if (old_dest_path)
7392     gtk_tree_path_free (old_dest_path);
7393
7394   if (TRUE /* FIXME if the location droppable predicate */)
7395     {
7396       can_drop = TRUE;
7397     }
7398
7399 out:
7400   if (can_drop)
7401     {
7402       GtkWidget *source_widget;
7403
7404       *suggested_action = gdk_drag_context_get_suggested_action (context);
7405       source_widget = gtk_drag_get_source_widget (context);
7406
7407       if (source_widget == widget)
7408         {
7409           /* Default to MOVE, unless the user has
7410            * pressed ctrl or shift to affect available actions
7411            */
7412           if ((gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE) != 0)
7413             *suggested_action = GDK_ACTION_MOVE;
7414         }
7415
7416       gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
7417                                        path, pos);
7418     }
7419   else
7420     {
7421       /* can't drop here */
7422       remove_open_timeout (tree_view);
7423
7424       gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
7425                                        NULL,
7426                                        GTK_TREE_VIEW_DROP_BEFORE);
7427     }
7428
7429   if (path)
7430     gtk_tree_path_free (path);
7431
7432   return TRUE;
7433 }
7434
7435 static GtkTreePath*
7436 get_logical_dest_row (GtkTreeView *tree_view,
7437                       gboolean    *path_down_mode,
7438                       gboolean    *drop_append_mode)
7439 {
7440   /* adjust path to point to the row the drop goes in front of */
7441   GtkTreePath *path = NULL;
7442   GtkTreeViewDropPosition pos;
7443
7444   g_return_val_if_fail (path_down_mode != NULL, NULL);
7445   g_return_val_if_fail (drop_append_mode != NULL, NULL);
7446
7447   *path_down_mode = FALSE;
7448   *drop_append_mode = 0;
7449
7450   gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
7451
7452   if (path == NULL)
7453     return NULL;
7454
7455   if (pos == GTK_TREE_VIEW_DROP_BEFORE)
7456     ; /* do nothing */
7457   else if (pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE ||
7458            pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
7459     *path_down_mode = TRUE;
7460   else
7461     {
7462       GtkTreeIter iter;
7463       GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
7464
7465       g_assert (pos == GTK_TREE_VIEW_DROP_AFTER);
7466
7467       if (!gtk_tree_model_get_iter (model, &iter, path) ||
7468           !gtk_tree_model_iter_next (model, &iter))
7469         *drop_append_mode = 1;
7470       else
7471         {
7472           *drop_append_mode = 0;
7473           gtk_tree_path_next (path);
7474         }
7475     }
7476
7477   return path;
7478 }
7479
7480 static gboolean
7481 gtk_tree_view_maybe_begin_dragging_row (GtkTreeView      *tree_view,
7482                                         GdkEventMotion   *event)
7483 {
7484   GtkWidget *widget = GTK_WIDGET (tree_view);
7485   GdkDragContext *context;
7486   TreeViewDragInfo *di;
7487   GtkTreePath *path = NULL;
7488   gint button;
7489   gint cell_x, cell_y;
7490   GtkTreeModel *model;
7491   gboolean retval = FALSE;
7492
7493   di = get_info (tree_view);
7494
7495   if (di == NULL || !di->source_set)
7496     goto out;
7497
7498   if (tree_view->priv->pressed_button < 0)
7499     goto out;
7500
7501   if (!gtk_drag_check_threshold (widget,
7502                                  tree_view->priv->press_start_x,
7503                                  tree_view->priv->press_start_y,
7504                                  event->x, event->y))
7505     goto out;
7506
7507   model = gtk_tree_view_get_model (tree_view);
7508
7509   if (model == NULL)
7510     goto out;
7511
7512   button = tree_view->priv->pressed_button;
7513   tree_view->priv->pressed_button = -1;
7514
7515   gtk_tree_view_get_path_at_pos (tree_view,
7516                                  tree_view->priv->press_start_x,
7517                                  tree_view->priv->press_start_y,
7518                                  &path,
7519                                  NULL,
7520                                  &cell_x,
7521                                  &cell_y);
7522
7523   if (path == NULL)
7524     goto out;
7525
7526   if (!GTK_IS_TREE_DRAG_SOURCE (model) ||
7527       !gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (model),
7528                                            path))
7529     goto out;
7530
7531   if (!(GDK_BUTTON1_MASK << (button - 1) & di->start_button_mask))
7532     goto out;
7533
7534   /* Now we can begin the drag */
7535
7536   retval = TRUE;
7537
7538   context = gtk_drag_begin (widget,
7539                             gtk_drag_source_get_target_list (widget),
7540                             di->source_actions,
7541                             button,
7542                             (GdkEvent*)event);
7543
7544   set_source_row (context, model, path);
7545
7546  out:
7547   if (path)
7548     gtk_tree_path_free (path);
7549
7550   return retval;
7551 }
7552
7553
7554 static void
7555 gtk_tree_view_drag_begin (GtkWidget      *widget,
7556                           GdkDragContext *context)
7557 {
7558   GtkTreeView *tree_view;
7559   GtkTreePath *path = NULL;
7560   gint cell_x, cell_y;
7561   cairo_surface_t *row_pix;
7562   TreeViewDragInfo *di;
7563
7564   tree_view = GTK_TREE_VIEW (widget);
7565
7566   /* if the user uses a custom DND source impl, we don't set the icon here */
7567   di = get_info (tree_view);
7568
7569   if (di == NULL || !di->source_set)
7570     return;
7571
7572   gtk_tree_view_get_path_at_pos (tree_view,
7573                                  tree_view->priv->press_start_x,
7574                                  tree_view->priv->press_start_y,
7575                                  &path,
7576                                  NULL,
7577                                  &cell_x,
7578                                  &cell_y);
7579
7580   g_return_if_fail (path != NULL);
7581
7582   row_pix = gtk_tree_view_create_row_drag_icon (tree_view,
7583                                                 path);
7584   cairo_surface_set_device_offset (row_pix,
7585                                    /* the + 1 is for the black border in the icon */
7586                                    - (tree_view->priv->press_start_x + 1),
7587                                    - (cell_y + 1));
7588
7589   gtk_drag_set_icon_surface (context, row_pix);
7590
7591   cairo_surface_destroy (row_pix);
7592   gtk_tree_path_free (path);
7593 }
7594
7595 static void
7596 gtk_tree_view_drag_end (GtkWidget      *widget,
7597                         GdkDragContext *context)
7598 {
7599   /* do nothing */
7600 }
7601
7602 /* Default signal implementations for the drag signals */
7603 static void
7604 gtk_tree_view_drag_data_get (GtkWidget        *widget,
7605                              GdkDragContext   *context,
7606                              GtkSelectionData *selection_data,
7607                              guint             info,
7608                              guint             time)
7609 {
7610   GtkTreeView *tree_view;
7611   GtkTreeModel *model;
7612   TreeViewDragInfo *di;
7613   GtkTreePath *source_row;
7614
7615   tree_view = GTK_TREE_VIEW (widget);
7616
7617   model = gtk_tree_view_get_model (tree_view);
7618
7619   if (model == NULL)
7620     return;
7621
7622   di = get_info (GTK_TREE_VIEW (widget));
7623
7624   if (di == NULL)
7625     return;
7626
7627   source_row = get_source_row (context);
7628
7629   if (source_row == NULL)
7630     return;
7631
7632   /* We can implement the GTK_TREE_MODEL_ROW target generically for
7633    * any model; for DragSource models there are some other targets
7634    * we also support.
7635    */
7636
7637   if (GTK_IS_TREE_DRAG_SOURCE (model) &&
7638       gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model),
7639                                           source_row,
7640                                           selection_data))
7641     goto done;
7642
7643   /* If drag_data_get does nothing, try providing row data. */
7644   if (gtk_selection_data_get_target (selection_data) == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
7645     {
7646       gtk_tree_set_row_drag_data (selection_data,
7647                                   model,
7648                                   source_row);
7649     }
7650
7651  done:
7652   gtk_tree_path_free (source_row);
7653 }
7654
7655
7656 static void
7657 gtk_tree_view_drag_data_delete (GtkWidget      *widget,
7658                                 GdkDragContext *context)
7659 {
7660   TreeViewDragInfo *di;
7661   GtkTreeModel *model;
7662   GtkTreeView *tree_view;
7663   GtkTreePath *source_row;
7664
7665   tree_view = GTK_TREE_VIEW (widget);
7666   model = gtk_tree_view_get_model (tree_view);
7667
7668   if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_SOURCE, "drag_data_delete"))
7669     return;
7670
7671   di = get_info (tree_view);
7672
7673   if (di == NULL)
7674     return;
7675
7676   source_row = get_source_row (context);
7677
7678   if (source_row == NULL)
7679     return;
7680
7681   gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (model),
7682                                          source_row);
7683
7684   gtk_tree_path_free (source_row);
7685
7686   set_source_row (context, NULL, NULL);
7687 }
7688
7689 static void
7690 gtk_tree_view_drag_leave (GtkWidget      *widget,
7691                           GdkDragContext *context,
7692                           guint             time)
7693 {
7694   /* unset any highlight row */
7695   gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
7696                                    NULL,
7697                                    GTK_TREE_VIEW_DROP_BEFORE);
7698
7699   remove_scroll_timeout (GTK_TREE_VIEW (widget));
7700   remove_open_timeout (GTK_TREE_VIEW (widget));
7701 }
7702
7703
7704 static gboolean
7705 gtk_tree_view_drag_motion (GtkWidget        *widget,
7706                            GdkDragContext   *context,
7707                            /* coordinates relative to the widget */
7708                            gint              x,
7709                            gint              y,
7710                            guint             time)
7711 {
7712   gboolean empty;
7713   GtkTreePath *path = NULL;
7714   GtkTreeViewDropPosition pos;
7715   GtkTreeView *tree_view;
7716   GdkDragAction suggested_action = 0;
7717   GdkAtom target;
7718
7719   tree_view = GTK_TREE_VIEW (widget);
7720
7721   if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
7722     return FALSE;
7723
7724   gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
7725
7726   /* we only know this *after* set_desination_row */
7727   empty = tree_view->priv->empty_view_drop;
7728
7729   if (path == NULL && !empty)
7730     {
7731       /* Can't drop here. */
7732       gdk_drag_status (context, 0, time);
7733     }
7734   else
7735     {
7736       if (tree_view->priv->open_dest_timeout == 0 &&
7737           (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
7738            pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE))
7739         {
7740           tree_view->priv->open_dest_timeout =
7741             gdk_threads_add_timeout (AUTO_EXPAND_TIMEOUT, open_row_timeout, tree_view);
7742         }
7743       else
7744         {
7745           add_scroll_timeout (tree_view);
7746         }
7747
7748       if (target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
7749         {
7750           /* Request data so we can use the source row when
7751            * determining whether to accept the drop
7752            */
7753           set_status_pending (context, suggested_action);
7754           gtk_drag_get_data (widget, context, target, time);
7755         }
7756       else
7757         {
7758           set_status_pending (context, 0);
7759           gdk_drag_status (context, suggested_action, time);
7760         }
7761     }
7762
7763   if (path)
7764     gtk_tree_path_free (path);
7765
7766   return TRUE;
7767 }
7768
7769
7770 static gboolean
7771 gtk_tree_view_drag_drop (GtkWidget        *widget,
7772                          GdkDragContext   *context,
7773                          /* coordinates relative to the widget */
7774                          gint              x,
7775                          gint              y,
7776                          guint             time)
7777 {
7778   GtkTreeView *tree_view;
7779   GtkTreePath *path;
7780   GdkDragAction suggested_action = 0;
7781   GdkAtom target = GDK_NONE;
7782   TreeViewDragInfo *di;
7783   GtkTreeModel *model;
7784   gboolean path_down_mode;
7785   gboolean drop_append_mode;
7786
7787   tree_view = GTK_TREE_VIEW (widget);
7788
7789   model = gtk_tree_view_get_model (tree_view);
7790
7791   remove_scroll_timeout (GTK_TREE_VIEW (widget));
7792   remove_open_timeout (GTK_TREE_VIEW (widget));
7793
7794   di = get_info (tree_view);
7795
7796   if (di == NULL)
7797     return FALSE;
7798
7799   if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_drop"))
7800     return FALSE;
7801
7802   if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
7803     return FALSE;
7804
7805   path = get_logical_dest_row (tree_view, &path_down_mode, &drop_append_mode);
7806
7807   if (target != GDK_NONE && path != NULL)
7808     {
7809       /* in case a motion had requested drag data, change things so we
7810        * treat drag data receives as a drop.
7811        */
7812       set_status_pending (context, 0);
7813       set_dest_row (context, model, path,
7814                     path_down_mode, tree_view->priv->empty_view_drop,
7815                     drop_append_mode);
7816     }
7817
7818   if (path)
7819     gtk_tree_path_free (path);
7820
7821   /* Unset this thing */
7822   gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
7823                                    NULL,
7824                                    GTK_TREE_VIEW_DROP_BEFORE);
7825
7826   if (target != GDK_NONE)
7827     {
7828       gtk_drag_get_data (widget, context, target, time);
7829       return TRUE;
7830     }
7831   else
7832     return FALSE;
7833 }
7834
7835 static void
7836 gtk_tree_view_drag_data_received (GtkWidget        *widget,
7837                                   GdkDragContext   *context,
7838                                   /* coordinates relative to the widget */
7839                                   gint              x,
7840                                   gint              y,
7841                                   GtkSelectionData *selection_data,
7842                                   guint             info,
7843                                   guint             time)
7844 {
7845   GtkTreePath *path;
7846   TreeViewDragInfo *di;
7847   gboolean accepted = FALSE;
7848   GtkTreeModel *model;
7849   GtkTreeView *tree_view;
7850   GtkTreePath *dest_row;
7851   GdkDragAction suggested_action;
7852   gboolean path_down_mode;
7853   gboolean drop_append_mode;
7854
7855   tree_view = GTK_TREE_VIEW (widget);
7856
7857   model = gtk_tree_view_get_model (tree_view);
7858
7859   if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_data_received"))
7860     return;
7861
7862   di = get_info (tree_view);
7863
7864   if (di == NULL)
7865     return;
7866
7867   suggested_action = get_status_pending (context);
7868
7869   if (suggested_action)
7870     {
7871       /* We are getting this data due to a request in drag_motion,
7872        * rather than due to a request in drag_drop, so we are just
7873        * supposed to call drag_status, not actually paste in the
7874        * data.
7875        */
7876       path = get_logical_dest_row (tree_view, &path_down_mode,
7877                                    &drop_append_mode);
7878
7879       if (path == NULL)
7880         suggested_action = 0;
7881       else if (path_down_mode)
7882         gtk_tree_path_down (path);
7883
7884       if (suggested_action)
7885         {
7886           if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
7887                                                      path,
7888                                                      selection_data))
7889             {
7890               if (path_down_mode)
7891                 {
7892                   path_down_mode = FALSE;
7893                   gtk_tree_path_up (path);
7894
7895                   if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
7896                                                              path,
7897                                                              selection_data))
7898                     suggested_action = 0;
7899                 }
7900               else
7901                 suggested_action = 0;
7902             }
7903         }
7904
7905       gdk_drag_status (context, suggested_action, time);
7906
7907       if (path)
7908         gtk_tree_path_free (path);
7909
7910       /* If you can't drop, remove user drop indicator until the next motion */
7911       if (suggested_action == 0)
7912         gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
7913                                          NULL,
7914                                          GTK_TREE_VIEW_DROP_BEFORE);
7915
7916       return;
7917     }
7918
7919   dest_row = get_dest_row (context, &path_down_mode);
7920
7921   if (dest_row == NULL)
7922     return;
7923
7924   if (gtk_selection_data_get_length (selection_data) >= 0)
7925     {
7926       if (path_down_mode)
7927         {
7928           gtk_tree_path_down (dest_row);
7929           if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
7930                                                      dest_row, selection_data))
7931             gtk_tree_path_up (dest_row);
7932         }
7933     }
7934
7935   if (gtk_selection_data_get_length (selection_data) >= 0)
7936     {
7937       if (gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model),
7938                                                  dest_row,
7939                                                  selection_data))
7940         accepted = TRUE;
7941     }
7942
7943   gtk_drag_finish (context,
7944                    accepted,
7945                    (gdk_drag_context_get_selected_action (context) == GDK_ACTION_MOVE),
7946                    time);
7947
7948   if (gtk_tree_path_get_depth (dest_row) == 1
7949       && gtk_tree_path_get_indices (dest_row)[0] == 0)
7950     {
7951       /* special special case drag to "0", scroll to first item */
7952       if (!tree_view->priv->scroll_to_path)
7953         gtk_tree_view_scroll_to_cell (tree_view, dest_row, NULL, FALSE, 0.0, 0.0);
7954     }
7955
7956   gtk_tree_path_free (dest_row);
7957
7958   /* drop dest_row */
7959   set_dest_row (context, NULL, NULL, FALSE, FALSE, FALSE);
7960 }
7961
7962
7963
7964 /* GtkContainer Methods
7965  */
7966
7967
7968 static void
7969 gtk_tree_view_remove (GtkContainer *container,
7970                       GtkWidget    *widget)
7971 {
7972   GtkTreeView *tree_view = GTK_TREE_VIEW (container);
7973   GtkTreeViewChild *child = NULL;
7974   GList *tmp_list;
7975
7976   tmp_list = tree_view->priv->children;
7977   while (tmp_list)
7978     {
7979       child = tmp_list->data;
7980       if (child->widget == widget)
7981         {
7982           gtk_widget_unparent (widget);
7983
7984           tree_view->priv->children = g_list_remove_link (tree_view->priv->children, tmp_list);
7985           g_list_free_1 (tmp_list);
7986           g_slice_free (GtkTreeViewChild, child);
7987           return;
7988         }
7989
7990       tmp_list = tmp_list->next;
7991     }
7992
7993   tmp_list = tree_view->priv->columns;
7994
7995   while (tmp_list)
7996     {
7997       GtkTreeViewColumn *column;
7998       GtkWidget         *button;
7999
8000       column = tmp_list->data;
8001       button = gtk_tree_view_column_get_button (column);
8002
8003       if (button == widget)
8004         {
8005           gtk_widget_unparent (widget);
8006           return;
8007         }
8008       tmp_list = tmp_list->next;
8009     }
8010 }
8011
8012 static void
8013 gtk_tree_view_forall (GtkContainer *container,
8014                       gboolean      include_internals,
8015                       GtkCallback   callback,
8016                       gpointer      callback_data)
8017 {
8018   GtkTreeView *tree_view = GTK_TREE_VIEW (container);
8019   GtkTreeViewChild *child = NULL;
8020   GtkTreeViewColumn *column;
8021   GtkWidget *button;
8022   GList *tmp_list;
8023
8024   tmp_list = tree_view->priv->children;
8025   while (tmp_list)
8026     {
8027       child = tmp_list->data;
8028       tmp_list = tmp_list->next;
8029
8030       (* callback) (child->widget, callback_data);
8031     }
8032   if (include_internals == FALSE)
8033     return;
8034
8035   for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
8036     {
8037       column = tmp_list->data;
8038       button = gtk_tree_view_column_get_button (column);
8039
8040       if (button)
8041         (* callback) (button, callback_data);
8042     }
8043 }
8044
8045 /* Returns TRUE is any of the columns contains a cell that can-focus.
8046  * If this is not the case, a column-spanning focus rectangle will be
8047  * drawn.
8048  */
8049 static gboolean
8050 gtk_tree_view_has_can_focus_cell (GtkTreeView *tree_view)
8051 {
8052   GList *list;
8053
8054   for (list = tree_view->priv->columns; list; list = list->next)
8055     {
8056       GtkTreeViewColumn *column = list->data;
8057
8058       if (!gtk_tree_view_column_get_visible (column))
8059         continue;
8060       if (gtk_cell_area_is_activatable (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (column))))
8061         return TRUE;
8062     }
8063
8064   return FALSE;
8065 }
8066
8067 static void
8068 column_sizing_notify (GObject    *object,
8069                       GParamSpec *pspec,
8070                       gpointer    data)
8071 {
8072   GtkTreeViewColumn *c = GTK_TREE_VIEW_COLUMN (object);
8073
8074   if (gtk_tree_view_column_get_sizing (c) != GTK_TREE_VIEW_COLUMN_FIXED)
8075     /* disable fixed height mode */
8076     g_object_set (data, "fixed-height-mode", FALSE, NULL);
8077 }
8078
8079 /**
8080  * gtk_tree_view_set_fixed_height_mode:
8081  * @tree_view: a #GtkTreeView 
8082  * @enable: %TRUE to enable fixed height mode
8083  * 
8084  * Enables or disables the fixed height mode of @tree_view. 
8085  * Fixed height mode speeds up #GtkTreeView by assuming that all 
8086  * rows have the same height. 
8087  * Only enable this option if all rows are the same height and all
8088  * columns are of type %GTK_TREE_VIEW_COLUMN_FIXED.
8089  *
8090  * Since: 2.6 
8091  **/
8092 void
8093 gtk_tree_view_set_fixed_height_mode (GtkTreeView *tree_view,
8094                                      gboolean     enable)
8095 {
8096   GList *l;
8097   
8098   enable = enable != FALSE;
8099
8100   if (enable == tree_view->priv->fixed_height_mode)
8101     return;
8102
8103   if (!enable)
8104     {
8105       tree_view->priv->fixed_height_mode = 0;
8106       tree_view->priv->fixed_height = -1;
8107
8108       /* force a revalidation */
8109       install_presize_handler (tree_view);
8110     }
8111   else 
8112     {
8113       /* make sure all columns are of type FIXED */
8114       for (l = tree_view->priv->columns; l; l = l->next)
8115         {
8116           GtkTreeViewColumn *c = l->data;
8117           
8118           g_return_if_fail (gtk_tree_view_column_get_sizing (c) == GTK_TREE_VIEW_COLUMN_FIXED);
8119         }
8120       
8121       /* yes, we really have to do this is in a separate loop */
8122       for (l = tree_view->priv->columns; l; l = l->next)
8123         g_signal_connect (l->data, "notify::sizing",
8124                           G_CALLBACK (column_sizing_notify), tree_view);
8125       
8126       tree_view->priv->fixed_height_mode = 1;
8127       tree_view->priv->fixed_height = -1;
8128       
8129       if (tree_view->priv->tree)
8130         initialize_fixed_height_mode (tree_view);
8131     }
8132
8133   g_object_notify (G_OBJECT (tree_view), "fixed-height-mode");
8134 }
8135
8136 /**
8137  * gtk_tree_view_get_fixed_height_mode:
8138  * @tree_view: a #GtkTreeView
8139  * 
8140  * Returns whether fixed height mode is turned on for @tree_view.
8141  * 
8142  * Return value: %TRUE if @tree_view is in fixed height mode
8143  * 
8144  * Since: 2.6
8145  **/
8146 gboolean
8147 gtk_tree_view_get_fixed_height_mode (GtkTreeView *tree_view)
8148 {
8149   return tree_view->priv->fixed_height_mode;
8150 }
8151
8152 /* Returns TRUE if the focus is within the headers, after the focus operation is
8153  * done
8154  */
8155 static gboolean
8156 gtk_tree_view_header_focus (GtkTreeView      *tree_view,
8157                             GtkDirectionType  dir,
8158                             gboolean          clamp_column_visible)
8159 {
8160   GtkTreeViewColumn *column;
8161   GtkWidget *focus_child;
8162   GtkWidget *button;
8163   GList *last_column, *first_column;
8164   GList *tmp_list;
8165   gboolean rtl;
8166
8167   if (! tree_view->priv->headers_visible)
8168     return FALSE;
8169
8170   focus_child = gtk_container_get_focus_child (GTK_CONTAINER (tree_view));
8171
8172   first_column = tree_view->priv->columns;
8173   while (first_column)
8174     {
8175       column = GTK_TREE_VIEW_COLUMN (first_column->data);
8176       button = gtk_tree_view_column_get_button (column);
8177
8178       if (gtk_widget_get_can_focus (button) &&
8179           gtk_tree_view_column_get_visible (column) &&
8180           (gtk_tree_view_column_get_clickable (column) ||
8181            gtk_tree_view_column_get_reorderable (column)))
8182         break;
8183       first_column = first_column->next;
8184     }
8185
8186   /* No headers are visible, or are focusable.  We can't focus in or out.
8187    */
8188   if (first_column == NULL)
8189     return FALSE;
8190
8191   last_column = g_list_last (tree_view->priv->columns);
8192   while (last_column)
8193     {
8194       column = GTK_TREE_VIEW_COLUMN (last_column->data);
8195       button = gtk_tree_view_column_get_button (column);
8196
8197       if (gtk_widget_get_can_focus (button) &&
8198           gtk_tree_view_column_get_visible (column) &&
8199           (gtk_tree_view_column_get_clickable (column) ||
8200            gtk_tree_view_column_get_reorderable (column)))
8201         break;
8202       last_column = last_column->prev;
8203     }
8204
8205
8206   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
8207
8208   switch (dir)
8209     {
8210     case GTK_DIR_TAB_BACKWARD:
8211     case GTK_DIR_TAB_FORWARD:
8212     case GTK_DIR_UP:
8213     case GTK_DIR_DOWN:
8214       if (focus_child == NULL)
8215         {
8216           if (tree_view->priv->focus_column != NULL)
8217             button = gtk_tree_view_column_get_button (tree_view->priv->focus_column);
8218           else 
8219             button = NULL;
8220
8221           if (button && gtk_widget_get_can_focus (button))
8222             focus_child = button;
8223           else
8224             focus_child = gtk_tree_view_column_get_button (GTK_TREE_VIEW_COLUMN (first_column->data));
8225
8226           gtk_widget_grab_focus (focus_child);
8227           break;
8228         }
8229       return FALSE;
8230
8231     case GTK_DIR_LEFT:
8232     case GTK_DIR_RIGHT:
8233       if (focus_child == NULL)
8234         {
8235           if (tree_view->priv->focus_column != NULL)
8236             focus_child = gtk_tree_view_column_get_button (tree_view->priv->focus_column);
8237           else if (dir == GTK_DIR_LEFT)
8238             focus_child = gtk_tree_view_column_get_button (GTK_TREE_VIEW_COLUMN (last_column->data));
8239           else
8240             focus_child = gtk_tree_view_column_get_button (GTK_TREE_VIEW_COLUMN (first_column->data));
8241
8242           gtk_widget_grab_focus (focus_child);
8243           break;
8244         }
8245
8246       if (gtk_widget_child_focus (focus_child, dir))
8247         {
8248           /* The focus moves inside the button. */
8249           /* This is probably a great example of bad UI */
8250           break;
8251         }
8252
8253       /* We need to move the focus among the row of buttons. */
8254       for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
8255         if (gtk_tree_view_column_get_button (GTK_TREE_VIEW_COLUMN (tmp_list->data)) == focus_child)
8256           break;
8257
8258       if ((tmp_list == first_column && dir == (rtl ? GTK_DIR_RIGHT : GTK_DIR_LEFT))
8259           || (tmp_list == last_column && dir == (rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT)))
8260         {
8261           gtk_widget_error_bell (GTK_WIDGET (tree_view));
8262           break;
8263         }
8264
8265       while (tmp_list)
8266         {
8267           GtkTreeViewColumn *column;
8268           GtkWidget         *button;
8269
8270           if (dir == (rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT))
8271             tmp_list = tmp_list->next;
8272           else
8273             tmp_list = tmp_list->prev;
8274
8275           if (tmp_list == NULL)
8276             {
8277               g_warning ("Internal button not found");
8278               break;
8279             }
8280           column = tmp_list->data;
8281           button = gtk_tree_view_column_get_button (column);
8282           if (button &&
8283               gtk_tree_view_column_get_visible (column) &&
8284               gtk_widget_get_can_focus (button))
8285             {
8286               focus_child = button;
8287               gtk_widget_grab_focus (button);
8288               break;
8289             }
8290         }
8291       break;
8292     default:
8293       g_assert_not_reached ();
8294       break;
8295     }
8296
8297   /* if focus child is non-null, we assume it's been set to the current focus child
8298    */
8299   if (focus_child)
8300     {
8301       for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
8302         if (gtk_tree_view_column_get_button (GTK_TREE_VIEW_COLUMN (tmp_list->data)) == focus_child)
8303           {
8304             tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
8305             break;
8306           }
8307
8308       if (clamp_column_visible)
8309         {
8310           gtk_tree_view_clamp_column_visible (tree_view,
8311                                               tree_view->priv->focus_column,
8312                                               FALSE);
8313         }
8314     }
8315
8316   return (focus_child != NULL);
8317 }
8318
8319 /* This function returns in 'path' the first focusable path, if the given path
8320  * is already focusable, it's the returned one.
8321  */
8322 static gboolean
8323 search_first_focusable_path (GtkTreeView  *tree_view,
8324                              GtkTreePath **path,
8325                              gboolean      search_forward,
8326                              GtkRBTree   **new_tree,
8327                              GtkRBNode   **new_node)
8328 {
8329   GtkRBTree *tree = NULL;
8330   GtkRBNode *node = NULL;
8331
8332   if (!path || !*path)
8333     return FALSE;
8334
8335   _gtk_tree_view_find_node (tree_view, *path, &tree, &node);
8336
8337   if (!tree || !node)
8338     return FALSE;
8339
8340   while (node && row_is_separator (tree_view, NULL, *path))
8341     {
8342       if (search_forward)
8343         _gtk_rbtree_next_full (tree, node, &tree, &node);
8344       else
8345         _gtk_rbtree_prev_full (tree, node, &tree, &node);
8346
8347       if (*path)
8348         gtk_tree_path_free (*path);
8349
8350       if (node)
8351         *path = _gtk_tree_view_find_path (tree_view, tree, node);
8352       else
8353         *path = NULL;
8354     }
8355
8356   if (new_tree)
8357     *new_tree = tree;
8358
8359   if (new_node)
8360     *new_node = node;
8361
8362   return (*path != NULL);
8363 }
8364
8365 static gint
8366 gtk_tree_view_focus (GtkWidget        *widget,
8367                      GtkDirectionType  direction)
8368 {
8369   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
8370   GtkContainer *container = GTK_CONTAINER (widget);
8371   GtkWidget *focus_child;
8372
8373   if (!gtk_widget_is_sensitive (widget) || !gtk_widget_get_can_focus (widget))
8374     return FALSE;
8375
8376   focus_child = gtk_container_get_focus_child (container);
8377
8378   gtk_tree_view_stop_editing (GTK_TREE_VIEW (widget), FALSE);
8379   /* Case 1.  Headers currently have focus. */
8380   if (focus_child)
8381     {
8382       switch (direction)
8383         {
8384         case GTK_DIR_LEFT:
8385         case GTK_DIR_RIGHT:
8386           gtk_tree_view_header_focus (tree_view, direction, TRUE);
8387           return TRUE;
8388         case GTK_DIR_TAB_BACKWARD:
8389         case GTK_DIR_UP:
8390           return FALSE;
8391         case GTK_DIR_TAB_FORWARD:
8392         case GTK_DIR_DOWN:
8393           gtk_widget_grab_focus (widget);
8394           return TRUE;
8395         default:
8396           g_assert_not_reached ();
8397           return FALSE;
8398         }
8399     }
8400
8401   /* Case 2. We don't have focus at all. */
8402   if (!gtk_widget_has_focus (widget))
8403     {
8404       gtk_widget_grab_focus (widget);
8405       return TRUE;
8406     }
8407
8408   /* Case 3. We have focus already. */
8409   if (direction == GTK_DIR_TAB_BACKWARD)
8410     return (gtk_tree_view_header_focus (tree_view, direction, FALSE));
8411   else if (direction == GTK_DIR_TAB_FORWARD)
8412     return FALSE;
8413
8414   /* Other directions caught by the keybindings */
8415   gtk_widget_grab_focus (widget);
8416   return TRUE;
8417 }
8418
8419 static void
8420 gtk_tree_view_grab_focus (GtkWidget *widget)
8421 {
8422   GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->grab_focus (widget);
8423
8424   gtk_tree_view_focus_to_cursor (GTK_TREE_VIEW (widget));
8425 }
8426
8427 static void
8428 gtk_tree_view_style_updated (GtkWidget *widget)
8429 {
8430   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
8431   GList *list;
8432   GtkTreeViewColumn *column;
8433
8434   GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->style_updated (widget);
8435
8436   if (gtk_widget_get_realized (widget))
8437     {
8438       GtkStyleContext *context;
8439
8440       context = gtk_widget_get_style_context (widget);
8441
8442       gtk_style_context_save (context);
8443       gtk_style_context_add_class (context, GTK_STYLE_CLASS_VIEW);
8444       gtk_style_context_set_background (context, tree_view->priv->bin_window);
8445       gtk_style_context_restore (context);
8446
8447       gtk_style_context_set_background (context, tree_view->priv->header_window);
8448
8449       gtk_tree_view_set_grid_lines (tree_view, tree_view->priv->grid_lines);
8450       gtk_tree_view_set_enable_tree_lines (tree_view, tree_view->priv->tree_lines_enabled);
8451     }
8452
8453   gtk_widget_style_get (widget,
8454                         "expander-size", &tree_view->priv->expander_size,
8455                         NULL);
8456   tree_view->priv->expander_size += EXPANDER_EXTRA_PADDING;
8457
8458   for (list = tree_view->priv->columns; list; list = list->next)
8459     {
8460       column = list->data;
8461       _gtk_tree_view_column_cell_set_dirty (column, TRUE);
8462     }
8463
8464   tree_view->priv->fixed_height = -1;
8465   _gtk_rbtree_mark_invalid (tree_view->priv->tree);
8466
8467   gtk_widget_queue_resize (widget);
8468 }
8469
8470
8471 static void
8472 gtk_tree_view_set_focus_child (GtkContainer *container,
8473                                GtkWidget    *child)
8474 {
8475   GtkTreeView *tree_view = GTK_TREE_VIEW (container);
8476   GList *list;
8477
8478   for (list = tree_view->priv->columns; list; list = list->next)
8479     {
8480       if (gtk_tree_view_column_get_button (GTK_TREE_VIEW_COLUMN (list->data)) == child)
8481         {
8482           tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (list->data);
8483           break;
8484         }
8485     }
8486
8487   GTK_CONTAINER_CLASS (gtk_tree_view_parent_class)->set_focus_child (container, child);
8488 }
8489
8490 static GtkWidgetPath *
8491 gtk_tree_view_get_path_for_child (GtkContainer *container,
8492                                   GtkWidget    *child)
8493 {
8494   GtkTreeView *tree_view = GTK_TREE_VIEW (container);
8495   GtkWidgetPath *path;
8496   gboolean rtl;
8497   GList *list;
8498   gint n_col = 0;
8499
8500   path = GTK_CONTAINER_CLASS (gtk_tree_view_parent_class)->get_path_for_child (container, child);
8501   rtl = (gtk_widget_get_direction (GTK_WIDGET (container)) == GTK_TEXT_DIR_RTL);
8502
8503   for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
8504        list;
8505        list = (rtl ? list->prev : list->next))
8506     {
8507       GtkTreeViewColumn *column = list->data;
8508       GtkRegionFlags flags = 0;
8509
8510       if (!gtk_tree_view_column_get_visible (column))
8511         continue;
8512
8513       n_col++;
8514
8515       if (gtk_tree_view_column_get_widget (column) != child &&
8516           gtk_tree_view_column_get_button (column) != child)
8517         continue;
8518
8519       if ((n_col % 2) == 0)
8520         flags |= GTK_REGION_EVEN;
8521       else
8522         flags |= GTK_REGION_ODD;
8523
8524       if (n_col == 1)
8525         flags |= GTK_REGION_FIRST;
8526
8527       if ((rtl && !list->prev) ||
8528           (!rtl && !list->next))
8529         flags |= GTK_REGION_LAST;
8530
8531       gtk_widget_path_iter_add_region (path, -1, GTK_STYLE_REGION_COLUMN_HEADER, flags);
8532       break;
8533     }
8534
8535   gtk_widget_path_append_for_widget (path, child);
8536
8537   return path;
8538 }
8539
8540 static gboolean
8541 gtk_tree_view_real_move_cursor (GtkTreeView       *tree_view,
8542                                 GtkMovementStep    step,
8543                                 gint               count)
8544 {
8545   GdkModifierType state;
8546
8547   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
8548   g_return_val_if_fail (step == GTK_MOVEMENT_LOGICAL_POSITIONS ||
8549                         step == GTK_MOVEMENT_VISUAL_POSITIONS ||
8550                         step == GTK_MOVEMENT_DISPLAY_LINES ||
8551                         step == GTK_MOVEMENT_PAGES ||
8552                         step == GTK_MOVEMENT_BUFFER_ENDS, FALSE);
8553
8554   if (tree_view->priv->tree == NULL)
8555     return FALSE;
8556   if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
8557     return FALSE;
8558
8559   gtk_tree_view_stop_editing (tree_view, FALSE);
8560   tree_view->priv->draw_keyfocus = TRUE;
8561   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
8562
8563   if (gtk_get_current_event_state (&state))
8564     {
8565       if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
8566         tree_view->priv->ctrl_pressed = TRUE;
8567       if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
8568         tree_view->priv->shift_pressed = TRUE;
8569     }
8570   /* else we assume not pressed */
8571
8572   switch (step)
8573     {
8574       /* currently we make no distinction.  When we go bi-di, we need to */
8575     case GTK_MOVEMENT_LOGICAL_POSITIONS:
8576     case GTK_MOVEMENT_VISUAL_POSITIONS:
8577       gtk_tree_view_move_cursor_left_right (tree_view, count);
8578       break;
8579     case GTK_MOVEMENT_DISPLAY_LINES:
8580       gtk_tree_view_move_cursor_up_down (tree_view, count);
8581       break;
8582     case GTK_MOVEMENT_PAGES:
8583       gtk_tree_view_move_cursor_page_up_down (tree_view, count);
8584       break;
8585     case GTK_MOVEMENT_BUFFER_ENDS:
8586       gtk_tree_view_move_cursor_start_end (tree_view, count);
8587       break;
8588     default:
8589       g_assert_not_reached ();
8590     }
8591
8592   tree_view->priv->ctrl_pressed = FALSE;
8593   tree_view->priv->shift_pressed = FALSE;
8594
8595   return TRUE;
8596 }
8597
8598 static void
8599 gtk_tree_view_put (GtkTreeView *tree_view,
8600                    GtkWidget   *child_widget,
8601                    /* in bin_window coordinates */
8602                    gint         x,
8603                    gint         y,
8604                    gint         width,
8605                    gint         height)
8606 {
8607   GtkTreeViewChild *child;
8608   
8609   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8610   g_return_if_fail (GTK_IS_WIDGET (child_widget));
8611
8612   child = g_slice_new (GtkTreeViewChild);
8613
8614   child->widget = child_widget;
8615   child->x = x;
8616   child->y = y;
8617   child->width = width;
8618   child->height = height;
8619
8620   tree_view->priv->children = g_list_append (tree_view->priv->children, child);
8621
8622   if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
8623     gtk_widget_set_parent_window (child->widget, tree_view->priv->bin_window);
8624   
8625   gtk_widget_set_parent (child_widget, GTK_WIDGET (tree_view));
8626 }
8627
8628 void
8629 _gtk_tree_view_child_move_resize (GtkTreeView *tree_view,
8630                                   GtkWidget   *widget,
8631                                   /* in tree coordinates */
8632                                   gint         x,
8633                                   gint         y,
8634                                   gint         width,
8635                                   gint         height)
8636 {
8637   GtkTreeViewChild *child = NULL;
8638   GList *list;
8639   GdkRectangle allocation;
8640
8641   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8642   g_return_if_fail (GTK_IS_WIDGET (widget));
8643
8644   for (list = tree_view->priv->children; list; list = list->next)
8645     {
8646       if (((GtkTreeViewChild *)list->data)->widget == widget)
8647         {
8648           child = list->data;
8649           break;
8650         }
8651     }
8652   if (child == NULL)
8653     return;
8654
8655   allocation.x = child->x = x;
8656   allocation.y = child->y = y;
8657   allocation.width = child->width = width;
8658   allocation.height = child->height = height;
8659
8660   if (gtk_widget_get_realized (widget))
8661     gtk_widget_size_allocate (widget, &allocation);
8662 }
8663
8664
8665 /* TreeModel Callbacks
8666  */
8667
8668 static void
8669 gtk_tree_view_row_changed (GtkTreeModel *model,
8670                            GtkTreePath  *path,
8671                            GtkTreeIter  *iter,
8672                            gpointer      data)
8673 {
8674   GtkTreeView *tree_view = (GtkTreeView *)data;
8675   GtkRBTree *tree;
8676   GtkRBNode *node;
8677   gboolean free_path = FALSE;
8678   GList *list;
8679   GtkTreePath *cursor_path;
8680
8681   g_return_if_fail (path != NULL || iter != NULL);
8682
8683   if (tree_view->priv->cursor != NULL)
8684     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
8685   else
8686     cursor_path = NULL;
8687
8688   if (tree_view->priv->edited_column &&
8689       (cursor_path == NULL || gtk_tree_path_compare (cursor_path, path) == 0))
8690     gtk_tree_view_stop_editing (tree_view, TRUE);
8691
8692   if (cursor_path != NULL)
8693     gtk_tree_path_free (cursor_path);
8694
8695   if (path == NULL)
8696     {
8697       path = gtk_tree_model_get_path (model, iter);
8698       free_path = TRUE;
8699     }
8700   else if (iter == NULL)
8701     gtk_tree_model_get_iter (model, iter, path);
8702
8703   if (_gtk_tree_view_find_node (tree_view,
8704                                 path,
8705                                 &tree,
8706                                 &node))
8707     /* We aren't actually showing the node */
8708     goto done;
8709
8710   if (tree == NULL)
8711     goto done;
8712
8713   if (tree_view->priv->fixed_height_mode
8714       && tree_view->priv->fixed_height >= 0)
8715     {
8716       _gtk_rbtree_node_set_height (tree, node, tree_view->priv->fixed_height);
8717       if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
8718         gtk_tree_view_node_queue_redraw (tree_view, tree, node);
8719     }
8720   else
8721     {
8722       _gtk_rbtree_node_mark_invalid (tree, node);
8723       for (list = tree_view->priv->columns; list; list = list->next)
8724         {
8725           GtkTreeViewColumn *column;
8726
8727           column = list->data;
8728           if (!gtk_tree_view_column_get_visible (column))
8729             continue;
8730
8731           if (gtk_tree_view_column_get_sizing (column) == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
8732             {
8733               _gtk_tree_view_column_cell_set_dirty (column, TRUE);
8734             }
8735         }
8736     }
8737
8738  done:
8739   if (!tree_view->priv->fixed_height_mode &&
8740       gtk_widget_get_realized (GTK_WIDGET (tree_view)))
8741     install_presize_handler (tree_view);
8742   if (free_path)
8743     gtk_tree_path_free (path);
8744 }
8745
8746 static void
8747 gtk_tree_view_row_inserted (GtkTreeModel *model,
8748                             GtkTreePath  *path,
8749                             GtkTreeIter  *iter,
8750                             gpointer      data)
8751 {
8752   GtkTreeView *tree_view = (GtkTreeView *) data;
8753   gint *indices;
8754   GtkRBTree *tmptree, *tree;
8755   GtkRBNode *tmpnode = NULL;
8756   gint depth;
8757   gint i = 0;
8758   gint height;
8759   gboolean free_path = FALSE;
8760   gboolean node_visible = TRUE;
8761
8762   g_return_if_fail (path != NULL || iter != NULL);
8763
8764   if (tree_view->priv->fixed_height_mode
8765       && tree_view->priv->fixed_height >= 0)
8766     height = tree_view->priv->fixed_height;
8767   else
8768     height = 0;
8769
8770   if (path == NULL)
8771     {
8772       path = gtk_tree_model_get_path (model, iter);
8773       free_path = TRUE;
8774     }
8775   else if (iter == NULL)
8776     gtk_tree_model_get_iter (model, iter, path);
8777
8778   if (tree_view->priv->tree == NULL)
8779     tree_view->priv->tree = _gtk_rbtree_new ();
8780
8781   tmptree = tree = tree_view->priv->tree;
8782
8783   /* Update all row-references */
8784   gtk_tree_row_reference_inserted (G_OBJECT (data), path);
8785   depth = gtk_tree_path_get_depth (path);
8786   indices = gtk_tree_path_get_indices (path);
8787
8788   /* First, find the parent tree */
8789   while (i < depth - 1)
8790     {
8791       if (tmptree == NULL)
8792         {
8793           /* We aren't showing the node */
8794           node_visible = FALSE;
8795           goto done;
8796         }
8797
8798       tmpnode = _gtk_rbtree_find_count (tmptree, indices[i] + 1);
8799       if (tmpnode == NULL)
8800         {
8801           g_warning ("A node was inserted with a parent that's not in the tree.\n" \
8802                      "This possibly means that a GtkTreeModel inserted a child node\n" \
8803                      "before the parent was inserted.");
8804           goto done;
8805         }
8806       else if (!GTK_RBNODE_FLAG_SET (tmpnode, GTK_RBNODE_IS_PARENT))
8807         {
8808           /* FIXME enforce correct behavior on model, probably */
8809           /* In theory, the model should have emitted has_child_toggled here.  We
8810            * try to catch it anyway, just to be safe, in case the model hasn't.
8811            */
8812           GtkTreePath *tmppath = _gtk_tree_view_find_path (tree_view,
8813                                                            tree,
8814                                                            tmpnode);
8815           gtk_tree_view_row_has_child_toggled (model, tmppath, NULL, data);
8816           gtk_tree_path_free (tmppath);
8817           goto done;
8818         }
8819
8820       tmptree = tmpnode->children;
8821       tree = tmptree;
8822       i++;
8823     }
8824
8825   if (tree == NULL)
8826     {
8827       node_visible = FALSE;
8828       goto done;
8829     }
8830
8831   /* ref the node */
8832   gtk_tree_model_ref_node (tree_view->priv->model, iter);
8833   if (indices[depth - 1] == 0)
8834     {
8835       tmpnode = _gtk_rbtree_find_count (tree, 1);
8836       tmpnode = _gtk_rbtree_insert_before (tree, tmpnode, height, FALSE);
8837     }
8838   else
8839     {
8840       tmpnode = _gtk_rbtree_find_count (tree, indices[depth - 1]);
8841       tmpnode = _gtk_rbtree_insert_after (tree, tmpnode, height, FALSE);
8842     }
8843
8844  done:
8845   if (height > 0)
8846     {
8847       if (tree)
8848         _gtk_rbtree_node_mark_valid (tree, tmpnode);
8849
8850       if (node_visible && node_is_visible (tree_view, tree, tmpnode))
8851         gtk_widget_queue_resize (GTK_WIDGET (tree_view));
8852       else
8853         gtk_widget_queue_resize_no_redraw (GTK_WIDGET (tree_view));
8854     }
8855   else
8856     install_presize_handler (tree_view);
8857   if (free_path)
8858     gtk_tree_path_free (path);
8859 }
8860
8861 static void
8862 gtk_tree_view_row_has_child_toggled (GtkTreeModel *model,
8863                                      GtkTreePath  *path,
8864                                      GtkTreeIter  *iter,
8865                                      gpointer      data)
8866 {
8867   GtkTreeView *tree_view = (GtkTreeView *)data;
8868   GtkTreeIter real_iter;
8869   gboolean has_child;
8870   GtkRBTree *tree;
8871   GtkRBNode *node;
8872   gboolean free_path = FALSE;
8873
8874   g_return_if_fail (path != NULL || iter != NULL);
8875
8876   if (iter)
8877     real_iter = *iter;
8878
8879   if (path == NULL)
8880     {
8881       path = gtk_tree_model_get_path (model, iter);
8882       free_path = TRUE;
8883     }
8884   else if (iter == NULL)
8885     gtk_tree_model_get_iter (model, &real_iter, path);
8886
8887   if (_gtk_tree_view_find_node (tree_view,
8888                                 path,
8889                                 &tree,
8890                                 &node))
8891     /* We aren't actually showing the node */
8892     goto done;
8893
8894   if (tree == NULL)
8895     goto done;
8896
8897   has_child = gtk_tree_model_iter_has_child (model, &real_iter);
8898   /* Sanity check.
8899    */
8900   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT) == has_child)
8901     goto done;
8902
8903   if (has_child)
8904     GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_PARENT);
8905   else
8906     GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_PARENT);
8907
8908   if (has_child && tree_view->priv->is_list)
8909     {
8910       tree_view->priv->is_list = FALSE;
8911       if (tree_view->priv->show_expanders)
8912         {
8913           GList *list;
8914
8915           for (list = tree_view->priv->columns; list; list = list->next)
8916             if (gtk_tree_view_column_get_visible (GTK_TREE_VIEW_COLUMN (list->data)))
8917               {
8918                 _gtk_tree_view_column_cell_set_dirty (GTK_TREE_VIEW_COLUMN (list->data), TRUE);
8919                 break;
8920               }
8921         }
8922       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
8923     }
8924   else
8925     {
8926       _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
8927     }
8928
8929  done:
8930   if (free_path)
8931     gtk_tree_path_free (path);
8932 }
8933
8934 static void
8935 count_children_helper (GtkRBTree *tree,
8936                        GtkRBNode *node,
8937                        gpointer   data)
8938 {
8939   if (node->children)
8940     _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, data);
8941   (*((gint *)data))++;
8942 }
8943
8944 static void
8945 check_selection_helper (GtkRBTree *tree,
8946                         GtkRBNode *node,
8947                         gpointer   data)
8948 {
8949   gint *value = (gint *)data;
8950
8951   *value = GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED);
8952
8953   if (node->children && !*value)
8954     _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, check_selection_helper, data);
8955 }
8956
8957 static void
8958 gtk_tree_view_row_deleted (GtkTreeModel *model,
8959                            GtkTreePath  *path,
8960                            gpointer      data)
8961 {
8962   GtkTreeView *tree_view = (GtkTreeView *)data;
8963   GtkRBTree *tree;
8964   GtkRBNode *node;
8965   GList *list;
8966   gint selection_changed = FALSE;
8967   GtkStyleContext *context;
8968
8969   g_return_if_fail (path != NULL);
8970
8971   gtk_tree_row_reference_deleted (G_OBJECT (data), path);
8972
8973   if (_gtk_tree_view_find_node (tree_view, path, &tree, &node))
8974     return;
8975
8976   if (tree == NULL)
8977     return;
8978
8979   /* check if the selection has been changed */
8980   _gtk_rbtree_traverse (tree, node, G_POST_ORDER,
8981                         check_selection_helper, &selection_changed);
8982
8983   for (list = tree_view->priv->columns; list; list = list->next)
8984     if (gtk_tree_view_column_get_visible (GTK_TREE_VIEW_COLUMN (list->data)) &&
8985         gtk_tree_view_column_get_sizing (GTK_TREE_VIEW_COLUMN (list->data)) == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
8986       _gtk_tree_view_column_cell_set_dirty ((GtkTreeViewColumn *)list->data, TRUE);
8987
8988   /* Ensure we don't have a dangling pointer to a dead node */
8989   ensure_unprelighted (tree_view);
8990
8991   /* Cancel editting if we've started */
8992   gtk_tree_view_stop_editing (tree_view, TRUE);
8993
8994   if (tree_view->priv->destroy_count_func)
8995     {
8996       gint child_count = 0;
8997       if (node->children)
8998         _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, &child_count);
8999       tree_view->priv->destroy_count_func (tree_view, path, child_count, tree_view->priv->destroy_count_data);
9000     }
9001
9002   if (tree->root->count == 1)
9003     {
9004       if (tree_view->priv->tree == tree)
9005         tree_view->priv->tree = NULL;
9006
9007       _gtk_rbtree_remove (tree);
9008     }
9009   else
9010     {
9011       _gtk_rbtree_remove_node (tree, node);
9012     }
9013
9014   if (! gtk_tree_row_reference_valid (tree_view->priv->top_row))
9015     {
9016       gtk_tree_row_reference_free (tree_view->priv->top_row);
9017       tree_view->priv->top_row = NULL;
9018     }
9019
9020   /* Cancel any ongoing animation happening within the row */
9021   context = gtk_widget_get_style_context (GTK_WIDGET (tree_view));
9022   gtk_style_context_cancel_animations (context, node);
9023
9024   install_scroll_sync_handler (tree_view);
9025
9026   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
9027
9028   if (selection_changed)
9029     g_signal_emit_by_name (tree_view->priv->selection, "changed");
9030 }
9031
9032 static void
9033 gtk_tree_view_rows_reordered (GtkTreeModel *model,
9034                               GtkTreePath  *parent,
9035                               GtkTreeIter  *iter,
9036                               gint         *new_order,
9037                               gpointer      data)
9038 {
9039   GtkTreeView *tree_view = GTK_TREE_VIEW (data);
9040   GtkRBTree *tree;
9041   GtkRBNode *node;
9042   gint len;
9043
9044   len = gtk_tree_model_iter_n_children (model, iter);
9045
9046   if (len < 2)
9047     return;
9048
9049   gtk_tree_row_reference_reordered (G_OBJECT (data),
9050                                     parent,
9051                                     iter,
9052                                     new_order);
9053
9054   if (_gtk_tree_view_find_node (tree_view,
9055                                 parent,
9056                                 &tree,
9057                                 &node))
9058     return;
9059
9060   /* We need to special case the parent path */
9061   if (tree == NULL)
9062     tree = tree_view->priv->tree;
9063   else
9064     tree = node->children;
9065
9066   if (tree == NULL)
9067     return;
9068
9069   if (tree_view->priv->edited_column)
9070     gtk_tree_view_stop_editing (tree_view, TRUE);
9071
9072   /* we need to be unprelighted */
9073   ensure_unprelighted (tree_view);
9074
9075   _gtk_rbtree_reorder (tree, new_order, len);
9076
9077   gtk_widget_queue_draw (GTK_WIDGET (tree_view));
9078
9079   gtk_tree_view_dy_to_top_row (tree_view);
9080 }
9081
9082
9083 /* Internal tree functions
9084  */
9085
9086
9087 static void
9088 gtk_tree_view_get_background_xrange (GtkTreeView       *tree_view,
9089                                      GtkRBTree         *tree,
9090                                      GtkTreeViewColumn *column,
9091                                      gint              *x1,
9092                                      gint              *x2)
9093 {
9094   GtkTreeViewColumn *tmp_column = NULL;
9095   gint total_width;
9096   GList *list;
9097   gboolean rtl;
9098
9099   if (x1)
9100     *x1 = 0;
9101
9102   if (x2)
9103     *x2 = 0;
9104
9105   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
9106
9107   total_width = 0;
9108   for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
9109        list;
9110        list = (rtl ? list->prev : list->next))
9111     {
9112       tmp_column = list->data;
9113
9114       if (tmp_column == column)
9115         break;
9116
9117       if (gtk_tree_view_column_get_visible (tmp_column))
9118         total_width += gtk_tree_view_column_get_width (tmp_column);
9119     }
9120
9121   if (tmp_column != column)
9122     {
9123       g_warning (G_STRLOC": passed-in column isn't in the tree");
9124       return;
9125     }
9126
9127   if (x1)
9128     *x1 = total_width;
9129
9130   if (x2)
9131     {
9132       if (gtk_tree_view_column_get_visible (column))
9133         *x2 = total_width + gtk_tree_view_column_get_width (column);
9134       else
9135         *x2 = total_width; /* width of 0 */
9136     }
9137 }
9138
9139 static void
9140 gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view,
9141                                 GtkRBTree   *tree,
9142                                 gint        *x1,
9143                                 gint        *x2)
9144 {
9145   gint x_offset = 0;
9146   GList *list;
9147   GtkTreeViewColumn *tmp_column = NULL;
9148   gint total_width;
9149   gboolean indent_expanders;
9150   gboolean rtl;
9151
9152   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
9153
9154   total_width = 0;
9155   for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
9156        list;
9157        list = (rtl ? list->prev : list->next))
9158     {
9159       tmp_column = list->data;
9160
9161       if (gtk_tree_view_is_expander_column (tree_view, tmp_column))
9162         {
9163           if (rtl)
9164             x_offset = total_width + gtk_tree_view_column_get_width (tmp_column) - tree_view->priv->expander_size;
9165           else
9166             x_offset = total_width;
9167           break;
9168         }
9169
9170       if (gtk_tree_view_column_get_visible (tmp_column))
9171         total_width += gtk_tree_view_column_get_width (tmp_column);
9172     }
9173
9174   gtk_widget_style_get (GTK_WIDGET (tree_view),
9175                         "indent-expanders", &indent_expanders,
9176                         NULL);
9177
9178   if (indent_expanders)
9179     {
9180       if (rtl)
9181         x_offset -= tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree);
9182       else
9183         x_offset += tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree);
9184     }
9185
9186   *x1 = x_offset;
9187
9188   if (tmp_column &&
9189       gtk_tree_view_column_get_visible (tmp_column))
9190     /* +1 because x2 isn't included in the range. */
9191     *x2 = *x1 + tree_view->priv->expander_size + 1;
9192   else
9193     *x2 = *x1;
9194 }
9195
9196 static void
9197 gtk_tree_view_build_tree (GtkTreeView *tree_view,
9198                           GtkRBTree   *tree,
9199                           GtkTreeIter *iter,
9200                           gint         depth,
9201                           gboolean     recurse)
9202 {
9203   GtkRBNode *temp = NULL;
9204   GtkTreePath *path = NULL;
9205
9206   do
9207     {
9208       gtk_tree_model_ref_node (tree_view->priv->model, iter);
9209       temp = _gtk_rbtree_insert_after (tree, temp, 0, FALSE);
9210
9211       if (tree_view->priv->fixed_height > 0)
9212         {
9213           if (GTK_RBNODE_FLAG_SET (temp, GTK_RBNODE_INVALID))
9214             {
9215               _gtk_rbtree_node_set_height (tree, temp, tree_view->priv->fixed_height);
9216               _gtk_rbtree_node_mark_valid (tree, temp);
9217             }
9218         }
9219
9220       if (tree_view->priv->is_list)
9221         continue;
9222
9223       if (recurse)
9224         {
9225           GtkTreeIter child;
9226
9227           if (!path)
9228             path = gtk_tree_model_get_path (tree_view->priv->model, iter);
9229           else
9230             gtk_tree_path_next (path);
9231
9232           if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter))
9233             {
9234               gboolean expand;
9235
9236               g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, iter, path, &expand);
9237
9238               if (gtk_tree_model_iter_has_child (tree_view->priv->model, iter)
9239                   && !expand)
9240                 {
9241                   temp->children = _gtk_rbtree_new ();
9242                   temp->children->parent_tree = tree;
9243                   temp->children->parent_node = temp;
9244                   gtk_tree_view_build_tree (tree_view, temp->children, &child, depth + 1, recurse);
9245                 }
9246             }
9247         }
9248
9249       if (gtk_tree_model_iter_has_child (tree_view->priv->model, iter))
9250         {
9251           if ((temp->flags&GTK_RBNODE_IS_PARENT) != GTK_RBNODE_IS_PARENT)
9252             temp->flags ^= GTK_RBNODE_IS_PARENT;
9253         }
9254     }
9255   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
9256
9257   if (path)
9258     gtk_tree_path_free (path);
9259 }
9260
9261 /* Make sure the node is visible vertically */
9262 static void
9263 gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
9264                                   GtkRBTree   *tree,
9265                                   GtkRBNode   *node)
9266 {
9267   gint node_dy, height;
9268   GtkTreePath *path = NULL;
9269
9270   if (!gtk_widget_get_realized (GTK_WIDGET (tree_view)))
9271     return;
9272
9273   /* just return if the node is visible, avoiding a costly expose */
9274   node_dy = _gtk_rbtree_node_find_offset (tree, node);
9275   height = gtk_tree_view_get_row_height (tree_view, node);
9276   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID)
9277       && node_dy >= gtk_adjustment_get_value (tree_view->priv->vadjustment)
9278       && node_dy + height <= (gtk_adjustment_get_value (tree_view->priv->vadjustment)
9279                               + gtk_adjustment_get_page_size (tree_view->priv->vadjustment)))
9280     return;
9281
9282   path = _gtk_tree_view_find_path (tree_view, tree, node);
9283   if (path)
9284     {
9285       /* We process updates because we want to clear old selected items when we scroll.
9286        * if this is removed, we get a "selection streak" at the bottom. */
9287       gtk_tree_view_bin_process_updates (tree_view);
9288
9289       gtk_tree_view_scroll_to_cell (tree_view, path, NULL, FALSE, 0.0, 0.0);
9290       gtk_tree_path_free (path);
9291     }
9292 }
9293
9294 static void
9295 gtk_tree_view_clamp_column_visible (GtkTreeView       *tree_view,
9296                                     GtkTreeViewColumn *column,
9297                                     gboolean           focus_to_cell)
9298 {
9299   GtkAllocation allocation;
9300   gint x, width;
9301
9302   if (column == NULL)
9303     return;
9304
9305   gtk_widget_get_allocation (gtk_tree_view_column_get_button (column), &allocation);
9306   x = allocation.x;
9307   width = allocation.width;
9308
9309   if (width > gtk_adjustment_get_page_size (tree_view->priv->hadjustment))
9310     {
9311       /* The column is larger than the horizontal page size.  If the
9312        * column has cells which can be focussed individually, then we make
9313        * sure the cell which gets focus is fully visible (if even the
9314        * focus cell is bigger than the page size, we make sure the
9315        * left-hand side of the cell is visible).
9316        *
9317        * If the column does not have an activatable cell, we
9318        * make sure the left-hand side of the column is visible.
9319        */
9320
9321       if (focus_to_cell && gtk_tree_view_has_can_focus_cell (tree_view))
9322         {
9323           GtkCellArea *cell_area;
9324           GtkCellRenderer *focus_cell;
9325
9326           cell_area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (column));
9327           focus_cell = gtk_cell_area_get_focus_cell (cell_area);
9328
9329           if (gtk_tree_view_column_cell_get_position (column, focus_cell,
9330                                                       &x, &width))
9331             {
9332               if (width < gtk_adjustment_get_page_size (tree_view->priv->hadjustment))
9333                 {
9334                   if (gtk_adjustment_get_value (tree_view->priv->hadjustment) + gtk_adjustment_get_page_size (tree_view->priv->hadjustment) < x + width)
9335                     gtk_adjustment_set_value (tree_view->priv->hadjustment,
9336                                               x + width - gtk_adjustment_get_page_size (tree_view->priv->hadjustment));
9337                   else if (gtk_adjustment_get_value (tree_view->priv->hadjustment) > x)
9338                     gtk_adjustment_set_value (tree_view->priv->hadjustment, x);
9339                 }
9340             }
9341         }
9342
9343       gtk_adjustment_set_value (tree_view->priv->hadjustment, x);
9344     }
9345   else
9346     {
9347       if ((gtk_adjustment_get_value (tree_view->priv->hadjustment) + gtk_adjustment_get_page_size (tree_view->priv->hadjustment)) < (x + width))
9348           gtk_adjustment_set_value (tree_view->priv->hadjustment,
9349                                     x + width - gtk_adjustment_get_page_size (tree_view->priv->hadjustment));
9350       else if (gtk_adjustment_get_value (tree_view->priv->hadjustment) > x)
9351         gtk_adjustment_set_value (tree_view->priv->hadjustment, x);
9352   }
9353 }
9354
9355 /* This function could be more efficient.  I'll optimize it if profiling seems
9356  * to imply that it is important */
9357 GtkTreePath *
9358 _gtk_tree_view_find_path (GtkTreeView *tree_view,
9359                           GtkRBTree   *tree,
9360                           GtkRBNode   *node)
9361 {
9362   GtkTreePath *path;
9363   GtkRBTree *tmp_tree;
9364   GtkRBNode *tmp_node, *last;
9365   gint count;
9366
9367   path = gtk_tree_path_new ();
9368
9369   g_return_val_if_fail (node != NULL, path);
9370   g_return_val_if_fail (node != tree->nil, path);
9371
9372   count = 1 + node->left->count;
9373
9374   last = node;
9375   tmp_node = node->parent;
9376   tmp_tree = tree;
9377   while (tmp_tree)
9378     {
9379       while (tmp_node != tmp_tree->nil)
9380         {
9381           if (tmp_node->right == last)
9382             count += 1 + tmp_node->left->count;
9383           last = tmp_node;
9384           tmp_node = tmp_node->parent;
9385         }
9386       gtk_tree_path_prepend_index (path, count - 1);
9387       last = tmp_tree->parent_node;
9388       tmp_tree = tmp_tree->parent_tree;
9389       if (last)
9390         {
9391           count = 1 + last->left->count;
9392           tmp_node = last->parent;
9393         }
9394     }
9395   return path;
9396 }
9397
9398 /* Returns TRUE if we ran out of tree before finding the path.  If the path is
9399  * invalid (ie. points to a node that's not in the tree), *tree and *node are
9400  * both set to NULL.
9401  */
9402 gboolean
9403 _gtk_tree_view_find_node (GtkTreeView  *tree_view,
9404                           GtkTreePath  *path,
9405                           GtkRBTree   **tree,
9406                           GtkRBNode   **node)
9407 {
9408   GtkRBNode *tmpnode = NULL;
9409   GtkRBTree *tmptree = tree_view->priv->tree;
9410   gint *indices = gtk_tree_path_get_indices (path);
9411   gint depth = gtk_tree_path_get_depth (path);
9412   gint i = 0;
9413
9414   *node = NULL;
9415   *tree = NULL;
9416
9417   if (depth == 0 || tmptree == NULL)
9418     return FALSE;
9419   do
9420     {
9421       tmpnode = _gtk_rbtree_find_count (tmptree, indices[i] + 1);
9422       ++i;
9423       if (tmpnode == NULL)
9424         {
9425           *tree = NULL;
9426           *node = NULL;
9427           return FALSE;
9428         }
9429       if (i >= depth)
9430         {
9431           *tree = tmptree;
9432           *node = tmpnode;
9433           return FALSE;
9434         }
9435       *tree = tmptree;
9436       *node = tmpnode;
9437       tmptree = tmpnode->children;
9438       if (tmptree == NULL)
9439         return TRUE;
9440     }
9441   while (1);
9442 }
9443
9444 static gboolean
9445 gtk_tree_view_is_expander_column (GtkTreeView       *tree_view,
9446                                   GtkTreeViewColumn *column)
9447 {
9448   GList *list;
9449
9450   if (tree_view->priv->is_list)
9451     return FALSE;
9452
9453   if (tree_view->priv->expander_column != NULL)
9454     {
9455       if (tree_view->priv->expander_column == column)
9456         return TRUE;
9457       return FALSE;
9458     }
9459   else
9460     {
9461       for (list = tree_view->priv->columns;
9462            list;
9463            list = list->next)
9464         if (gtk_tree_view_column_get_visible (GTK_TREE_VIEW_COLUMN (list->data)))
9465           break;
9466       if (list && list->data == column)
9467         return TRUE;
9468     }
9469   return FALSE;
9470 }
9471
9472 static inline gboolean
9473 gtk_tree_view_draw_expanders (GtkTreeView *tree_view)
9474 {
9475   if (!tree_view->priv->is_list && tree_view->priv->show_expanders)
9476     return TRUE;
9477   /* else */
9478   return FALSE;
9479 }
9480
9481 static void
9482 gtk_tree_view_add_move_binding (GtkBindingSet  *binding_set,
9483                                 guint           keyval,
9484                                 guint           modmask,
9485                                 gboolean        add_shifted_binding,
9486                                 GtkMovementStep step,
9487                                 gint            count)
9488 {
9489   
9490   gtk_binding_entry_add_signal (binding_set, keyval, modmask,
9491                                 "move-cursor", 2,
9492                                 G_TYPE_ENUM, step,
9493                                 G_TYPE_INT, count);
9494
9495   if (add_shifted_binding)
9496     gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
9497                                   "move-cursor", 2,
9498                                   G_TYPE_ENUM, step,
9499                                   G_TYPE_INT, count);
9500
9501   if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
9502    return;
9503
9504   gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
9505                                 "move-cursor", 2,
9506                                 G_TYPE_ENUM, step,
9507                                 G_TYPE_INT, count);
9508
9509   gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
9510                                 "move-cursor", 2,
9511                                 G_TYPE_ENUM, step,
9512                                 G_TYPE_INT, count);
9513 }
9514
9515 static gint
9516 gtk_tree_view_unref_tree_helper (GtkTreeModel *model,
9517                                  GtkTreeIter  *iter,
9518                                  GtkRBTree    *tree,
9519                                  GtkRBNode    *node)
9520 {
9521   gint retval = FALSE;
9522   do
9523     {
9524       g_return_val_if_fail (node != NULL, FALSE);
9525
9526       if (node->children)
9527         {
9528           GtkTreeIter child;
9529           GtkRBTree *new_tree;
9530           GtkRBNode *new_node;
9531
9532           new_tree = node->children;
9533           new_node = new_tree->root;
9534
9535           while (new_node && new_node->left != new_tree->nil)
9536             new_node = new_node->left;
9537
9538           if (!gtk_tree_model_iter_children (model, &child, iter))
9539             return FALSE;
9540
9541           retval = retval || gtk_tree_view_unref_tree_helper (model, &child, new_tree, new_node);
9542         }
9543
9544       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
9545         retval = TRUE;
9546       gtk_tree_model_unref_node (model, iter);
9547       node = _gtk_rbtree_next (tree, node);
9548     }
9549   while (gtk_tree_model_iter_next (model, iter));
9550
9551   return retval;
9552 }
9553
9554 static gint
9555 gtk_tree_view_unref_and_check_selection_tree (GtkTreeView *tree_view,
9556                                               GtkRBTree   *tree)
9557 {
9558   GtkTreeIter iter;
9559   GtkTreePath *path;
9560   GtkRBNode *node;
9561   gint retval;
9562
9563   if (!tree)
9564     return FALSE;
9565
9566   node = tree->root;
9567   while (node && node->left != tree->nil)
9568     node = node->left;
9569
9570   g_return_val_if_fail (node != NULL, FALSE);
9571   path = _gtk_tree_view_find_path (tree_view, tree, node);
9572   gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_view->priv->model),
9573                            &iter, path);
9574   retval = gtk_tree_view_unref_tree_helper (GTK_TREE_MODEL (tree_view->priv->model), &iter, tree, node);
9575   gtk_tree_path_free (path);
9576
9577   return retval;
9578 }
9579
9580 static void
9581 gtk_tree_view_set_column_drag_info (GtkTreeView       *tree_view,
9582                                     GtkTreeViewColumn *column)
9583 {
9584   GtkTreeViewColumn *left_column;
9585   GtkTreeViewColumn *cur_column = NULL;
9586   GtkTreeViewColumnReorder *reorder;
9587   gboolean rtl;
9588   GList *tmp_list;
9589   gint left;
9590
9591   /* We want to precalculate the motion list such that we know what column slots
9592    * are available.
9593    */
9594   left_column = NULL;
9595   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
9596
9597   /* First, identify all possible drop spots */
9598   if (rtl)
9599     tmp_list = g_list_last (tree_view->priv->columns);
9600   else
9601     tmp_list = g_list_first (tree_view->priv->columns);
9602
9603   while (tmp_list)
9604     {
9605       cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
9606       tmp_list = rtl?g_list_previous (tmp_list):g_list_next (tmp_list);
9607
9608       if (gtk_tree_view_column_get_visible (cur_column) == FALSE)
9609         continue;
9610
9611       /* If it's not the column moving and func tells us to skip over the column, we continue. */
9612       if (left_column != column && cur_column != column &&
9613           tree_view->priv->column_drop_func &&
9614           ! tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
9615         {
9616           left_column = cur_column;
9617           continue;
9618         }
9619       reorder = g_slice_new0 (GtkTreeViewColumnReorder);
9620       reorder->left_column = left_column;
9621       left_column = reorder->right_column = cur_column;
9622
9623       tree_view->priv->column_drag_info = g_list_append (tree_view->priv->column_drag_info, reorder);
9624     }
9625
9626   /* Add the last one */
9627   if (tree_view->priv->column_drop_func == NULL ||
9628       ((left_column != column) &&
9629        tree_view->priv->column_drop_func (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data)))
9630     {
9631       reorder = g_slice_new0 (GtkTreeViewColumnReorder);
9632       reorder->left_column = left_column;
9633       reorder->right_column = NULL;
9634       tree_view->priv->column_drag_info = g_list_append (tree_view->priv->column_drag_info, reorder);
9635     }
9636
9637   /* We quickly check to see if it even makes sense to reorder columns. */
9638   /* If there is nothing that can be moved, then we return */
9639
9640   if (tree_view->priv->column_drag_info == NULL)
9641     return;
9642
9643   /* We know there are always 2 slots possbile, as you can always return column. */
9644   /* If that's all there is, return */
9645   if (tree_view->priv->column_drag_info->next == NULL || 
9646       (tree_view->priv->column_drag_info->next->next == NULL &&
9647        ((GtkTreeViewColumnReorder *)tree_view->priv->column_drag_info->data)->right_column == column &&
9648        ((GtkTreeViewColumnReorder *)tree_view->priv->column_drag_info->next->data)->left_column == column))
9649     {
9650       for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
9651         g_slice_free (GtkTreeViewColumnReorder, tmp_list->data);
9652       g_list_free (tree_view->priv->column_drag_info);
9653       tree_view->priv->column_drag_info = NULL;
9654       return;
9655     }
9656   /* We fill in the ranges for the columns, now that we've isolated them */
9657   left = - TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view);
9658
9659   for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
9660     {
9661       reorder = (GtkTreeViewColumnReorder *) tmp_list->data;
9662
9663       reorder->left_align = left;
9664       if (tmp_list->next != NULL)
9665         {
9666           GtkAllocation right_allocation, left_allocation;
9667           GtkWidget    *left_button, *right_button;
9668
9669           g_assert (tmp_list->next->data);
9670
9671           right_button = gtk_tree_view_column_get_button (reorder->right_column);
9672           left_button  = gtk_tree_view_column_get_button
9673             (((GtkTreeViewColumnReorder *)tmp_list->next->data)->left_column);
9674
9675           gtk_widget_get_allocation (right_button, &right_allocation);
9676           gtk_widget_get_allocation (left_button, &left_allocation);
9677           left = reorder->right_align = (right_allocation.x + right_allocation.width + left_allocation.x) / 2;
9678         }
9679       else
9680         {
9681           reorder->right_align = gdk_window_get_width (tree_view->priv->header_window)
9682                                  + TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view);
9683         }
9684     }
9685 }
9686
9687 void
9688 _gtk_tree_view_column_start_drag (GtkTreeView       *tree_view,
9689                                   GtkTreeViewColumn *column,
9690                                   GdkDevice         *device)
9691 {
9692   GdkEvent *send_event;
9693   GtkAllocation allocation;
9694   GtkAllocation button_allocation;
9695   GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
9696   GtkWidget *button;
9697   GdkDevice *pointer, *keyboard;
9698
9699   g_return_if_fail (tree_view->priv->column_drag_info == NULL);
9700   g_return_if_fail (tree_view->priv->cur_reorder == NULL);
9701
9702   gtk_tree_view_set_column_drag_info (tree_view, column);
9703
9704   if (tree_view->priv->column_drag_info == NULL)
9705     return;
9706
9707   button = gtk_tree_view_column_get_button (column);
9708
9709   if (tree_view->priv->drag_window == NULL)
9710     {
9711       GdkWindowAttr attributes;
9712       guint attributes_mask;
9713
9714       gtk_widget_get_allocation (button, &button_allocation);
9715
9716       attributes.window_type = GDK_WINDOW_CHILD;
9717       attributes.wclass = GDK_INPUT_OUTPUT;
9718       attributes.x = button_allocation.x;
9719       attributes.y = 0;
9720       attributes.width = button_allocation.width;
9721       attributes.height = button_allocation.height;
9722       attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
9723       attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
9724       attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
9725
9726       tree_view->priv->drag_window = gdk_window_new (tree_view->priv->bin_window,
9727                                                      &attributes,
9728                                                      attributes_mask);
9729       gdk_window_set_user_data (tree_view->priv->drag_window, GTK_WIDGET (tree_view));
9730     }
9731
9732   if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
9733     {
9734       keyboard = device;
9735       pointer = gdk_device_get_associated_device (device);
9736     }
9737   else
9738     {
9739       pointer = device;
9740       keyboard = gdk_device_get_associated_device (device);
9741     }
9742
9743   gdk_device_ungrab (pointer, GDK_CURRENT_TIME);
9744   gdk_device_ungrab (keyboard, GDK_CURRENT_TIME);
9745
9746   gtk_grab_remove (button);
9747
9748   send_event = gdk_event_new (GDK_LEAVE_NOTIFY);
9749   send_event->crossing.send_event = TRUE;
9750   send_event->crossing.window = g_object_ref (gtk_button_get_event_window (GTK_BUTTON (button)));
9751   send_event->crossing.subwindow = NULL;
9752   send_event->crossing.detail = GDK_NOTIFY_ANCESTOR;
9753   send_event->crossing.time = GDK_CURRENT_TIME;
9754   gdk_event_set_device (send_event, device);
9755
9756   gtk_propagate_event (button, send_event);
9757   gdk_event_free (send_event);
9758
9759   send_event = gdk_event_new (GDK_BUTTON_RELEASE);
9760   send_event->button.window = g_object_ref (gdk_screen_get_root_window (screen));
9761   send_event->button.send_event = TRUE;
9762   send_event->button.time = GDK_CURRENT_TIME;
9763   send_event->button.x = -1;
9764   send_event->button.y = -1;
9765   send_event->button.axes = NULL;
9766   send_event->button.state = 0;
9767   send_event->button.button = 1;
9768   send_event->button.x_root = 0;
9769   send_event->button.y_root = 0;
9770   gdk_event_set_device (send_event, device);
9771
9772   gtk_propagate_event (button, send_event);
9773   gdk_event_free (send_event);
9774
9775   /* Kids, don't try this at home */
9776   g_object_ref (button);
9777   gtk_container_remove (GTK_CONTAINER (tree_view), button);
9778   gtk_widget_set_parent_window (button, tree_view->priv->drag_window);
9779   gtk_widget_set_parent (button, GTK_WIDGET (tree_view));
9780   g_object_unref (button);
9781
9782   gtk_widget_get_allocation (button, &button_allocation);
9783   tree_view->priv->drag_column_x = button_allocation.x;
9784   allocation = button_allocation;
9785   allocation.x = 0;
9786   gtk_widget_size_allocate (button, &allocation);
9787   gtk_widget_set_parent_window (button, tree_view->priv->drag_window);
9788
9789   tree_view->priv->drag_column = column;
9790   gdk_window_show (tree_view->priv->drag_window);
9791
9792   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
9793   while (gtk_events_pending ())
9794     gtk_main_iteration ();
9795
9796   tree_view->priv->in_column_drag = TRUE;
9797
9798   gdk_device_grab (pointer,
9799                    tree_view->priv->drag_window,
9800                    GDK_OWNERSHIP_NONE,
9801                    FALSE,
9802                    GDK_POINTER_MOTION_MASK|GDK_BUTTON_RELEASE_MASK,
9803                    NULL,
9804                    GDK_CURRENT_TIME);
9805   gdk_device_grab (keyboard,
9806                    tree_view->priv->drag_window,
9807                    GDK_OWNERSHIP_NONE,
9808                    FALSE,
9809                    GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK,
9810                    NULL,
9811                    GDK_CURRENT_TIME);
9812 }
9813
9814 static void
9815 gtk_tree_view_queue_draw_arrow (GtkTreeView        *tree_view,
9816                                 GtkRBTree          *tree,
9817                                 GtkRBNode          *node)
9818 {
9819   GtkAllocation allocation;
9820   GdkRectangle rect;
9821
9822   if (!gtk_widget_get_realized (GTK_WIDGET (tree_view)))
9823     return;
9824
9825   gtk_widget_get_allocation (GTK_WIDGET (tree_view), &allocation);
9826   rect.x = 0;
9827   rect.width = MAX (tree_view->priv->expander_size, MAX (tree_view->priv->width, allocation.width));
9828
9829   rect.y = gtk_tree_view_get_row_y_offset (tree_view, tree, node);
9830   rect.height = gtk_tree_view_get_row_height (tree_view, node);
9831
9832   gdk_window_invalidate_rect (tree_view->priv->bin_window, &rect, TRUE);
9833 }
9834
9835 void
9836 _gtk_tree_view_queue_draw_node (GtkTreeView        *tree_view,
9837                                 GtkRBTree          *tree,
9838                                 GtkRBNode          *node,
9839                                 const GdkRectangle *clip_rect)
9840 {
9841   GtkAllocation allocation;
9842   GdkRectangle rect;
9843
9844   if (!gtk_widget_get_realized (GTK_WIDGET (tree_view)))
9845     return;
9846
9847   gtk_widget_get_allocation (GTK_WIDGET (tree_view), &allocation);
9848   rect.x = 0;
9849   rect.width = MAX (tree_view->priv->width, allocation.width);
9850
9851   rect.y = gtk_tree_view_get_row_y_offset (tree_view, tree, node);
9852   rect.height = gtk_tree_view_get_row_height (tree_view, node);
9853
9854   if (clip_rect)
9855     {
9856       GdkRectangle new_rect;
9857
9858       gdk_rectangle_intersect (clip_rect, &rect, &new_rect);
9859
9860       gdk_window_invalidate_rect (tree_view->priv->bin_window, &new_rect, TRUE);
9861     }
9862   else
9863     {
9864       gdk_window_invalidate_rect (tree_view->priv->bin_window, &rect, TRUE);
9865     }
9866 }
9867
9868 static inline gint
9869 gtk_tree_view_get_effective_header_height (GtkTreeView *tree_view)
9870 {
9871   if (tree_view->priv->headers_visible)
9872     return tree_view->priv->header_height;
9873   /* else */
9874   return 0;
9875 }
9876
9877 gint
9878 _gtk_tree_view_get_header_height (GtkTreeView *tree_view)
9879 {
9880   return tree_view->priv->header_height;
9881 }
9882
9883 void
9884 _gtk_tree_view_get_row_separator_func (GtkTreeView                 *tree_view,
9885                                        GtkTreeViewRowSeparatorFunc *func,
9886                                        gpointer                    *data)
9887 {
9888   *func = tree_view->priv->row_separator_func;
9889   *data = tree_view->priv->row_separator_data;
9890 }
9891
9892 GtkTreePath *
9893 _gtk_tree_view_get_anchor_path (GtkTreeView *tree_view)
9894 {
9895   if (tree_view->priv->anchor)
9896     return gtk_tree_row_reference_get_path (tree_view->priv->anchor);
9897
9898   return NULL;
9899 }
9900
9901 void
9902 _gtk_tree_view_set_anchor_path (GtkTreeView *tree_view,
9903                                 GtkTreePath *anchor_path)
9904 {
9905   if (tree_view->priv->anchor)
9906     {
9907       gtk_tree_row_reference_free (tree_view->priv->anchor);
9908       tree_view->priv->anchor = NULL;
9909     }
9910
9911   if (anchor_path && tree_view->priv->model)
9912     tree_view->priv->anchor =
9913       gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), 
9914                                         tree_view->priv->model, anchor_path);
9915 }
9916
9917 GtkRBTree *
9918 _gtk_tree_view_get_rbtree (GtkTreeView *tree_view)
9919 {
9920   return tree_view->priv->tree;
9921 }
9922
9923 GdkWindow *
9924 _gtk_tree_view_get_header_window (GtkTreeView *tree_view)
9925 {
9926   return tree_view->priv->header_window;
9927 }
9928
9929 void
9930 _gtk_tree_view_set_focus_column (GtkTreeView       *tree_view,
9931                                  GtkTreeViewColumn *column)
9932 {
9933   tree_view->priv->focus_column = column;
9934 }
9935
9936
9937 static void
9938 gtk_tree_view_queue_draw_path (GtkTreeView        *tree_view,
9939                                GtkTreePath        *path,
9940                                const GdkRectangle *clip_rect)
9941 {
9942   GtkRBTree *tree = NULL;
9943   GtkRBNode *node = NULL;
9944
9945   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
9946
9947   if (tree)
9948     _gtk_tree_view_queue_draw_node (tree_view, tree, node, clip_rect);
9949 }
9950
9951 /* x and y are the mouse position
9952  */
9953 static void
9954 gtk_tree_view_draw_arrow (GtkTreeView *tree_view,
9955                           cairo_t     *cr,
9956                           GtkRBTree   *tree,
9957                           GtkRBNode   *node,
9958                           /* in bin_window coordinates */
9959                           gint         x,
9960                           gint         y)
9961 {
9962   GdkRectangle area;
9963   GtkStateFlags state = 0;
9964   GtkStyleContext *context;
9965   GtkWidget *widget;
9966   gint x_offset = 0;
9967   gint x2;
9968   gint vertical_separator;
9969   gint expander_size;
9970   GtkCellRendererState flags;
9971
9972   widget = GTK_WIDGET (tree_view);
9973   context = gtk_widget_get_style_context (widget);
9974
9975   gtk_widget_style_get (widget,
9976                         "vertical-separator", &vertical_separator,
9977                         NULL);
9978   expander_size = tree_view->priv->expander_size - EXPANDER_EXTRA_PADDING;
9979
9980   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
9981     return;
9982
9983   gtk_tree_view_get_arrow_xrange (tree_view, tree, &x_offset, &x2);
9984
9985   area.x = x_offset;
9986   area.y = gtk_tree_view_get_cell_area_y_offset (tree_view, tree, node,
9987                                                  vertical_separator);
9988   area.width = expander_size;
9989   area.height = gtk_tree_view_get_cell_area_height (tree_view, node,
9990                                                     vertical_separator);
9991
9992   if (!gtk_widget_get_sensitive (widget))
9993     state |= GTK_STATE_FLAG_INSENSITIVE;
9994   else
9995     {
9996       flags = 0;
9997
9998       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
9999         flags |= GTK_CELL_RENDERER_SELECTED;
10000
10001       state = gtk_cell_renderer_get_state (NULL, widget, flags);
10002
10003       if (node == tree_view->priv->button_pressed_node &&
10004           x >= area.x && x <= (area.x + area.width) &&
10005           y >= area.y && y <= (area.y + area.height))
10006         state |= GTK_STATE_FLAG_FOCUSED;
10007
10008       if (node == tree_view->priv->prelight_node &&
10009           tree_view->priv->arrow_prelit)
10010         state |= GTK_STATE_FLAG_PRELIGHT;
10011     }
10012
10013   if (node->children != NULL)
10014     state |= GTK_STATE_FLAG_ACTIVE;
10015
10016   gtk_style_context_save (context);
10017
10018   gtk_style_context_set_state (context, state);
10019   gtk_style_context_add_class (context, GTK_STYLE_CLASS_EXPANDER);
10020
10021   gtk_style_context_push_animatable_region (context, node);
10022
10023   gtk_render_expander (context, cr,
10024                        area.x, area.y,
10025                        area.width, area.height);
10026
10027   gtk_style_context_pop_animatable_region (context);
10028   gtk_style_context_restore (context);
10029 }
10030
10031 static void
10032 gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view)
10033
10034 {
10035   GtkTreePath *cursor_path;
10036
10037   if ((tree_view->priv->tree == NULL) ||
10038       (! gtk_widget_get_realized (GTK_WIDGET (tree_view))))
10039     return;
10040
10041   cursor_path = NULL;
10042   if (tree_view->priv->cursor)
10043     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
10044
10045   if (cursor_path == NULL)
10046     {
10047       /* Consult the selection before defaulting to the
10048        * first focusable element
10049        */
10050       GList *selected_rows;
10051       GtkTreeModel *model;
10052       GtkTreeSelection *selection;
10053
10054       selection = gtk_tree_view_get_selection (tree_view);
10055       selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
10056
10057       if (selected_rows)
10058         {
10059           cursor_path = gtk_tree_path_copy((const GtkTreePath *)(selected_rows->data));
10060           g_list_foreach (selected_rows, (GFunc)gtk_tree_path_free, NULL);
10061           g_list_free (selected_rows);
10062         }
10063       else
10064         {
10065           cursor_path = gtk_tree_path_new_first ();
10066           search_first_focusable_path (tree_view, &cursor_path,
10067                                        TRUE, NULL, NULL);
10068         }
10069
10070       gtk_tree_row_reference_free (tree_view->priv->cursor);
10071       tree_view->priv->cursor = NULL;
10072
10073       if (cursor_path)
10074         {
10075           if (gtk_tree_selection_get_mode (tree_view->priv->selection) == GTK_SELECTION_MULTIPLE)
10076             gtk_tree_view_real_set_cursor (tree_view, cursor_path, FALSE, FALSE);
10077           else
10078             gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
10079         }
10080     }
10081
10082   if (cursor_path)
10083     {
10084       tree_view->priv->draw_keyfocus = TRUE;
10085
10086       gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
10087       gtk_tree_path_free (cursor_path);
10088
10089       if (tree_view->priv->focus_column == NULL)
10090         {
10091           GList *list;
10092           for (list = tree_view->priv->columns; list; list = list->next)
10093             {
10094               if (gtk_tree_view_column_get_visible (GTK_TREE_VIEW_COLUMN (list->data)))
10095                 {
10096                   GtkCellArea *cell_area;
10097
10098                   tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (list->data);
10099
10100                   /* This happens when the treeview initially grabs focus and there
10101                    * is no column in focus, here we explicitly focus into the first cell */
10102                   cell_area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (tree_view->priv->focus_column));
10103                   if (!gtk_cell_area_get_focus_cell (cell_area))
10104                     {
10105                       gboolean rtl;
10106
10107                       rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
10108                       gtk_cell_area_focus (cell_area,
10109                                            rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT);
10110                     }
10111
10112                   break;
10113                 }
10114             }
10115         }
10116     }
10117 }
10118
10119 static void
10120 gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
10121                                    gint         count)
10122 {
10123   gint selection_count;
10124   GtkRBTree *cursor_tree = NULL;
10125   GtkRBNode *cursor_node = NULL;
10126   GtkRBTree *new_cursor_tree = NULL;
10127   GtkRBNode *new_cursor_node = NULL;
10128   GtkTreePath *cursor_path = NULL;
10129   gboolean grab_focus = TRUE;
10130   gboolean selectable;
10131   GtkDirectionType direction;
10132   GtkCellArea *cell_area = NULL;
10133   GtkCellRenderer *last_focus_cell = NULL;
10134   GtkTreeIter iter;
10135
10136   if (! gtk_widget_has_focus (GTK_WIDGET (tree_view)))
10137     return;
10138
10139   cursor_path = NULL;
10140   if (!gtk_tree_row_reference_valid (tree_view->priv->cursor))
10141     /* FIXME: we lost the cursor; should we get the first? */
10142     return;
10143
10144   cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
10145   _gtk_tree_view_find_node (tree_view, cursor_path,
10146                             &cursor_tree, &cursor_node);
10147
10148   if (cursor_tree == NULL)
10149     /* FIXME: we lost the cursor; should we get the first? */
10150     return;
10151
10152   direction = count < 0 ? GTK_DIR_UP : GTK_DIR_DOWN;
10153
10154   if (tree_view->priv->focus_column)
10155     cell_area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (tree_view->priv->focus_column));
10156
10157   /* If focus stays in the area for this row, then just return for this round */
10158   if (cell_area && (count == -1 || count == 1) &&
10159       gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path))
10160     {
10161       gtk_tree_view_column_cell_set_cell_data (tree_view->priv->focus_column,
10162                                                tree_view->priv->model,
10163                                                &iter,
10164                                                GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT),
10165                                                cursor_node->children?TRUE:FALSE);
10166
10167       /* Save the last cell that had focus, if we hit the end of the view we'll give
10168        * focus back to it. */
10169       last_focus_cell = gtk_cell_area_get_focus_cell (cell_area);
10170
10171       /* If focus stays in the area, no need to change the cursor row */
10172       if (gtk_cell_area_focus (cell_area, direction))
10173         return;
10174     }
10175
10176   selection_count = gtk_tree_selection_count_selected_rows (tree_view->priv->selection);
10177   selectable = _gtk_tree_selection_row_is_selectable (tree_view->priv->selection,
10178                                                       cursor_node,
10179                                                       cursor_path);
10180
10181   if (selection_count == 0
10182       && gtk_tree_selection_get_mode (tree_view->priv->selection) != GTK_SELECTION_NONE
10183       && !tree_view->priv->ctrl_pressed
10184       && selectable)
10185     {
10186       /* Don't move the cursor, but just select the current node */
10187       new_cursor_tree = cursor_tree;
10188       new_cursor_node = cursor_node;
10189     }
10190   else
10191     {
10192       if (count == -1)
10193         _gtk_rbtree_prev_full (cursor_tree, cursor_node,
10194                                &new_cursor_tree, &new_cursor_node);
10195       else
10196         _gtk_rbtree_next_full (cursor_tree, cursor_node,
10197                                &new_cursor_tree, &new_cursor_node);
10198     }
10199
10200   gtk_tree_path_free (cursor_path);
10201
10202   if (new_cursor_node)
10203     {
10204       cursor_path = _gtk_tree_view_find_path (tree_view,
10205                                               new_cursor_tree, new_cursor_node);
10206
10207       search_first_focusable_path (tree_view, &cursor_path,
10208                                    (count != -1),
10209                                    &new_cursor_tree,
10210                                    &new_cursor_node);
10211
10212       if (cursor_path)
10213         gtk_tree_path_free (cursor_path);
10214     }
10215
10216   /*
10217    * If the list has only one item and multi-selection is set then select
10218    * the row (if not yet selected).
10219    */
10220   if (gtk_tree_selection_get_mode (tree_view->priv->selection) == GTK_SELECTION_MULTIPLE &&
10221       new_cursor_node == NULL)
10222     {
10223       if (count == -1)
10224         _gtk_rbtree_next_full (cursor_tree, cursor_node,
10225                                &new_cursor_tree, &new_cursor_node);
10226       else
10227         _gtk_rbtree_prev_full (cursor_tree, cursor_node,
10228                                &new_cursor_tree, &new_cursor_node);
10229
10230       if (new_cursor_node == NULL
10231           && !GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_SELECTED))
10232         {
10233           new_cursor_node = cursor_node;
10234           new_cursor_tree = cursor_tree;
10235         }
10236       else
10237         {
10238           new_cursor_node = NULL;
10239         }
10240     }
10241
10242   if (new_cursor_node)
10243     {
10244       cursor_path = _gtk_tree_view_find_path (tree_view, new_cursor_tree, new_cursor_node);
10245       gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE);
10246       gtk_tree_path_free (cursor_path);
10247
10248       /* Give focus to the area in the new row */
10249       if (cell_area)
10250         gtk_cell_area_focus (cell_area, direction);
10251     }
10252   else
10253     {
10254       gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
10255
10256       if (!tree_view->priv->shift_pressed)
10257         {
10258           if (! gtk_widget_keynav_failed (GTK_WIDGET (tree_view),
10259                                           count < 0 ?
10260                                           GTK_DIR_UP : GTK_DIR_DOWN))
10261             {
10262               GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tree_view));
10263
10264               if (toplevel)
10265                 gtk_widget_child_focus (toplevel,
10266                                         count < 0 ?
10267                                         GTK_DIR_TAB_BACKWARD :
10268                                         GTK_DIR_TAB_FORWARD);
10269
10270               grab_focus = FALSE;
10271             }
10272         }
10273       else
10274         {
10275           gtk_widget_error_bell (GTK_WIDGET (tree_view));
10276         }
10277
10278       if (cell_area)
10279         gtk_cell_area_set_focus_cell (cell_area, last_focus_cell);
10280     }
10281
10282   if (grab_focus)
10283     gtk_widget_grab_focus (GTK_WIDGET (tree_view));
10284 }
10285
10286 static void
10287 gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
10288                                         gint         count)
10289 {
10290   GtkRBTree *cursor_tree = NULL;
10291   GtkRBNode *cursor_node = NULL;
10292   GtkTreePath *old_cursor_path = NULL;
10293   GtkTreePath *cursor_path = NULL;
10294   GtkRBTree *start_cursor_tree = NULL;
10295   GtkRBNode *start_cursor_node = NULL;
10296   gint y;
10297   gint window_y;
10298   gint vertical_separator;
10299
10300   if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
10301     return;
10302
10303   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
10304     old_cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
10305   else
10306     /* This is sorta weird.  Focus in should give us a cursor */
10307     return;
10308
10309   gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical-separator", &vertical_separator, NULL);
10310   _gtk_tree_view_find_node (tree_view, old_cursor_path,
10311                             &cursor_tree, &cursor_node);
10312
10313   if (cursor_tree == NULL)
10314     {
10315       /* FIXME: we lost the cursor.  Should we try to get one? */
10316       gtk_tree_path_free (old_cursor_path);
10317       return;
10318     }
10319   g_return_if_fail (cursor_node != NULL);
10320
10321   y = _gtk_rbtree_node_find_offset (cursor_tree, cursor_node);
10322   window_y = RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, y);
10323   y += tree_view->priv->cursor_offset;
10324   y += count * (int)gtk_adjustment_get_page_increment (tree_view->priv->vadjustment);
10325   y = CLAMP (y, (gint)gtk_adjustment_get_lower (tree_view->priv->vadjustment),  (gint)gtk_adjustment_get_upper (tree_view->priv->vadjustment) - vertical_separator);
10326
10327   if (y >= tree_view->priv->height)
10328     y = tree_view->priv->height - 1;
10329
10330   tree_view->priv->cursor_offset =
10331     _gtk_rbtree_find_offset (tree_view->priv->tree, y,
10332                              &cursor_tree, &cursor_node);
10333
10334   if (cursor_tree == NULL)
10335     {
10336       /* FIXME: we lost the cursor.  Should we try to get one? */
10337       gtk_tree_path_free (old_cursor_path);
10338       return;
10339     }
10340
10341   if (tree_view->priv->cursor_offset
10342       > gtk_tree_view_get_row_height (tree_view, cursor_node))
10343     {
10344       _gtk_rbtree_next_full (cursor_tree, cursor_node,
10345                              &cursor_tree, &cursor_node);
10346       tree_view->priv->cursor_offset -= gtk_tree_view_get_row_height (tree_view, cursor_node);
10347     }
10348
10349   y -= tree_view->priv->cursor_offset;
10350   cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
10351
10352   start_cursor_tree = cursor_tree;
10353   start_cursor_node = cursor_node;
10354
10355   if (! search_first_focusable_path (tree_view, &cursor_path,
10356                                      (count != -1),
10357                                      &cursor_tree, &cursor_node))
10358     {
10359       /* It looks like we reached the end of the view without finding
10360        * a focusable row.  We will step backwards to find the last
10361        * focusable row.
10362        */
10363       cursor_tree = start_cursor_tree;
10364       cursor_node = start_cursor_node;
10365       cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
10366
10367       search_first_focusable_path (tree_view, &cursor_path,
10368                                    (count == -1),
10369                                    &cursor_tree, &cursor_node);
10370     }
10371
10372   if (!cursor_path)
10373     goto cleanup;
10374
10375   /* update y */
10376   y = _gtk_rbtree_node_find_offset (cursor_tree, cursor_node);
10377
10378   gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
10379
10380   y -= window_y;
10381   gtk_tree_view_scroll_to_point (tree_view, -1, y);
10382   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
10383   _gtk_tree_view_queue_draw_node (tree_view, cursor_tree, cursor_node, NULL);
10384
10385   if (!gtk_tree_path_compare (old_cursor_path, cursor_path))
10386     gtk_widget_error_bell (GTK_WIDGET (tree_view));
10387
10388   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
10389
10390 cleanup:
10391   gtk_tree_path_free (old_cursor_path);
10392   gtk_tree_path_free (cursor_path);
10393 }
10394
10395 static void
10396 gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
10397                                       gint         count)
10398 {
10399   GtkRBTree *cursor_tree = NULL;
10400   GtkRBNode *cursor_node = NULL;
10401   GtkTreePath *cursor_path = NULL;
10402   GtkTreeViewColumn *column;
10403   GtkTreeIter iter;
10404   GList *list;
10405   gboolean found_column = FALSE;
10406   gboolean rtl;
10407   GtkDirectionType direction;
10408   GtkCellArea     *cell_area;
10409   GtkCellRenderer *last_focus_cell = NULL;
10410   GtkCellArea     *last_focus_area = NULL;
10411
10412   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
10413
10414   if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
10415     return;
10416
10417   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
10418     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
10419   else
10420     return;
10421
10422   _gtk_tree_view_find_node (tree_view, cursor_path, &cursor_tree, &cursor_node);
10423   if (cursor_tree == NULL)
10424     return;
10425   if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path) == FALSE)
10426     {
10427       gtk_tree_path_free (cursor_path);
10428       return;
10429     }
10430   gtk_tree_path_free (cursor_path);
10431
10432   list = rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns);
10433   if (tree_view->priv->focus_column)
10434     {
10435       /* Save the cell/area we are moving focus from, if moving the cursor
10436        * by one step hits the end we'll set focus back here */
10437       last_focus_area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (tree_view->priv->focus_column));
10438       last_focus_cell = gtk_cell_area_get_focus_cell (last_focus_area);
10439
10440       for (; list; list = (rtl ? list->prev : list->next))
10441         {
10442           if (list->data == tree_view->priv->focus_column)
10443             break;
10444         }
10445     }
10446
10447   direction = count > 0 ? GTK_DIR_RIGHT : GTK_DIR_LEFT;
10448
10449   while (list)
10450     {
10451       column = list->data;
10452       if (gtk_tree_view_column_get_visible (column) == FALSE)
10453         goto loop_end;
10454
10455       gtk_tree_view_column_cell_set_cell_data (column,
10456                                                tree_view->priv->model,
10457                                                &iter,
10458                                                GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT),
10459                                                cursor_node->children?TRUE:FALSE);
10460
10461       cell_area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (column));
10462       if (gtk_cell_area_focus (cell_area, direction))
10463         {
10464           tree_view->priv->focus_column = column;
10465           found_column = TRUE;
10466           break;
10467         }
10468
10469     loop_end:
10470       if (count == 1)
10471         list = rtl ? list->prev : list->next;
10472       else
10473         list = rtl ? list->next : list->prev;
10474     }
10475
10476   if (found_column)
10477     {
10478       if (!gtk_tree_view_has_can_focus_cell (tree_view))
10479         _gtk_tree_view_queue_draw_node (tree_view,
10480                                         cursor_tree,
10481                                         cursor_node,
10482                                         NULL);
10483       g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
10484       gtk_widget_grab_focus (GTK_WIDGET (tree_view));
10485     }
10486   else
10487     {
10488       gtk_widget_error_bell (GTK_WIDGET (tree_view));
10489
10490       if (last_focus_area)
10491         gtk_cell_area_set_focus_cell (last_focus_area, last_focus_cell);
10492     }
10493
10494   gtk_tree_view_clamp_column_visible (tree_view,
10495                                       tree_view->priv->focus_column, TRUE);
10496 }
10497
10498 static void
10499 gtk_tree_view_move_cursor_start_end (GtkTreeView *tree_view,
10500                                      gint         count)
10501 {
10502   GtkRBTree *cursor_tree;
10503   GtkRBNode *cursor_node;
10504   GtkTreePath *path;
10505   GtkTreePath *old_path;
10506
10507   if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
10508     return;
10509
10510   g_return_if_fail (tree_view->priv->tree != NULL);
10511
10512   gtk_tree_view_get_cursor (tree_view, &old_path, NULL);
10513
10514   cursor_tree = tree_view->priv->tree;
10515   cursor_node = cursor_tree->root;
10516
10517   if (count == -1)
10518     {
10519       while (cursor_node && cursor_node->left != cursor_tree->nil)
10520         cursor_node = cursor_node->left;
10521
10522       /* Now go forward to find the first focusable row. */
10523       path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
10524       search_first_focusable_path (tree_view, &path,
10525                                    TRUE, &cursor_tree, &cursor_node);
10526     }
10527   else
10528     {
10529       do
10530         {
10531           while (cursor_node && cursor_node->right != cursor_tree->nil)
10532             cursor_node = cursor_node->right;
10533           if (cursor_node->children == NULL)
10534             break;
10535
10536           cursor_tree = cursor_node->children;
10537           cursor_node = cursor_tree->root;
10538         }
10539       while (1);
10540
10541       /* Now go backwards to find last focusable row. */
10542       path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
10543       search_first_focusable_path (tree_view, &path,
10544                                    FALSE, &cursor_tree, &cursor_node);
10545     }
10546
10547   if (!path)
10548     goto cleanup;
10549
10550   if (gtk_tree_path_compare (old_path, path))
10551     {
10552       gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
10553       gtk_widget_grab_focus (GTK_WIDGET (tree_view));
10554     }
10555   else
10556     {
10557       gtk_widget_error_bell (GTK_WIDGET (tree_view));
10558     }
10559
10560 cleanup:
10561   gtk_tree_path_free (old_path);
10562   gtk_tree_path_free (path);
10563 }
10564
10565 static gboolean
10566 gtk_tree_view_real_select_all (GtkTreeView *tree_view)
10567 {
10568   if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
10569     return FALSE;
10570
10571   if (gtk_tree_selection_get_mode (tree_view->priv->selection) != GTK_SELECTION_MULTIPLE)
10572     return FALSE;
10573
10574   gtk_tree_selection_select_all (tree_view->priv->selection);
10575
10576   return TRUE;
10577 }
10578
10579 static gboolean
10580 gtk_tree_view_real_unselect_all (GtkTreeView *tree_view)
10581 {
10582   if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
10583     return FALSE;
10584
10585   if (gtk_tree_selection_get_mode (tree_view->priv->selection) != GTK_SELECTION_MULTIPLE)
10586     return FALSE;
10587
10588   gtk_tree_selection_unselect_all (tree_view->priv->selection);
10589
10590   return TRUE;
10591 }
10592
10593 static gboolean
10594 gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view,
10595                                       gboolean     start_editing)
10596 {
10597   GtkRBTree *new_tree = NULL;
10598   GtkRBNode *new_node = NULL;
10599   GtkRBTree *cursor_tree = NULL;
10600   GtkRBNode *cursor_node = NULL;
10601   GtkTreePath *cursor_path = NULL;
10602   GtkTreeSelectMode mode = 0;
10603
10604   if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
10605     return FALSE;
10606
10607   if (tree_view->priv->cursor)
10608     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
10609
10610   if (cursor_path == NULL)
10611     return FALSE;
10612
10613   _gtk_tree_view_find_node (tree_view, cursor_path,
10614                             &cursor_tree, &cursor_node);
10615
10616   if (cursor_tree == NULL)
10617     {
10618       gtk_tree_path_free (cursor_path);
10619       return FALSE;
10620     }
10621
10622   if (!tree_view->priv->shift_pressed && start_editing &&
10623       tree_view->priv->focus_column)
10624     {
10625       if (gtk_tree_view_start_editing (tree_view, cursor_path, FALSE))
10626         {
10627           gtk_tree_path_free (cursor_path);
10628           return TRUE;
10629         }
10630     }
10631
10632   if (tree_view->priv->ctrl_pressed)
10633     mode |= GTK_TREE_SELECT_MODE_TOGGLE;
10634   if (tree_view->priv->shift_pressed)
10635     mode |= GTK_TREE_SELECT_MODE_EXTEND;
10636
10637   _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
10638                                             cursor_node,
10639                                             cursor_tree,
10640                                             cursor_path,
10641                                             mode,
10642                                             FALSE);
10643
10644   /* We bail out if the original (tree, node) don't exist anymore after
10645    * handling the selection-changed callback.  We do return TRUE because
10646    * the key press has been handled at this point.
10647    */
10648   _gtk_tree_view_find_node (tree_view, cursor_path, &new_tree, &new_node);
10649
10650   if (cursor_tree != new_tree || cursor_node != new_node)
10651     return FALSE;
10652
10653   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
10654
10655   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
10656   _gtk_tree_view_queue_draw_node (tree_view, cursor_tree, cursor_node, NULL);
10657
10658   if (!tree_view->priv->shift_pressed)
10659     gtk_tree_view_row_activated (tree_view, cursor_path,
10660                                  tree_view->priv->focus_column);
10661     
10662   gtk_tree_path_free (cursor_path);
10663
10664   return TRUE;
10665 }
10666
10667 static gboolean
10668 gtk_tree_view_real_toggle_cursor_row (GtkTreeView *tree_view)
10669 {
10670   GtkRBTree *new_tree = NULL;
10671   GtkRBNode *new_node = NULL;
10672   GtkRBTree *cursor_tree = NULL;
10673   GtkRBNode *cursor_node = NULL;
10674   GtkTreePath *cursor_path = NULL;
10675
10676   if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
10677     return FALSE;
10678
10679   cursor_path = NULL;
10680   if (tree_view->priv->cursor)
10681     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
10682
10683   if (cursor_path == NULL)
10684     return FALSE;
10685
10686   _gtk_tree_view_find_node (tree_view, cursor_path,
10687                             &cursor_tree, &cursor_node);
10688   if (cursor_tree == NULL)
10689     {
10690       gtk_tree_path_free (cursor_path);
10691       return FALSE;
10692     }
10693
10694   _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
10695                                             cursor_node,
10696                                             cursor_tree,
10697                                             cursor_path,
10698                                             GTK_TREE_SELECT_MODE_TOGGLE,
10699                                             FALSE);
10700
10701   /* We bail out if the original (tree, node) don't exist anymore after
10702    * handling the selection-changed callback.  We do return TRUE because
10703    * the key press has been handled at this point.
10704    */
10705   _gtk_tree_view_find_node (tree_view, cursor_path, &new_tree, &new_node);
10706
10707   if (cursor_tree != new_tree || cursor_node != new_node)
10708     return FALSE;
10709
10710   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
10711
10712   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
10713   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
10714   gtk_tree_path_free (cursor_path);
10715
10716   return TRUE;
10717 }
10718
10719 static gboolean
10720 gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView *tree_view,
10721                                                gboolean     logical,
10722                                                gboolean     expand,
10723                                                gboolean     open_all)
10724 {
10725   GtkTreePath *cursor_path = NULL;
10726   GtkRBTree *tree;
10727   GtkRBNode *node;
10728
10729   if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
10730     return FALSE;
10731
10732   cursor_path = NULL;
10733   if (tree_view->priv->cursor)
10734     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
10735
10736   if (cursor_path == NULL)
10737     return FALSE;
10738
10739   if (_gtk_tree_view_find_node (tree_view, cursor_path, &tree, &node))
10740     return FALSE;
10741
10742   /* Don't handle the event if we aren't an expander */
10743   if (!((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT))
10744     return FALSE;
10745
10746   if (!logical
10747       && gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL)
10748     expand = !expand;
10749
10750   if (expand)
10751     gtk_tree_view_real_expand_row (tree_view, cursor_path, tree, node, open_all, TRUE);
10752   else
10753     gtk_tree_view_real_collapse_row (tree_view, cursor_path, tree, node, TRUE);
10754
10755   gtk_tree_path_free (cursor_path);
10756
10757   return TRUE;
10758 }
10759
10760 static gboolean
10761 gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
10762 {
10763   GtkRBTree *cursor_tree = NULL;
10764   GtkRBNode *cursor_node = NULL;
10765   GtkTreePath *cursor_path = NULL;
10766   GdkModifierType state;
10767
10768   if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
10769     goto out;
10770
10771   cursor_path = NULL;
10772   if (tree_view->priv->cursor)
10773     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
10774
10775   if (cursor_path == NULL)
10776     goto out;
10777
10778   _gtk_tree_view_find_node (tree_view, cursor_path,
10779                             &cursor_tree, &cursor_node);
10780   if (cursor_tree == NULL)
10781     {
10782       gtk_tree_path_free (cursor_path);
10783       goto out;
10784     }
10785
10786   if (cursor_tree->parent_node)
10787     {
10788       gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
10789       cursor_node = cursor_tree->parent_node;
10790       cursor_tree = cursor_tree->parent_tree;
10791
10792       gtk_tree_path_up (cursor_path);
10793
10794       if (gtk_get_current_event_state (&state))
10795         {
10796           if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
10797             tree_view->priv->ctrl_pressed = TRUE;
10798         }
10799
10800       gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
10801       gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
10802
10803       gtk_widget_grab_focus (GTK_WIDGET (tree_view));
10804       gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
10805       gtk_tree_path_free (cursor_path);
10806
10807       tree_view->priv->ctrl_pressed = FALSE;
10808
10809       return TRUE;
10810     }
10811
10812  out:
10813
10814   tree_view->priv->search_entry_avoid_unhandled_binding = TRUE;
10815   return FALSE;
10816 }
10817
10818 static gboolean
10819 gtk_tree_view_search_entry_flush_timeout (GtkTreeView *tree_view)
10820 {
10821   gtk_tree_view_search_dialog_hide (tree_view->priv->search_window, tree_view, NULL);
10822   tree_view->priv->typeselect_flush_timeout = 0;
10823
10824   return FALSE;
10825 }
10826
10827 /* Cut and paste from gtkwindow.c */
10828 static void
10829 send_focus_change (GtkWidget *widget,
10830                    GdkDevice *device,
10831                    gboolean   in)
10832 {
10833   GdkDeviceManager *device_manager;
10834   GList *devices, *d;
10835
10836   device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
10837   devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
10838   devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
10839   devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
10840
10841   for (d = devices; d; d = d->next)
10842     {
10843       GdkDevice *dev = d->data;
10844       GdkEvent *fevent;
10845       GdkWindow *window;
10846
10847       if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
10848         continue;
10849
10850       window = gtk_widget_get_window (widget);
10851
10852       /* Skip non-master keyboards that haven't
10853        * selected for events from this window
10854        */
10855       if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
10856           !gdk_window_get_device_events (window, dev))
10857         continue;
10858
10859       fevent = gdk_event_new (GDK_FOCUS_CHANGE);
10860
10861       fevent->focus_change.type = GDK_FOCUS_CHANGE;
10862       fevent->focus_change.window = g_object_ref (window);
10863       fevent->focus_change.in = in;
10864       gdk_event_set_device (fevent, device);
10865
10866       gtk_widget_send_focus_change (widget, fevent);
10867
10868       gdk_event_free (fevent);
10869     }
10870
10871   g_list_free (devices);
10872 }
10873
10874 static void
10875 gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view)
10876 {
10877   GtkWidget *frame, *vbox, *toplevel;
10878   GdkScreen *screen;
10879
10880   if (tree_view->priv->search_custom_entry_set)
10881     return;
10882
10883   toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tree_view));
10884   screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
10885
10886    if (tree_view->priv->search_window != NULL)
10887      {
10888        if (gtk_window_has_group (GTK_WINDOW (toplevel)))
10889          gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)),
10890                                       GTK_WINDOW (tree_view->priv->search_window));
10891        else if (gtk_window_has_group (GTK_WINDOW (tree_view->priv->search_window)))
10892          gtk_window_group_remove_window (gtk_window_get_group (GTK_WINDOW (tree_view->priv->search_window)),
10893                                          GTK_WINDOW (tree_view->priv->search_window));
10894
10895        gtk_window_set_screen (GTK_WINDOW (tree_view->priv->search_window), screen);
10896
10897        return;
10898      }
10899    
10900   tree_view->priv->search_window = gtk_window_new (GTK_WINDOW_POPUP);
10901   gtk_window_set_screen (GTK_WINDOW (tree_view->priv->search_window), screen);
10902
10903   if (gtk_window_has_group (GTK_WINDOW (toplevel)))
10904     gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)),
10905                                  GTK_WINDOW (tree_view->priv->search_window));
10906
10907   gtk_window_set_type_hint (GTK_WINDOW (tree_view->priv->search_window),
10908                             GDK_WINDOW_TYPE_HINT_UTILITY);
10909   gtk_window_set_modal (GTK_WINDOW (tree_view->priv->search_window), TRUE);
10910   g_signal_connect (tree_view->priv->search_window, "delete-event",
10911                     G_CALLBACK (gtk_tree_view_search_delete_event),
10912                     tree_view);
10913   g_signal_connect (tree_view->priv->search_window, "key-press-event",
10914                     G_CALLBACK (gtk_tree_view_search_key_press_event),
10915                     tree_view);
10916   g_signal_connect (tree_view->priv->search_window, "button-press-event",
10917                     G_CALLBACK (gtk_tree_view_search_button_press_event),
10918                     tree_view);
10919   g_signal_connect (tree_view->priv->search_window, "scroll-event",
10920                     G_CALLBACK (gtk_tree_view_search_scroll_event),
10921                     tree_view);
10922
10923   frame = gtk_frame_new (NULL);
10924   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
10925   gtk_widget_show (frame);
10926   gtk_container_add (GTK_CONTAINER (tree_view->priv->search_window), frame);
10927
10928   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
10929   gtk_widget_show (vbox);
10930   gtk_container_add (GTK_CONTAINER (frame), vbox);
10931   gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);
10932
10933   /* add entry */
10934   tree_view->priv->search_entry = gtk_entry_new ();
10935   gtk_widget_show (tree_view->priv->search_entry);
10936   g_signal_connect (tree_view->priv->search_entry, "populate-popup",
10937                     G_CALLBACK (gtk_tree_view_search_disable_popdown),
10938                     tree_view);
10939   g_signal_connect (tree_view->priv->search_entry,
10940                     "activate", G_CALLBACK (gtk_tree_view_search_activate),
10941                     tree_view);
10942
10943   g_signal_connect (_gtk_entry_get_im_context (GTK_ENTRY (tree_view->priv->search_entry)),
10944                     "preedit-changed",
10945                     G_CALLBACK (gtk_tree_view_search_preedit_changed),
10946                     tree_view);
10947
10948   gtk_container_add (GTK_CONTAINER (vbox),
10949                      tree_view->priv->search_entry);
10950
10951   gtk_widget_realize (tree_view->priv->search_entry);
10952 }
10953
10954 /* Pops up the interactive search entry.  If keybinding is TRUE then the user
10955  * started this by typing the start_interactive_search keybinding.  Otherwise, it came from 
10956  */
10957 static gboolean
10958 gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view,
10959                                              GdkDevice   *device,
10960                                              gboolean     keybinding)
10961 {
10962   /* We only start interactive search if we have focus or the columns
10963    * have focus.  If one of our children have focus, we don't want to
10964    * start the search.
10965    */
10966   GList *list;
10967   gboolean found_focus = FALSE;
10968   GtkWidgetClass *entry_parent_class;
10969   
10970   if (!tree_view->priv->enable_search && !keybinding)
10971     return FALSE;
10972
10973   if (tree_view->priv->search_custom_entry_set)
10974     return FALSE;
10975
10976   if (tree_view->priv->search_window != NULL &&
10977       gtk_widget_get_visible (tree_view->priv->search_window))
10978     return TRUE;
10979
10980   for (list = tree_view->priv->columns; list; list = list->next)
10981     {
10982       GtkTreeViewColumn *column;
10983       GtkWidget         *button;
10984
10985       column = list->data;
10986       if (!gtk_tree_view_column_get_visible (column))
10987         continue;
10988
10989       button = gtk_tree_view_column_get_button (column);
10990       if (gtk_widget_has_focus (button))
10991         {
10992           found_focus = TRUE;
10993           break;
10994         }
10995     }
10996   
10997   if (gtk_widget_has_focus (GTK_WIDGET (tree_view)))
10998     found_focus = TRUE;
10999
11000   if (!found_focus)
11001     return FALSE;
11002
11003   if (tree_view->priv->search_column < 0)
11004     return FALSE;
11005
11006   gtk_tree_view_ensure_interactive_directory (tree_view);
11007
11008   if (keybinding)
11009     gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
11010
11011   /* done, show it */
11012   tree_view->priv->search_position_func (tree_view, tree_view->priv->search_window, tree_view->priv->search_position_user_data);
11013   gtk_widget_show (tree_view->priv->search_window);
11014   if (tree_view->priv->search_entry_changed_id == 0)
11015     {
11016       tree_view->priv->search_entry_changed_id =
11017         g_signal_connect (tree_view->priv->search_entry, "changed",
11018                           G_CALLBACK (gtk_tree_view_search_init),
11019                           tree_view);
11020     }
11021
11022   tree_view->priv->typeselect_flush_timeout =
11023     gdk_threads_add_timeout (GTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT,
11024                    (GSourceFunc) gtk_tree_view_search_entry_flush_timeout,
11025                    tree_view);
11026
11027   /* Grab focus will select all the text.  We don't want that to happen, so we
11028    * call the parent instance and bypass the selection change.  This is probably
11029    * really non-kosher. */
11030   entry_parent_class = g_type_class_peek_parent (GTK_ENTRY_GET_CLASS (tree_view->priv->search_entry));
11031   (entry_parent_class->grab_focus) (tree_view->priv->search_entry);
11032
11033   /* send focus-in event */
11034   send_focus_change (tree_view->priv->search_entry, device, TRUE);
11035
11036   /* search first matching iter */
11037   gtk_tree_view_search_init (tree_view->priv->search_entry, tree_view);
11038
11039   return TRUE;
11040 }
11041
11042 static gboolean
11043 gtk_tree_view_start_interactive_search (GtkTreeView *tree_view)
11044 {
11045   return gtk_tree_view_real_start_interactive_search (tree_view,
11046                                                       gtk_get_current_event_device (),
11047                                                       TRUE);
11048 }
11049
11050 /* this function returns the new width of the column being resized given
11051  * the column and x position of the cursor; the x cursor position is passed
11052  * in as a pointer and automagicly corrected if it's beyond min/max limits
11053  */
11054 static gint
11055 gtk_tree_view_new_column_width (GtkTreeView *tree_view,
11056                                 gint       i,
11057                                 gint      *x)
11058 {
11059   GtkAllocation allocation;
11060   GtkTreeViewColumn *column;
11061   GtkRequisition button_req;
11062   gint max_width, min_width;
11063   gint width;
11064   gboolean rtl;
11065
11066   /* first translate the x position from widget->window
11067    * to clist->clist_window
11068    */
11069   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
11070   column = g_list_nth (tree_view->priv->columns, i)->data;
11071   gtk_widget_get_allocation (gtk_tree_view_column_get_button (column), &allocation);
11072   width = rtl ? (allocation.x + allocation.width - *x) : (*x - allocation.x);
11073
11074   /* Clamp down the value */
11075   min_width = gtk_tree_view_column_get_min_width (column);
11076   if (min_width == -1)
11077     {
11078       gtk_widget_get_preferred_size (gtk_tree_view_column_get_button (column), &button_req, NULL);
11079       width = MAX (button_req.width, width);
11080     }
11081   else
11082     width = MAX (min_width, width);
11083
11084   max_width = gtk_tree_view_column_get_max_width (column);
11085   if (max_width != -1)
11086     width = MIN (width, max_width);
11087
11088   *x = rtl ? (allocation.x + allocation.width - width) : (allocation.x + width);
11089
11090   return width;
11091 }
11092
11093
11094 /* FIXME this adjust_allocation is a big cut-and-paste from
11095  * GtkCList, needs to be some "official" way to do this
11096  * factored out.
11097  */
11098 typedef struct
11099 {
11100   GdkWindow *window;
11101   int dx;
11102   int dy;
11103 } ScrollData;
11104
11105 /* The window to which widget->window is relative */
11106 #define ALLOCATION_WINDOW(widget)               \
11107    (!gtk_widget_get_has_window (widget) ?                   \
11108     gtk_widget_get_window (widget) :                        \
11109     gdk_window_get_parent (gtk_widget_get_window (widget)))
11110
11111 static void
11112 adjust_allocation_recurse (GtkWidget *widget,
11113                            gpointer   data)
11114 {
11115   GtkAllocation allocation;
11116   ScrollData *scroll_data = data;
11117
11118   /* Need to really size allocate instead of just poking
11119    * into widget->allocation if the widget is not realized.
11120    * FIXME someone figure out why this was.
11121    */
11122   gtk_widget_get_allocation (widget, &allocation);
11123   if (!gtk_widget_get_realized (widget))
11124     {
11125       if (gtk_widget_get_visible (widget))
11126         {
11127           GdkRectangle tmp_rectangle = allocation;
11128           tmp_rectangle.x += scroll_data->dx;
11129           tmp_rectangle.y += scroll_data->dy;
11130           
11131           gtk_widget_size_allocate (widget, &tmp_rectangle);
11132         }
11133     }
11134   else
11135     {
11136       if (ALLOCATION_WINDOW (widget) == scroll_data->window)
11137         {
11138           allocation.x += scroll_data->dx;
11139           allocation.y += scroll_data->dy;
11140           gtk_widget_set_allocation (widget, &allocation);
11141
11142           if (GTK_IS_CONTAINER (widget))
11143             gtk_container_forall (GTK_CONTAINER (widget),
11144                                   adjust_allocation_recurse,
11145                                   data);
11146         }
11147     }
11148 }
11149
11150 static void
11151 adjust_allocation (GtkWidget *widget,
11152                    int        dx,
11153                    int        dy)
11154 {
11155   ScrollData scroll_data;
11156
11157   if (gtk_widget_get_realized (widget))
11158     scroll_data.window = ALLOCATION_WINDOW (widget);
11159   else
11160     scroll_data.window = NULL;
11161     
11162   scroll_data.dx = dx;
11163   scroll_data.dy = dy;
11164   
11165   adjust_allocation_recurse (widget, &scroll_data);
11166 }
11167
11168 /* Callbacks */
11169 static void
11170 gtk_tree_view_adjustment_changed (GtkAdjustment *adjustment,
11171                                   GtkTreeView   *tree_view)
11172 {
11173   if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
11174     {
11175       GtkStyleContext *context;
11176       gint dy;
11177         
11178       gdk_window_move (tree_view->priv->bin_window,
11179                        - gtk_adjustment_get_value (tree_view->priv->hadjustment),
11180                        gtk_tree_view_get_effective_header_height (tree_view));
11181       gdk_window_move (tree_view->priv->header_window,
11182                        - gtk_adjustment_get_value (tree_view->priv->hadjustment),
11183                        0);
11184       dy = tree_view->priv->dy - (int) gtk_adjustment_get_value (tree_view->priv->vadjustment);
11185       if (dy)
11186         {
11187           update_prelight (tree_view,
11188                            tree_view->priv->event_last_x,
11189                            tree_view->priv->event_last_y - dy);
11190
11191           if (tree_view->priv->edited_column)
11192             {
11193               GList *list;
11194               GtkTreeViewChild *child = NULL;
11195               GtkCellEditable *edit_widget;
11196               GtkCellArea *area;
11197
11198               area        = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (tree_view->priv->edited_column));
11199               edit_widget = gtk_cell_area_get_edit_widget (area);
11200               if (GTK_IS_WIDGET (edit_widget))
11201                 {
11202                   adjust_allocation (GTK_WIDGET (edit_widget), 0, dy);
11203
11204                   for (list = tree_view->priv->children; list; list = list->next)
11205                     {
11206                       child = (GtkTreeViewChild *)list->data;
11207                       if (child->widget == GTK_WIDGET (edit_widget))
11208                         {
11209                           child->y += dy;
11210                           break;
11211                         }
11212                     }
11213                 }
11214             }
11215         }
11216       gdk_window_scroll (tree_view->priv->bin_window, 0, dy);
11217
11218       context = gtk_widget_get_style_context (GTK_WIDGET (tree_view));
11219       gtk_style_context_scroll_animations (context, tree_view->priv->bin_window, 0, dy);
11220
11221       if (tree_view->priv->dy != (int) gtk_adjustment_get_value (tree_view->priv->vadjustment))
11222         {
11223           /* update our dy and top_row */
11224           tree_view->priv->dy = (int) gtk_adjustment_get_value (tree_view->priv->vadjustment);
11225
11226           if (!tree_view->priv->in_top_row_to_dy)
11227             gtk_tree_view_dy_to_top_row (tree_view);
11228         }
11229
11230       gdk_window_process_updates (tree_view->priv->header_window, TRUE);
11231       gtk_tree_view_bin_process_updates (tree_view);
11232     }
11233 }
11234
11235 \f
11236
11237 /* Public methods
11238  */
11239
11240 /**
11241  * gtk_tree_view_new:
11242  *
11243  * Creates a new #GtkTreeView widget.
11244  *
11245  * Return value: A newly created #GtkTreeView widget.
11246  **/
11247 GtkWidget *
11248 gtk_tree_view_new (void)
11249 {
11250   return g_object_new (GTK_TYPE_TREE_VIEW, NULL);
11251 }
11252
11253 /**
11254  * gtk_tree_view_new_with_model:
11255  * @model: the model.
11256  *
11257  * Creates a new #GtkTreeView widget with the model initialized to @model.
11258  *
11259  * Return value: A newly created #GtkTreeView widget.
11260  **/
11261 GtkWidget *
11262 gtk_tree_view_new_with_model (GtkTreeModel *model)
11263 {
11264   return g_object_new (GTK_TYPE_TREE_VIEW, "model", model, NULL);
11265 }
11266
11267 /* Public Accessors
11268  */
11269
11270 /**
11271  * gtk_tree_view_get_model:
11272  * @tree_view: a #GtkTreeView
11273  *
11274  * Returns the model the #GtkTreeView is based on.  Returns %NULL if the
11275  * model is unset.
11276  *
11277  * Return value: (transfer none): A #GtkTreeModel, or %NULL if none is currently being used.
11278  **/
11279 GtkTreeModel *
11280 gtk_tree_view_get_model (GtkTreeView *tree_view)
11281 {
11282   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
11283
11284   return tree_view->priv->model;
11285 }
11286
11287 /**
11288  * gtk_tree_view_set_model:
11289  * @tree_view: A #GtkTreeNode.
11290  * @model: (allow-none): The model.
11291  *
11292  * Sets the model for a #GtkTreeView.  If the @tree_view already has a model
11293  * set, it will remove it before setting the new model.  If @model is %NULL,
11294  * then it will unset the old model.
11295  **/
11296 void
11297 gtk_tree_view_set_model (GtkTreeView  *tree_view,
11298                          GtkTreeModel *model)
11299 {
11300   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
11301   g_return_if_fail (model == NULL || GTK_IS_TREE_MODEL (model));
11302
11303   if (model == tree_view->priv->model)
11304     return;
11305
11306   if (tree_view->priv->scroll_to_path)
11307     {
11308       gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
11309       tree_view->priv->scroll_to_path = NULL;
11310     }
11311
11312   if (tree_view->priv->model)
11313     {
11314       GList *tmplist = tree_view->priv->columns;
11315       GtkStyleContext *context;
11316
11317       gtk_tree_view_unref_and_check_selection_tree (tree_view, tree_view->priv->tree);
11318       gtk_tree_view_stop_editing (tree_view, TRUE);
11319
11320       context = gtk_widget_get_style_context (GTK_WIDGET (tree_view));
11321       gtk_style_context_cancel_animations (context, NULL);
11322
11323       g_signal_handlers_disconnect_by_func (tree_view->priv->model,
11324                                             gtk_tree_view_row_changed,
11325                                             tree_view);
11326       g_signal_handlers_disconnect_by_func (tree_view->priv->model,
11327                                             gtk_tree_view_row_inserted,
11328                                             tree_view);
11329       g_signal_handlers_disconnect_by_func (tree_view->priv->model,
11330                                             gtk_tree_view_row_has_child_toggled,
11331                                             tree_view);
11332       g_signal_handlers_disconnect_by_func (tree_view->priv->model,
11333                                             gtk_tree_view_row_deleted,
11334                                             tree_view);
11335       g_signal_handlers_disconnect_by_func (tree_view->priv->model,
11336                                             gtk_tree_view_rows_reordered,
11337                                             tree_view);
11338
11339       for (; tmplist; tmplist = tmplist->next)
11340         _gtk_tree_view_column_unset_model (tmplist->data,
11341                                            tree_view->priv->model);
11342
11343       if (tree_view->priv->tree)
11344         gtk_tree_view_free_rbtree (tree_view);
11345
11346       gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
11347       tree_view->priv->drag_dest_row = NULL;
11348       gtk_tree_row_reference_free (tree_view->priv->cursor);
11349       tree_view->priv->cursor = NULL;
11350       gtk_tree_row_reference_free (tree_view->priv->anchor);
11351       tree_view->priv->anchor = NULL;
11352       gtk_tree_row_reference_free (tree_view->priv->top_row);
11353       tree_view->priv->top_row = NULL;
11354       gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
11355       tree_view->priv->scroll_to_path = NULL;
11356
11357       tree_view->priv->scroll_to_column = NULL;
11358
11359       g_object_unref (tree_view->priv->model);
11360
11361       tree_view->priv->search_column = -1;
11362       tree_view->priv->fixed_height_check = 0;
11363       tree_view->priv->fixed_height = -1;
11364       tree_view->priv->dy = tree_view->priv->top_row_dy = 0;
11365       tree_view->priv->last_button_x = -1;
11366       tree_view->priv->last_button_y = -1;
11367     }
11368
11369   tree_view->priv->model = model;
11370
11371   if (tree_view->priv->model)
11372     {
11373       gint i;
11374       GtkTreePath *path;
11375       GtkTreeIter iter;
11376       GtkTreeModelFlags flags;
11377
11378       if (tree_view->priv->search_column == -1)
11379         {
11380           for (i = 0; i < gtk_tree_model_get_n_columns (model); i++)
11381             {
11382               GType type = gtk_tree_model_get_column_type (model, i);
11383
11384               if (g_value_type_transformable (type, G_TYPE_STRING))
11385                 {
11386                   tree_view->priv->search_column = i;
11387                   break;
11388                 }
11389             }
11390         }
11391
11392       g_object_ref (tree_view->priv->model);
11393       g_signal_connect (tree_view->priv->model,
11394                         "row-changed",
11395                         G_CALLBACK (gtk_tree_view_row_changed),
11396                         tree_view);
11397       g_signal_connect (tree_view->priv->model,
11398                         "row-inserted",
11399                         G_CALLBACK (gtk_tree_view_row_inserted),
11400                         tree_view);
11401       g_signal_connect (tree_view->priv->model,
11402                         "row-has-child-toggled",
11403                         G_CALLBACK (gtk_tree_view_row_has_child_toggled),
11404                         tree_view);
11405       g_signal_connect (tree_view->priv->model,
11406                         "row-deleted",
11407                         G_CALLBACK (gtk_tree_view_row_deleted),
11408                         tree_view);
11409       g_signal_connect (tree_view->priv->model,
11410                         "rows-reordered",
11411                         G_CALLBACK (gtk_tree_view_rows_reordered),
11412                         tree_view);
11413
11414       flags = gtk_tree_model_get_flags (tree_view->priv->model);
11415       if ((flags & GTK_TREE_MODEL_LIST_ONLY) == GTK_TREE_MODEL_LIST_ONLY)
11416         tree_view->priv->is_list = TRUE;
11417       else
11418         tree_view->priv->is_list = FALSE;
11419
11420       path = gtk_tree_path_new_first ();
11421       if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path))
11422         {
11423           tree_view->priv->tree = _gtk_rbtree_new ();
11424           gtk_tree_view_build_tree (tree_view, tree_view->priv->tree, &iter, 1, FALSE);
11425         }
11426       gtk_tree_path_free (path);
11427
11428       /*  FIXME: do I need to do this? gtk_tree_view_create_buttons (tree_view); */
11429       install_presize_handler (tree_view);
11430     }
11431
11432   g_object_notify (G_OBJECT (tree_view), "model");
11433
11434   if (tree_view->priv->selection)
11435   _gtk_tree_selection_emit_changed (tree_view->priv->selection);
11436
11437   if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
11438     gtk_widget_queue_resize (GTK_WIDGET (tree_view));
11439 }
11440
11441 /**
11442  * gtk_tree_view_get_selection:
11443  * @tree_view: A #GtkTreeView.
11444  *
11445  * Gets the #GtkTreeSelection associated with @tree_view.
11446  *
11447  * Return value: (transfer none): A #GtkTreeSelection object.
11448  **/
11449 GtkTreeSelection *
11450 gtk_tree_view_get_selection (GtkTreeView *tree_view)
11451 {
11452   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
11453
11454   return tree_view->priv->selection;
11455 }
11456
11457 /**
11458  * gtk_tree_view_get_hadjustment:
11459  * @tree_view: A #GtkTreeView
11460  *
11461  * Gets the #GtkAdjustment currently being used for the horizontal aspect.
11462  *
11463  * Return value: (transfer none): A #GtkAdjustment object, or %NULL
11464  *     if none is currently being used.
11465  *
11466  * Deprecated: 3.0: Use gtk_scrollable_get_hadjustment()
11467  **/
11468 GtkAdjustment *
11469 gtk_tree_view_get_hadjustment (GtkTreeView *tree_view)
11470 {
11471   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
11472
11473   return tree_view->priv->hadjustment;
11474 }
11475
11476 /**
11477  * gtk_tree_view_set_hadjustment:
11478  * @tree_view: A #GtkTreeView
11479  * @adjustment: (allow-none): The #GtkAdjustment to set, or %NULL
11480  *
11481  * Sets the #GtkAdjustment for the current horizontal aspect.
11482  *
11483  * Deprecated: 3.0: Use gtk_scrollable_set_hadjustment()
11484  **/
11485 void
11486 gtk_tree_view_set_hadjustment (GtkTreeView   *tree_view,
11487                                GtkAdjustment *adjustment)
11488 {
11489   GtkTreeViewPrivate *priv = tree_view->priv;
11490
11491   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
11492   g_return_if_fail (adjustment == NULL || GTK_IS_ADJUSTMENT (adjustment));
11493
11494   if (adjustment && priv->hadjustment == adjustment)
11495     return;
11496
11497   if (priv->hadjustment != NULL)
11498     {
11499       g_signal_handlers_disconnect_by_func (priv->hadjustment,
11500                                             gtk_tree_view_adjustment_changed,
11501                                             tree_view);
11502       g_object_unref (priv->hadjustment);
11503     }
11504
11505   if (adjustment == NULL)
11506     adjustment = gtk_adjustment_new (0.0, 0.0, 0.0,
11507                                      0.0, 0.0, 0.0);
11508
11509   g_signal_connect (adjustment, "value-changed",
11510                     G_CALLBACK (gtk_tree_view_adjustment_changed), tree_view);
11511   priv->hadjustment = g_object_ref_sink (adjustment);
11512   /* FIXME: Adjustment should probably be populated here with fresh values, but
11513    * internal details are too complicated for me to decipher right now.
11514    */
11515   gtk_tree_view_adjustment_changed (NULL, tree_view);
11516
11517   g_object_notify (G_OBJECT (tree_view), "hadjustment");
11518 }
11519
11520 /**
11521  * gtk_tree_view_get_vadjustment:
11522  * @tree_view: A #GtkTreeView
11523  *
11524  * Gets the #GtkAdjustment currently being used for the vertical aspect.
11525  *
11526  * Return value: (transfer none): A #GtkAdjustment object, or %NULL
11527  *     if none is currently being used.
11528  *
11529  * Deprecated: 3.0: Use gtk_scrollable_get_vadjustment()
11530  **/
11531 GtkAdjustment *
11532 gtk_tree_view_get_vadjustment (GtkTreeView *tree_view)
11533 {
11534   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
11535
11536   return tree_view->priv->vadjustment;
11537 }
11538
11539 /**
11540  * gtk_tree_view_set_vadjustment:
11541  * @tree_view: A #GtkTreeView
11542  * @adjustment: (allow-none): The #GtkAdjustment to set, or %NULL
11543  *
11544  * Sets the #GtkAdjustment for the current vertical aspect.
11545  *
11546  * Deprecated: 3.0: Use gtk_scrollable_set_vadjustment()
11547  **/
11548 void
11549 gtk_tree_view_set_vadjustment (GtkTreeView   *tree_view,
11550                                GtkAdjustment *adjustment)
11551 {
11552   GtkTreeViewPrivate *priv = tree_view->priv;
11553
11554   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
11555   g_return_if_fail (adjustment == NULL || GTK_IS_ADJUSTMENT (adjustment));
11556
11557   if (adjustment && priv->vadjustment == adjustment)
11558     return;
11559
11560   if (priv->vadjustment != NULL)
11561     {
11562       g_signal_handlers_disconnect_by_func (priv->vadjustment,
11563                                             gtk_tree_view_adjustment_changed,
11564                                             tree_view);
11565       g_object_unref (priv->vadjustment);
11566     }
11567
11568   if (adjustment == NULL)
11569     adjustment = gtk_adjustment_new (0.0, 0.0, 0.0,
11570                                      0.0, 0.0, 0.0);
11571
11572   g_signal_connect (adjustment, "value-changed",
11573                     G_CALLBACK (gtk_tree_view_adjustment_changed), tree_view);
11574   priv->vadjustment = g_object_ref_sink (adjustment);
11575   /* FIXME: Adjustment should probably be populated here with fresh values, but
11576    * internal details are too complicated for me to decipher right now.
11577    */
11578   gtk_tree_view_adjustment_changed (NULL, tree_view);
11579   g_object_notify (G_OBJECT (tree_view), "vadjustment");
11580 }
11581
11582 /* Column and header operations */
11583
11584 /**
11585  * gtk_tree_view_get_headers_visible:
11586  * @tree_view: A #GtkTreeView.
11587  *
11588  * Returns %TRUE if the headers on the @tree_view are visible.
11589  *
11590  * Return value: Whether the headers are visible or not.
11591  **/
11592 gboolean
11593 gtk_tree_view_get_headers_visible (GtkTreeView *tree_view)
11594 {
11595   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
11596
11597   return tree_view->priv->headers_visible;
11598 }
11599
11600 /**
11601  * gtk_tree_view_set_headers_visible:
11602  * @tree_view: A #GtkTreeView.
11603  * @headers_visible: %TRUE if the headers are visible
11604  *
11605  * Sets the visibility state of the headers.
11606  **/
11607 void
11608 gtk_tree_view_set_headers_visible (GtkTreeView *tree_view,
11609                                    gboolean     headers_visible)
11610 {
11611   gint x, y;
11612   GList *list;
11613   GtkTreeViewColumn *column;
11614   GtkAllocation allocation;
11615   GtkWidget *button;
11616
11617   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
11618
11619   headers_visible = !! headers_visible;
11620
11621   if (tree_view->priv->headers_visible == headers_visible)
11622     return;
11623
11624   tree_view->priv->headers_visible = headers_visible == TRUE;
11625
11626   if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
11627     {
11628       gdk_window_get_position (tree_view->priv->bin_window, &x, &y);
11629       if (headers_visible)
11630         {
11631           gtk_widget_get_allocation (GTK_WIDGET (tree_view), &allocation);
11632           gdk_window_move_resize (tree_view->priv->bin_window,
11633                                   x, y  + gtk_tree_view_get_effective_header_height (tree_view),
11634                                   tree_view->priv->width, allocation.height -  + gtk_tree_view_get_effective_header_height (tree_view));
11635
11636           if (gtk_widget_get_mapped (GTK_WIDGET (tree_view)))
11637             gtk_tree_view_map_buttons (tree_view);
11638         }
11639       else
11640         {
11641           gdk_window_move_resize (tree_view->priv->bin_window, x, y, tree_view->priv->width, tree_view->priv->height);
11642
11643           for (list = tree_view->priv->columns; list; list = list->next)
11644             {
11645               column = list->data;
11646               button = gtk_tree_view_column_get_button (column);
11647
11648               gtk_widget_hide (button);
11649               gtk_widget_unmap (button);
11650             }
11651           gdk_window_hide (tree_view->priv->header_window);
11652         }
11653     }
11654
11655   gtk_widget_get_allocation (GTK_WIDGET (tree_view), &allocation);
11656   gtk_adjustment_configure (tree_view->priv->vadjustment,
11657                             gtk_adjustment_get_value (tree_view->priv->vadjustment),
11658                             0,
11659                             tree_view->priv->height,
11660                             gtk_adjustment_get_step_increment (tree_view->priv->vadjustment),
11661                             (allocation.height - gtk_tree_view_get_effective_header_height (tree_view)) / 2,
11662                             allocation.height - gtk_tree_view_get_effective_header_height (tree_view));
11663
11664   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
11665
11666   g_object_notify (G_OBJECT (tree_view), "headers-visible");
11667 }
11668
11669 /**
11670  * gtk_tree_view_columns_autosize:
11671  * @tree_view: A #GtkTreeView.
11672  *
11673  * Resizes all columns to their optimal width. Only works after the
11674  * treeview has been realized.
11675  **/
11676 void
11677 gtk_tree_view_columns_autosize (GtkTreeView *tree_view)
11678 {
11679   gboolean dirty = FALSE;
11680   GList *list;
11681   GtkTreeViewColumn *column;
11682
11683   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
11684
11685   for (list = tree_view->priv->columns; list; list = list->next)
11686     {
11687       column = list->data;
11688       if (gtk_tree_view_column_get_sizing (column) == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
11689         continue;
11690       _gtk_tree_view_column_cell_set_dirty (column, TRUE);
11691       dirty = TRUE;
11692     }
11693
11694   if (dirty)
11695     gtk_widget_queue_resize (GTK_WIDGET (tree_view));
11696 }
11697
11698 /**
11699  * gtk_tree_view_set_headers_clickable:
11700  * @tree_view: A #GtkTreeView.
11701  * @setting: %TRUE if the columns are clickable.
11702  *
11703  * Allow the column title buttons to be clicked.
11704  **/
11705 void
11706 gtk_tree_view_set_headers_clickable (GtkTreeView *tree_view,
11707                                      gboolean   setting)
11708 {
11709   GList *list;
11710
11711   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
11712
11713   for (list = tree_view->priv->columns; list; list = list->next)
11714     gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (list->data), setting);
11715
11716   g_object_notify (G_OBJECT (tree_view), "headers-clickable");
11717 }
11718
11719
11720 /**
11721  * gtk_tree_view_get_headers_clickable:
11722  * @tree_view: A #GtkTreeView.
11723  *
11724  * Returns whether all header columns are clickable.
11725  *
11726  * Return value: %TRUE if all header columns are clickable, otherwise %FALSE
11727  *
11728  * Since: 2.10
11729  **/
11730 gboolean 
11731 gtk_tree_view_get_headers_clickable (GtkTreeView *tree_view)
11732 {
11733   GList *list;
11734   
11735   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
11736
11737   for (list = tree_view->priv->columns; list; list = list->next)
11738     if (!gtk_tree_view_column_get_clickable (GTK_TREE_VIEW_COLUMN (list->data)))
11739       return FALSE;
11740
11741   return TRUE;
11742 }
11743
11744 /**
11745  * gtk_tree_view_set_rules_hint
11746  * @tree_view: a #GtkTreeView
11747  * @setting: %TRUE if the tree requires reading across rows
11748  *
11749  * This function tells GTK+ that the user interface for your
11750  * application requires users to read across tree rows and associate
11751  * cells with one another. By default, GTK+ will then render the tree
11752  * with alternating row colors. Do <emphasis>not</emphasis> use it
11753  * just because you prefer the appearance of the ruled tree; that's a
11754  * question for the theme. Some themes will draw tree rows in
11755  * alternating colors even when rules are turned off, and users who
11756  * prefer that appearance all the time can choose those themes. You
11757  * should call this function only as a <emphasis>semantic</emphasis>
11758  * hint to the theme engine that your tree makes alternating colors
11759  * useful from a functional standpoint (since it has lots of columns,
11760  * generally).
11761  *
11762  **/
11763 void
11764 gtk_tree_view_set_rules_hint (GtkTreeView  *tree_view,
11765                               gboolean      setting)
11766 {
11767   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
11768
11769   setting = setting != FALSE;
11770
11771   if (tree_view->priv->has_rules != setting)
11772     {
11773       tree_view->priv->has_rules = setting;
11774       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
11775     }
11776
11777   g_object_notify (G_OBJECT (tree_view), "rules-hint");
11778 }
11779
11780 /**
11781  * gtk_tree_view_get_rules_hint
11782  * @tree_view: a #GtkTreeView
11783  *
11784  * Gets the setting set by gtk_tree_view_set_rules_hint().
11785  *
11786  * Return value: %TRUE if rules are useful for the user of this tree
11787  **/
11788 gboolean
11789 gtk_tree_view_get_rules_hint (GtkTreeView  *tree_view)
11790 {
11791   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
11792
11793   return tree_view->priv->has_rules;
11794 }
11795
11796 /* Public Column functions
11797  */
11798
11799 /**
11800  * gtk_tree_view_append_column:
11801  * @tree_view: A #GtkTreeView.
11802  * @column: The #GtkTreeViewColumn to add.
11803  *
11804  * Appends @column to the list of columns. If @tree_view has "fixed_height"
11805  * mode enabled, then @column must have its "sizing" property set to be
11806  * GTK_TREE_VIEW_COLUMN_FIXED.
11807  *
11808  * Return value: The number of columns in @tree_view after appending.
11809  **/
11810 gint
11811 gtk_tree_view_append_column (GtkTreeView       *tree_view,
11812                              GtkTreeViewColumn *column)
11813 {
11814   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
11815   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
11816   g_return_val_if_fail (gtk_tree_view_column_get_tree_view (column) == NULL, -1);
11817
11818   return gtk_tree_view_insert_column (tree_view, column, -1);
11819 }
11820
11821 void
11822 _gtk_tree_view_reset_header_styles (GtkTreeView *tree_view)
11823 {
11824   GList *columns;
11825
11826   for (columns = tree_view->priv->columns; columns; columns = columns->next)
11827     {
11828       GtkTreeViewColumn *column = columns->data;
11829       GtkWidget *header_widget;
11830
11831       if (gtk_tree_view_column_get_visible (column))
11832         continue;
11833
11834       header_widget = gtk_tree_view_column_get_widget (column);
11835
11836       if (!header_widget)
11837         header_widget = gtk_tree_view_column_get_button (column);
11838
11839       gtk_widget_reset_style (header_widget);
11840     }
11841 }
11842
11843
11844 /**
11845  * gtk_tree_view_remove_column:
11846  * @tree_view: A #GtkTreeView.
11847  * @column: The #GtkTreeViewColumn to remove.
11848  *
11849  * Removes @column from @tree_view.
11850  *
11851  * Return value: The number of columns in @tree_view after removing.
11852  **/
11853 gint
11854 gtk_tree_view_remove_column (GtkTreeView       *tree_view,
11855                              GtkTreeViewColumn *column)
11856 {
11857   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
11858   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
11859   g_return_val_if_fail (gtk_tree_view_column_get_tree_view (column) == GTK_WIDGET (tree_view), -1);
11860
11861   if (tree_view->priv->focus_column == column)
11862     tree_view->priv->focus_column = NULL;
11863
11864   if (tree_view->priv->edited_column == column)
11865     {
11866       gtk_tree_view_stop_editing (tree_view, TRUE);
11867
11868       /* no need to, but just to be sure ... */
11869       tree_view->priv->edited_column = NULL;
11870     }
11871
11872   if (tree_view->priv->expander_column == column)
11873     tree_view->priv->expander_column = NULL;
11874
11875   g_signal_handlers_disconnect_by_func (column,
11876                                         G_CALLBACK (column_sizing_notify),
11877                                         tree_view);
11878
11879   _gtk_tree_view_column_unset_tree_view (column);
11880
11881   tree_view->priv->columns = g_list_remove (tree_view->priv->columns, column);
11882   tree_view->priv->n_columns--;
11883
11884   if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
11885     {
11886       GList *list;
11887
11888       _gtk_tree_view_column_unrealize_button (column);
11889       for (list = tree_view->priv->columns; list; list = list->next)
11890         {
11891           GtkTreeViewColumn *tmp_column;
11892
11893           tmp_column = GTK_TREE_VIEW_COLUMN (list->data);
11894           if (gtk_tree_view_column_get_visible (tmp_column))
11895             _gtk_tree_view_column_cell_set_dirty (tmp_column, TRUE);
11896         }
11897
11898       if (tree_view->priv->n_columns == 0 &&
11899           gtk_tree_view_get_headers_visible (tree_view))
11900         gdk_window_hide (tree_view->priv->header_window);
11901
11902       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
11903     }
11904
11905   _gtk_tree_view_reset_header_styles (tree_view);
11906
11907   g_object_unref (column);
11908   g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
11909
11910   return tree_view->priv->n_columns;
11911 }
11912
11913 /**
11914  * gtk_tree_view_insert_column:
11915  * @tree_view: A #GtkTreeView.
11916  * @column: The #GtkTreeViewColumn to be inserted.
11917  * @position: The position to insert @column in.
11918  *
11919  * This inserts the @column into the @tree_view at @position.  If @position is
11920  * -1, then the column is inserted at the end. If @tree_view has
11921  * "fixed_height" mode enabled, then @column must have its "sizing" property
11922  * set to be GTK_TREE_VIEW_COLUMN_FIXED.
11923  *
11924  * Return value: The number of columns in @tree_view after insertion.
11925  **/
11926 gint
11927 gtk_tree_view_insert_column (GtkTreeView       *tree_view,
11928                              GtkTreeViewColumn *column,
11929                              gint               position)
11930 {
11931   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
11932   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
11933   g_return_val_if_fail (gtk_tree_view_column_get_tree_view (column) == NULL, -1);
11934
11935   if (tree_view->priv->fixed_height_mode)
11936     g_return_val_if_fail (gtk_tree_view_column_get_sizing (column)
11937                           == GTK_TREE_VIEW_COLUMN_FIXED, -1);
11938
11939   g_object_ref_sink (column);
11940
11941   if (tree_view->priv->n_columns == 0 &&
11942       gtk_widget_get_realized (GTK_WIDGET (tree_view)) &&
11943       gtk_tree_view_get_headers_visible (tree_view))
11944     {
11945       gdk_window_show (tree_view->priv->header_window);
11946     }
11947
11948   g_signal_connect (column, "notify::sizing",
11949                     G_CALLBACK (column_sizing_notify), tree_view);
11950
11951   tree_view->priv->columns = g_list_insert (tree_view->priv->columns,
11952                                             column, position);
11953   tree_view->priv->n_columns++;
11954
11955   _gtk_tree_view_column_set_tree_view (column, tree_view);
11956
11957   if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
11958     {
11959       GList *list;
11960
11961       _gtk_tree_view_column_realize_button (column);
11962
11963       for (list = tree_view->priv->columns; list; list = list->next)
11964         {
11965           column = GTK_TREE_VIEW_COLUMN (list->data);
11966           if (gtk_tree_view_column_get_visible (column))
11967             _gtk_tree_view_column_cell_set_dirty (column, TRUE);
11968         }
11969       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
11970     }
11971
11972   _gtk_tree_view_reset_header_styles (tree_view);
11973   g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
11974
11975   return tree_view->priv->n_columns;
11976 }
11977
11978 /**
11979  * gtk_tree_view_insert_column_with_attributes:
11980  * @tree_view: A #GtkTreeView
11981  * @position: The position to insert the new column in.
11982  * @title: The title to set the header to.
11983  * @cell: The #GtkCellRenderer.
11984  * @Varargs: A %NULL-terminated list of attributes.
11985  *
11986  * Creates a new #GtkTreeViewColumn and inserts it into the @tree_view at
11987  * @position.  If @position is -1, then the newly created column is inserted at
11988  * the end.  The column is initialized with the attributes given. If @tree_view
11989  * has "fixed_height" mode enabled, then the new column will have its sizing
11990  * property set to be GTK_TREE_VIEW_COLUMN_FIXED.
11991  *
11992  * Return value: The number of columns in @tree_view after insertion.
11993  **/
11994 gint
11995 gtk_tree_view_insert_column_with_attributes (GtkTreeView     *tree_view,
11996                                              gint             position,
11997                                              const gchar     *title,
11998                                              GtkCellRenderer *cell,
11999                                              ...)
12000 {
12001   GtkTreeViewColumn *column;
12002   gchar *attribute;
12003   va_list args;
12004   gint column_id;
12005
12006   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
12007
12008   column = gtk_tree_view_column_new ();
12009   if (tree_view->priv->fixed_height_mode)
12010     gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
12011
12012   gtk_tree_view_column_set_title (column, title);
12013   gtk_tree_view_column_pack_start (column, cell, TRUE);
12014
12015   va_start (args, cell);
12016
12017   attribute = va_arg (args, gchar *);
12018
12019   while (attribute != NULL)
12020     {
12021       column_id = va_arg (args, gint);
12022       gtk_tree_view_column_add_attribute (column, cell, attribute, column_id);
12023       attribute = va_arg (args, gchar *);
12024     }
12025
12026   va_end (args);
12027
12028   gtk_tree_view_insert_column (tree_view, column, position);
12029
12030   return tree_view->priv->n_columns;
12031 }
12032
12033 /**
12034  * gtk_tree_view_insert_column_with_data_func:
12035  * @tree_view: a #GtkTreeView
12036  * @position: Position to insert, -1 for append
12037  * @title: column title
12038  * @cell: cell renderer for column
12039  * @func: function to set attributes of cell renderer
12040  * @data: data for @func
12041  * @dnotify: destroy notifier for @data
12042  *
12043  * Convenience function that inserts a new column into the #GtkTreeView
12044  * with the given cell renderer and a #GtkCellDataFunc to set cell renderer
12045  * attributes (normally using data from the model). See also
12046  * gtk_tree_view_column_set_cell_data_func(), gtk_tree_view_column_pack_start().
12047  * If @tree_view has "fixed_height" mode enabled, then the new column will have its
12048  * "sizing" property set to be GTK_TREE_VIEW_COLUMN_FIXED.
12049  *
12050  * Return value: number of columns in the tree view post-insert
12051  **/
12052 gint
12053 gtk_tree_view_insert_column_with_data_func  (GtkTreeView               *tree_view,
12054                                              gint                       position,
12055                                              const gchar               *title,
12056                                              GtkCellRenderer           *cell,
12057                                              GtkTreeCellDataFunc        func,
12058                                              gpointer                   data,
12059                                              GDestroyNotify             dnotify)
12060 {
12061   GtkTreeViewColumn *column;
12062
12063   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
12064
12065   column = gtk_tree_view_column_new ();
12066   if (tree_view->priv->fixed_height_mode)
12067     gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
12068
12069   gtk_tree_view_column_set_title (column, title);
12070   gtk_tree_view_column_pack_start (column, cell, TRUE);
12071   gtk_tree_view_column_set_cell_data_func (column, cell, func, data, dnotify);
12072
12073   gtk_tree_view_insert_column (tree_view, column, position);
12074
12075   return tree_view->priv->n_columns;
12076 }
12077
12078 /**
12079  * gtk_tree_view_get_column:
12080  * @tree_view: A #GtkTreeView.
12081  * @n: The position of the column, counting from 0.
12082  *
12083  * Gets the #GtkTreeViewColumn at the given position in the #tree_view.
12084  *
12085  * Return value: (transfer none): The #GtkTreeViewColumn, or %NULL if the
12086  *     position is outside the range of columns.
12087  **/
12088 GtkTreeViewColumn *
12089 gtk_tree_view_get_column (GtkTreeView *tree_view,
12090                           gint         n)
12091 {
12092   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
12093
12094   if (n < 0 || n >= tree_view->priv->n_columns)
12095     return NULL;
12096
12097   if (tree_view->priv->columns == NULL)
12098     return NULL;
12099
12100   return GTK_TREE_VIEW_COLUMN (g_list_nth (tree_view->priv->columns, n)->data);
12101 }
12102
12103 /**
12104  * gtk_tree_view_get_columns:
12105  * @tree_view: A #GtkTreeView
12106  *
12107  * Returns a #GList of all the #GtkTreeViewColumn s currently in @tree_view.
12108  * The returned list must be freed with g_list_free ().
12109  *
12110  * Return value: (element-type GtkTreeViewColumn) (transfer container): A list of #GtkTreeViewColumn s
12111  **/
12112 GList *
12113 gtk_tree_view_get_columns (GtkTreeView *tree_view)
12114 {
12115   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
12116
12117   return g_list_copy (tree_view->priv->columns);
12118 }
12119
12120 /**
12121  * gtk_tree_view_move_column_after:
12122  * @tree_view: A #GtkTreeView
12123  * @column: The #GtkTreeViewColumn to be moved.
12124  * @base_column: (allow-none): The #GtkTreeViewColumn to be moved relative to, or %NULL.
12125  *
12126  * Moves @column to be after to @base_column.  If @base_column is %NULL, then
12127  * @column is placed in the first position.
12128  **/
12129 void
12130 gtk_tree_view_move_column_after (GtkTreeView       *tree_view,
12131                                  GtkTreeViewColumn *column,
12132                                  GtkTreeViewColumn *base_column)
12133 {
12134   GList *column_list_el, *base_el = NULL;
12135
12136   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
12137
12138   column_list_el = g_list_find (tree_view->priv->columns, column);
12139   g_return_if_fail (column_list_el != NULL);
12140
12141   if (base_column)
12142     {
12143       base_el = g_list_find (tree_view->priv->columns, base_column);
12144       g_return_if_fail (base_el != NULL);
12145     }
12146
12147   if (column_list_el->prev == base_el)
12148     return;
12149
12150   tree_view->priv->columns = g_list_remove_link (tree_view->priv->columns, column_list_el);
12151   if (base_el == NULL)
12152     {
12153       column_list_el->prev = NULL;
12154       column_list_el->next = tree_view->priv->columns;
12155       if (column_list_el->next)
12156         column_list_el->next->prev = column_list_el;
12157       tree_view->priv->columns = column_list_el;
12158     }
12159   else
12160     {
12161       column_list_el->prev = base_el;
12162       column_list_el->next = base_el->next;
12163       if (column_list_el->next)
12164         column_list_el->next->prev = column_list_el;
12165       base_el->next = column_list_el;
12166     }
12167
12168   if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
12169     {
12170       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
12171       gtk_tree_view_size_allocate_columns (GTK_WIDGET (tree_view), NULL);
12172     }
12173
12174   _gtk_tree_view_reset_header_styles (tree_view);
12175   g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
12176 }
12177
12178 /**
12179  * gtk_tree_view_set_expander_column:
12180  * @tree_view: A #GtkTreeView
12181  * @column: %NULL, or the column to draw the expander arrow at.
12182  *
12183  * Sets the column to draw the expander arrow at. It must be in @tree_view.  
12184  * If @column is %NULL, then the expander arrow is always at the first 
12185  * visible column.
12186  *
12187  * If you do not want expander arrow to appear in your tree, set the 
12188  * expander column to a hidden column.
12189  **/
12190 void
12191 gtk_tree_view_set_expander_column (GtkTreeView       *tree_view,
12192                                    GtkTreeViewColumn *column)
12193 {
12194   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
12195   g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
12196
12197   if (tree_view->priv->expander_column != column)
12198     {
12199       GList *list;
12200
12201       if (column)
12202         {
12203           /* Confirm that column is in tree_view */
12204           for (list = tree_view->priv->columns; list; list = list->next)
12205             if (list->data == column)
12206               break;
12207           g_return_if_fail (list != NULL);
12208         }
12209
12210       tree_view->priv->expander_column = column;
12211       g_object_notify (G_OBJECT (tree_view), "expander-column");
12212     }
12213 }
12214
12215 /**
12216  * gtk_tree_view_get_expander_column:
12217  * @tree_view: A #GtkTreeView
12218  *
12219  * Returns the column that is the current expander column.
12220  * This column has the expander arrow drawn next to it.
12221  *
12222  * Return value: (transfer none): The expander column.
12223  **/
12224 GtkTreeViewColumn *
12225 gtk_tree_view_get_expander_column (GtkTreeView *tree_view)
12226 {
12227   GList *list;
12228
12229   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
12230
12231   for (list = tree_view->priv->columns; list; list = list->next)
12232     if (gtk_tree_view_is_expander_column (tree_view, GTK_TREE_VIEW_COLUMN (list->data)))
12233       return (GtkTreeViewColumn *) list->data;
12234   return NULL;
12235 }
12236
12237
12238 /**
12239  * gtk_tree_view_set_column_drag_function:
12240  * @tree_view: A #GtkTreeView.
12241  * @func: (allow-none): A function to determine which columns are reorderable, or %NULL.
12242  * @user_data: (allow-none): User data to be passed to @func, or %NULL
12243  * @destroy: (allow-none): Destroy notifier for @user_data, or %NULL
12244  *
12245  * Sets a user function for determining where a column may be dropped when
12246  * dragged.  This function is called on every column pair in turn at the
12247  * beginning of a column drag to determine where a drop can take place.  The
12248  * arguments passed to @func are: the @tree_view, the #GtkTreeViewColumn being
12249  * dragged, the two #GtkTreeViewColumn s determining the drop spot, and
12250  * @user_data.  If either of the #GtkTreeViewColumn arguments for the drop spot
12251  * are %NULL, then they indicate an edge.  If @func is set to be %NULL, then
12252  * @tree_view reverts to the default behavior of allowing all columns to be
12253  * dropped everywhere.
12254  **/
12255 void
12256 gtk_tree_view_set_column_drag_function (GtkTreeView               *tree_view,
12257                                         GtkTreeViewColumnDropFunc  func,
12258                                         gpointer                   user_data,
12259                                         GDestroyNotify             destroy)
12260 {
12261   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
12262
12263   if (tree_view->priv->column_drop_func_data_destroy)
12264     tree_view->priv->column_drop_func_data_destroy (tree_view->priv->column_drop_func_data);
12265
12266   tree_view->priv->column_drop_func = func;
12267   tree_view->priv->column_drop_func_data = user_data;
12268   tree_view->priv->column_drop_func_data_destroy = destroy;
12269 }
12270
12271 /**
12272  * gtk_tree_view_scroll_to_point:
12273  * @tree_view: a #GtkTreeView
12274  * @tree_x: X coordinate of new top-left pixel of visible area, or -1
12275  * @tree_y: Y coordinate of new top-left pixel of visible area, or -1
12276  *
12277  * Scrolls the tree view such that the top-left corner of the visible
12278  * area is @tree_x, @tree_y, where @tree_x and @tree_y are specified
12279  * in tree coordinates.  The @tree_view must be realized before
12280  * this function is called.  If it isn't, you probably want to be
12281  * using gtk_tree_view_scroll_to_cell().
12282  *
12283  * If either @tree_x or @tree_y are -1, then that direction isn't scrolled.
12284  **/
12285 void
12286 gtk_tree_view_scroll_to_point (GtkTreeView *tree_view,
12287                                gint         tree_x,
12288                                gint         tree_y)
12289 {
12290   GtkAdjustment *hadj;
12291   GtkAdjustment *vadj;
12292
12293   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
12294   g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (tree_view)));
12295
12296   hadj = tree_view->priv->hadjustment;
12297   vadj = tree_view->priv->vadjustment;
12298
12299   if (tree_x != -1)
12300     gtk_adjustment_set_value (hadj, tree_x);
12301   if (tree_y != -1)
12302     gtk_adjustment_set_value (vadj, tree_y);
12303 }
12304
12305 /**
12306  * gtk_tree_view_scroll_to_cell:
12307  * @tree_view: A #GtkTreeView.
12308  * @path: (allow-none): The path of the row to move to, or %NULL.
12309  * @column: (allow-none): The #GtkTreeViewColumn to move horizontally to, or %NULL.
12310  * @use_align: whether to use alignment arguments, or %FALSE.
12311  * @row_align: The vertical alignment of the row specified by @path.
12312  * @col_align: The horizontal alignment of the column specified by @column.
12313  *
12314  * Moves the alignments of @tree_view to the position specified by @column and
12315  * @path.  If @column is %NULL, then no horizontal scrolling occurs.  Likewise,
12316  * if @path is %NULL no vertical scrolling occurs.  At a minimum, one of @column
12317  * or @path need to be non-%NULL.  @row_align determines where the row is
12318  * placed, and @col_align determines where @column is placed.  Both are expected
12319  * to be between 0.0 and 1.0. 0.0 means left/top alignment, 1.0 means
12320  * right/bottom alignment, 0.5 means center.
12321  *
12322  * If @use_align is %FALSE, then the alignment arguments are ignored, and the
12323  * tree does the minimum amount of work to scroll the cell onto the screen.
12324  * This means that the cell will be scrolled to the edge closest to its current
12325  * position.  If the cell is currently visible on the screen, nothing is done.
12326  *
12327  * This function only works if the model is set, and @path is a valid row on the
12328  * model.  If the model changes before the @tree_view is realized, the centered
12329  * path will be modified to reflect this change.
12330  **/
12331 void
12332 gtk_tree_view_scroll_to_cell (GtkTreeView       *tree_view,
12333                               GtkTreePath       *path,
12334                               GtkTreeViewColumn *column,
12335                               gboolean           use_align,
12336                               gfloat             row_align,
12337                               gfloat             col_align)
12338 {
12339   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
12340   g_return_if_fail (tree_view->priv->model != NULL);
12341   g_return_if_fail (tree_view->priv->tree != NULL);
12342   g_return_if_fail (row_align >= 0.0 && row_align <= 1.0);
12343   g_return_if_fail (col_align >= 0.0 && col_align <= 1.0);
12344   g_return_if_fail (path != NULL || column != NULL);
12345
12346 #if 0
12347   g_print ("gtk_tree_view_scroll_to_cell:\npath: %s\ncolumn: %s\nuse_align: %d\nrow_align: %f\ncol_align: %f\n",
12348            gtk_tree_path_to_string (path), column?"non-null":"null", use_align, row_align, col_align);
12349 #endif
12350   row_align = CLAMP (row_align, 0.0, 1.0);
12351   col_align = CLAMP (col_align, 0.0, 1.0);
12352
12353
12354   /* Note: Despite the benefits that come from having one code path for the
12355    * scrolling code, we short-circuit validate_visible_area's immplementation as
12356    * it is much slower than just going to the point.
12357    */
12358   if (!gtk_widget_get_visible (GTK_WIDGET (tree_view)) ||
12359       !gtk_widget_get_realized (GTK_WIDGET (tree_view)) ||
12360       _gtk_widget_get_alloc_needed (GTK_WIDGET (tree_view)) ||
12361       GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
12362     {
12363       if (tree_view->priv->scroll_to_path)
12364         gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
12365
12366       tree_view->priv->scroll_to_path = NULL;
12367       tree_view->priv->scroll_to_column = NULL;
12368
12369       if (path)
12370         tree_view->priv->scroll_to_path = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
12371       if (column)
12372         tree_view->priv->scroll_to_column = column;
12373       tree_view->priv->scroll_to_use_align = use_align;
12374       tree_view->priv->scroll_to_row_align = row_align;
12375       tree_view->priv->scroll_to_col_align = col_align;
12376
12377       install_presize_handler (tree_view);
12378     }
12379   else
12380     {
12381       GdkRectangle cell_rect;
12382       GdkRectangle vis_rect;
12383       gint dest_x, dest_y;
12384
12385       gtk_tree_view_get_background_area (tree_view, path, column, &cell_rect);
12386       gtk_tree_view_get_visible_rect (tree_view, &vis_rect);
12387
12388       cell_rect.y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, cell_rect.y);
12389
12390       dest_x = vis_rect.x;
12391       dest_y = vis_rect.y;
12392
12393       if (column)
12394         {
12395           if (use_align)
12396             {
12397               dest_x = cell_rect.x - ((vis_rect.width - cell_rect.width) * col_align);
12398             }
12399           else
12400             {
12401               if (cell_rect.x < vis_rect.x)
12402                 dest_x = cell_rect.x;
12403               if (cell_rect.x + cell_rect.width > vis_rect.x + vis_rect.width)
12404                 dest_x = cell_rect.x + cell_rect.width - vis_rect.width;
12405             }
12406         }
12407
12408       if (path)
12409         {
12410           if (use_align)
12411             {
12412               dest_y = cell_rect.y - ((vis_rect.height - cell_rect.height) * row_align);
12413               dest_y = MAX (dest_y, 0);
12414             }
12415           else
12416             {
12417               if (cell_rect.y < vis_rect.y)
12418                 dest_y = cell_rect.y;
12419               if (cell_rect.y + cell_rect.height > vis_rect.y + vis_rect.height)
12420                 dest_y = cell_rect.y + cell_rect.height - vis_rect.height;
12421             }
12422         }
12423
12424       gtk_tree_view_scroll_to_point (tree_view, dest_x, dest_y);
12425     }
12426 }
12427
12428 /**
12429  * gtk_tree_view_row_activated:
12430  * @tree_view: A #GtkTreeView
12431  * @path: The #GtkTreePath to be activated.
12432  * @column: The #GtkTreeViewColumn to be activated.
12433  *
12434  * Activates the cell determined by @path and @column.
12435  **/
12436 void
12437 gtk_tree_view_row_activated (GtkTreeView       *tree_view,
12438                              GtkTreePath       *path,
12439                              GtkTreeViewColumn *column)
12440 {
12441   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
12442
12443   g_signal_emit (tree_view, tree_view_signals[ROW_ACTIVATED], 0, path, column);
12444 }
12445
12446
12447 static void
12448 gtk_tree_view_expand_all_emission_helper (GtkRBTree *tree,
12449                                           GtkRBNode *node,
12450                                           gpointer   data)
12451 {
12452   GtkTreeView *tree_view = data;
12453
12454   if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT &&
12455       node->children)
12456     {
12457       GtkTreePath *path;
12458       GtkTreeIter iter;
12459
12460       path = _gtk_tree_view_find_path (tree_view, tree, node);
12461       gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
12462
12463       g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
12464
12465       gtk_tree_path_free (path);
12466     }
12467
12468   if (node->children)
12469     _gtk_rbtree_traverse (node->children,
12470                           node->children->root,
12471                           G_PRE_ORDER,
12472                           gtk_tree_view_expand_all_emission_helper,
12473                           tree_view);
12474 }
12475
12476 /**
12477  * gtk_tree_view_expand_all:
12478  * @tree_view: A #GtkTreeView.
12479  *
12480  * Recursively expands all nodes in the @tree_view.
12481  **/
12482 void
12483 gtk_tree_view_expand_all (GtkTreeView *tree_view)
12484 {
12485   GtkTreePath *path;
12486   GtkRBTree *tree;
12487   GtkRBNode *node;
12488
12489   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
12490
12491   if (tree_view->priv->tree == NULL)
12492     return;
12493
12494   path = gtk_tree_path_new_first ();
12495   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
12496
12497   while (node)
12498     {
12499       gtk_tree_view_real_expand_row (tree_view, path, tree, node, TRUE, FALSE);
12500       node = _gtk_rbtree_next (tree, node);
12501       gtk_tree_path_next (path);
12502   }
12503
12504   gtk_tree_path_free (path);
12505 }
12506
12507 /**
12508  * gtk_tree_view_collapse_all:
12509  * @tree_view: A #GtkTreeView.
12510  *
12511  * Recursively collapses all visible, expanded nodes in @tree_view.
12512  **/
12513 void
12514 gtk_tree_view_collapse_all (GtkTreeView *tree_view)
12515 {
12516   GtkRBTree *tree;
12517   GtkRBNode *node;
12518   GtkTreePath *path;
12519   gint *indices;
12520
12521   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
12522
12523   if (tree_view->priv->tree == NULL)
12524     return;
12525
12526   path = gtk_tree_path_new ();
12527   gtk_tree_path_down (path);
12528   indices = gtk_tree_path_get_indices (path);
12529
12530   tree = tree_view->priv->tree;
12531   node = tree->root;
12532   while (node && node->left != tree->nil)
12533     node = node->left;
12534
12535   while (node)
12536     {
12537       if (node->children)
12538         gtk_tree_view_real_collapse_row (tree_view, path, tree, node, FALSE);
12539       indices[0]++;
12540       node = _gtk_rbtree_next (tree, node);
12541     }
12542
12543   gtk_tree_path_free (path);
12544 }
12545
12546 /**
12547  * gtk_tree_view_expand_to_path:
12548  * @tree_view: A #GtkTreeView.
12549  * @path: path to a row.
12550  *
12551  * Expands the row at @path. This will also expand all parent rows of
12552  * @path as necessary.
12553  *
12554  * Since: 2.2
12555  **/
12556 void
12557 gtk_tree_view_expand_to_path (GtkTreeView *tree_view,
12558                               GtkTreePath *path)
12559 {
12560   gint i, depth;
12561   gint *indices;
12562   GtkTreePath *tmp;
12563
12564   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
12565   g_return_if_fail (path != NULL);
12566
12567   depth = gtk_tree_path_get_depth (path);
12568   indices = gtk_tree_path_get_indices (path);
12569
12570   tmp = gtk_tree_path_new ();
12571   g_return_if_fail (tmp != NULL);
12572
12573   for (i = 0; i < depth; i++)
12574     {
12575       gtk_tree_path_append_index (tmp, indices[i]);
12576       gtk_tree_view_expand_row (tree_view, tmp, FALSE);
12577     }
12578
12579   gtk_tree_path_free (tmp);
12580 }
12581
12582 /* FIXME the bool return values for expand_row and collapse_row are
12583  * not analagous; they should be TRUE if the row had children and
12584  * was not already in the requested state.
12585  */
12586
12587
12588 static gboolean
12589 gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
12590                                GtkTreePath *path,
12591                                GtkRBTree   *tree,
12592                                GtkRBNode   *node,
12593                                gboolean     open_all,
12594                                gboolean     animate)
12595 {
12596   GtkTreeIter iter;
12597   GtkTreeIter temp;
12598   gboolean expand;
12599
12600   if (animate)
12601     g_object_get (gtk_widget_get_settings (GTK_WIDGET (tree_view)),
12602                   "gtk-enable-animations", &animate,
12603                   NULL);
12604
12605   remove_auto_expand_timeout (tree_view);
12606
12607   if (node->children && !open_all)
12608     return FALSE;
12609
12610   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
12611     return FALSE;
12612
12613   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
12614   if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
12615     return FALSE;
12616
12617
12618    if (node->children && open_all)
12619     {
12620       gboolean retval = FALSE;
12621       GtkTreePath *tmp_path = gtk_tree_path_copy (path);
12622
12623       gtk_tree_path_append_index (tmp_path, 0);
12624       tree = node->children;
12625       node = tree->root;
12626       while (node->left != tree->nil)
12627         node = node->left;
12628       /* try to expand the children */
12629       do
12630         {
12631          gboolean t;
12632          t = gtk_tree_view_real_expand_row (tree_view, tmp_path, tree, node,
12633                                             TRUE, animate);
12634          if (t)
12635            retval = TRUE;
12636
12637          gtk_tree_path_next (tmp_path);
12638          node = _gtk_rbtree_next (tree, node);
12639        }
12640       while (node != NULL);
12641
12642       gtk_tree_path_free (tmp_path);
12643
12644       return retval;
12645     }
12646
12647   g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, &iter, path, &expand);
12648
12649   if (!gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
12650     return FALSE;
12651
12652   if (expand)
12653     return FALSE;
12654
12655   node->children = _gtk_rbtree_new ();
12656   node->children->parent_tree = tree;
12657   node->children->parent_node = node;
12658
12659   gtk_tree_model_iter_children (tree_view->priv->model, &temp, &iter);
12660
12661   gtk_tree_view_build_tree (tree_view,
12662                             node->children,
12663                             &temp,
12664                             gtk_tree_path_get_depth (path) + 1,
12665                             open_all);
12666
12667   if (animate)
12668     {
12669       GtkStyleContext *context;
12670
12671       context = gtk_widget_get_style_context (GTK_WIDGET (tree_view));
12672
12673       gtk_style_context_save (context);
12674       gtk_style_context_add_class (context, GTK_STYLE_CLASS_EXPANDER);
12675
12676       gtk_style_context_notify_state_change (context, tree_view->priv->bin_window,
12677                                              node, GTK_STATE_ACTIVE, TRUE);
12678
12679       _gtk_style_context_invalidate_animation_areas (context);
12680       gtk_style_context_restore (context);
12681     }
12682
12683   install_presize_handler (tree_view);
12684
12685   g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
12686   if (open_all && node->children)
12687     {
12688       _gtk_rbtree_traverse (node->children,
12689                             node->children->root,
12690                             G_PRE_ORDER,
12691                             gtk_tree_view_expand_all_emission_helper,
12692                             tree_view);
12693     }
12694   return TRUE;
12695 }
12696
12697
12698 /**
12699  * gtk_tree_view_expand_row:
12700  * @tree_view: a #GtkTreeView
12701  * @path: path to a row
12702  * @open_all: whether to recursively expand, or just expand immediate children
12703  *
12704  * Opens the row so its children are visible.
12705  *
12706  * Return value: %TRUE if the row existed and had children
12707  **/
12708 gboolean
12709 gtk_tree_view_expand_row (GtkTreeView *tree_view,
12710                           GtkTreePath *path,
12711                           gboolean     open_all)
12712 {
12713   GtkRBTree *tree;
12714   GtkRBNode *node;
12715
12716   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
12717   g_return_val_if_fail (tree_view->priv->model != NULL, FALSE);
12718   g_return_val_if_fail (path != NULL, FALSE);
12719
12720   if (_gtk_tree_view_find_node (tree_view,
12721                                 path,
12722                                 &tree,
12723                                 &node))
12724     return FALSE;
12725
12726   if (tree != NULL)
12727     return gtk_tree_view_real_expand_row (tree_view, path, tree, node, open_all, FALSE);
12728   else
12729     return FALSE;
12730 }
12731
12732 static gboolean
12733 gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
12734                                  GtkTreePath *path,
12735                                  GtkRBTree   *tree,
12736                                  GtkRBNode   *node,
12737                                  gboolean     animate)
12738 {
12739   GtkTreeIter iter;
12740   GtkTreeIter children;
12741   gboolean collapse;
12742   gint x, y;
12743   GList *list;
12744   GdkWindow *child, *parent;
12745
12746   if (animate)
12747     g_object_get (gtk_widget_get_settings (GTK_WIDGET (tree_view)),
12748                   "gtk-enable-animations", &animate,
12749                   NULL);
12750
12751   remove_auto_expand_timeout (tree_view);
12752
12753   if (node->children == NULL)
12754     return FALSE;
12755   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
12756
12757   g_signal_emit (tree_view, tree_view_signals[TEST_COLLAPSE_ROW], 0, &iter, path, &collapse);
12758
12759   if (collapse)
12760     return FALSE;
12761
12762   /* if the prelighted node is a child of us, we want to unprelight it.  We have
12763    * a chance to prelight the correct node below */
12764
12765   if (tree_view->priv->prelight_tree)
12766     {
12767       GtkRBTree *parent_tree;
12768       GtkRBNode *parent_node;
12769
12770       parent_tree = tree_view->priv->prelight_tree->parent_tree;
12771       parent_node = tree_view->priv->prelight_tree->parent_node;
12772       while (parent_tree)
12773         {
12774           if (parent_tree == tree && parent_node == node)
12775             {
12776               ensure_unprelighted (tree_view);
12777               break;
12778             }
12779           parent_node = parent_tree->parent_node;
12780           parent_tree = parent_tree->parent_tree;
12781         }
12782     }
12783
12784   TREE_VIEW_INTERNAL_ASSERT (gtk_tree_model_iter_children (tree_view->priv->model, &children, &iter), FALSE);
12785
12786   for (list = tree_view->priv->columns; list; list = list->next)
12787     {
12788       GtkTreeViewColumn *column = list->data;
12789
12790       if (gtk_tree_view_column_get_visible (column) == FALSE)
12791         continue;
12792       if (gtk_tree_view_column_get_sizing (column) == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
12793         _gtk_tree_view_column_cell_set_dirty (column, TRUE);
12794     }
12795
12796   if (tree_view->priv->destroy_count_func)
12797     {
12798       GtkTreePath *child_path;
12799       gint child_count = 0;
12800       child_path = gtk_tree_path_copy (path);
12801       gtk_tree_path_down (child_path);
12802       if (node->children)
12803         _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, &child_count);
12804       tree_view->priv->destroy_count_func (tree_view, child_path, child_count, tree_view->priv->destroy_count_data);
12805       gtk_tree_path_free (child_path);
12806     }
12807
12808   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
12809     {
12810       GtkTreePath *cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
12811
12812       if (gtk_tree_path_is_ancestor (path, cursor_path))
12813         {
12814           gtk_tree_row_reference_free (tree_view->priv->cursor);
12815           tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
12816                                                                       tree_view->priv->model,
12817                                                                       path);
12818         }
12819       gtk_tree_path_free (cursor_path);
12820     }
12821
12822   if (gtk_tree_row_reference_valid (tree_view->priv->anchor))
12823     {
12824       GtkTreePath *anchor_path = gtk_tree_row_reference_get_path (tree_view->priv->anchor);
12825       if (gtk_tree_path_is_ancestor (path, anchor_path))
12826         {
12827           gtk_tree_row_reference_free (tree_view->priv->anchor);
12828           tree_view->priv->anchor = NULL;
12829         }
12830       gtk_tree_path_free (anchor_path);
12831     }
12832
12833   /* Stop a pending double click */
12834   tree_view->priv->last_button_x = -1;
12835   tree_view->priv->last_button_y = -1;
12836
12837   if (gtk_tree_view_unref_and_check_selection_tree (tree_view, node->children))
12838     {
12839       _gtk_rbtree_remove (node->children);
12840       g_signal_emit_by_name (tree_view->priv->selection, "changed");
12841     }
12842   else
12843     _gtk_rbtree_remove (node->children);
12844
12845   if (animate)
12846     {
12847       GtkStyleContext *context;
12848
12849       context = gtk_widget_get_style_context (GTK_WIDGET (tree_view));
12850
12851       gtk_style_context_save (context);
12852       gtk_style_context_add_class (context, GTK_STYLE_CLASS_EXPANDER);
12853
12854       gtk_style_context_notify_state_change (context, tree_view->priv->bin_window,
12855                                              node, GTK_STATE_ACTIVE, FALSE);
12856
12857       _gtk_style_context_invalidate_animation_areas (context);
12858       gtk_style_context_restore (context);
12859     }
12860
12861   if (gtk_widget_get_mapped (GTK_WIDGET (tree_view)))
12862     {
12863       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
12864     }
12865
12866   g_signal_emit (tree_view, tree_view_signals[ROW_COLLAPSED], 0, &iter, path);
12867   
12868   if (gtk_widget_get_mapped (GTK_WIDGET (tree_view)))
12869     {
12870       /* now that we've collapsed all rows, we want to try to set the prelight
12871        * again. To do this, we fake a motion event and send it to ourselves. */
12872
12873       child = tree_view->priv->bin_window;
12874       parent = gdk_window_get_parent (child);
12875
12876       if (gdk_window_get_pointer (parent, &x, &y, NULL) == child)
12877         {
12878           GdkEventMotion event;
12879           gint child_x, child_y;
12880
12881           gdk_window_get_position (child, &child_x, &child_y);
12882
12883           event.window = tree_view->priv->bin_window;
12884           event.x = x - child_x;
12885           event.y = y - child_y;
12886
12887           /* despite the fact this isn't a real event, I'm almost positive it will
12888            * never trigger a drag event.  maybe_drag is the only function that uses
12889            * more than just event.x and event.y. */
12890           gtk_tree_view_motion_bin_window (GTK_WIDGET (tree_view), &event);
12891         }
12892     }
12893
12894   return TRUE;
12895 }
12896
12897 /**
12898  * gtk_tree_view_collapse_row:
12899  * @tree_view: a #GtkTreeView
12900  * @path: path to a row in the @tree_view
12901  *
12902  * Collapses a row (hides its child rows, if they exist).
12903  *
12904  * Return value: %TRUE if the row was collapsed.
12905  **/
12906 gboolean
12907 gtk_tree_view_collapse_row (GtkTreeView *tree_view,
12908                             GtkTreePath *path)
12909 {
12910   GtkRBTree *tree;
12911   GtkRBNode *node;
12912
12913   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
12914   g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE);
12915   g_return_val_if_fail (path != NULL, FALSE);
12916
12917   if (_gtk_tree_view_find_node (tree_view,
12918                                 path,
12919                                 &tree,
12920                                 &node))
12921     return FALSE;
12922
12923   if (tree == NULL || node->children == NULL)
12924     return FALSE;
12925
12926   return gtk_tree_view_real_collapse_row (tree_view, path, tree, node, FALSE);
12927 }
12928
12929 static void
12930 gtk_tree_view_map_expanded_rows_helper (GtkTreeView            *tree_view,
12931                                         GtkRBTree              *tree,
12932                                         GtkTreePath            *path,
12933                                         GtkTreeViewMappingFunc  func,
12934                                         gpointer                user_data)
12935 {
12936   GtkRBNode *node;
12937
12938   if (tree == NULL || tree->root == NULL)
12939     return;
12940
12941   node = tree->root;
12942
12943   while (node && node->left != tree->nil)
12944     node = node->left;
12945
12946   while (node)
12947     {
12948       if (node->children)
12949         {
12950           (* func) (tree_view, path, user_data);
12951           gtk_tree_path_down (path);
12952           gtk_tree_view_map_expanded_rows_helper (tree_view, node->children, path, func, user_data);
12953           gtk_tree_path_up (path);
12954         }
12955       gtk_tree_path_next (path);
12956       node = _gtk_rbtree_next (tree, node);
12957     }
12958 }
12959
12960 /**
12961  * gtk_tree_view_map_expanded_rows:
12962  * @tree_view: A #GtkTreeView
12963  * @func: (scope call): A function to be called
12964  * @data: User data to be passed to the function.
12965  *
12966  * Calls @func on all expanded rows.
12967  **/
12968 void
12969 gtk_tree_view_map_expanded_rows (GtkTreeView            *tree_view,
12970                                  GtkTreeViewMappingFunc  func,
12971                                  gpointer                user_data)
12972 {
12973   GtkTreePath *path;
12974
12975   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
12976   g_return_if_fail (func != NULL);
12977
12978   path = gtk_tree_path_new_first ();
12979
12980   gtk_tree_view_map_expanded_rows_helper (tree_view,
12981                                           tree_view->priv->tree,
12982                                           path, func, user_data);
12983
12984   gtk_tree_path_free (path);
12985 }
12986
12987 /**
12988  * gtk_tree_view_row_expanded:
12989  * @tree_view: A #GtkTreeView.
12990  * @path: A #GtkTreePath to test expansion state.
12991  *
12992  * Returns %TRUE if the node pointed to by @path is expanded in @tree_view.
12993  *
12994  * Return value: %TRUE if #path is expanded.
12995  **/
12996 gboolean
12997 gtk_tree_view_row_expanded (GtkTreeView *tree_view,
12998                             GtkTreePath *path)
12999 {
13000   GtkRBTree *tree;
13001   GtkRBNode *node;
13002
13003   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
13004   g_return_val_if_fail (path != NULL, FALSE);
13005
13006   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
13007
13008   if (node == NULL)
13009     return FALSE;
13010
13011   return (node->children != NULL);
13012 }
13013
13014 /**
13015  * gtk_tree_view_get_reorderable:
13016  * @tree_view: a #GtkTreeView
13017  *
13018  * Retrieves whether the user can reorder the tree via drag-and-drop. See
13019  * gtk_tree_view_set_reorderable().
13020  *
13021  * Return value: %TRUE if the tree can be reordered.
13022  **/
13023 gboolean
13024 gtk_tree_view_get_reorderable (GtkTreeView *tree_view)
13025 {
13026   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
13027
13028   return tree_view->priv->reorderable;
13029 }
13030
13031 /**
13032  * gtk_tree_view_set_reorderable:
13033  * @tree_view: A #GtkTreeView.
13034  * @reorderable: %TRUE, if the tree can be reordered.
13035  *
13036  * This function is a convenience function to allow you to reorder
13037  * models that support the #GtkDragSourceIface and the
13038  * #GtkDragDestIface.  Both #GtkTreeStore and #GtkListStore support
13039  * these.  If @reorderable is %TRUE, then the user can reorder the
13040  * model by dragging and dropping rows. The developer can listen to
13041  * these changes by connecting to the model's row_inserted and
13042  * row_deleted signals. The reordering is implemented by setting up
13043  * the tree view as a drag source and destination. Therefore, drag and
13044  * drop can not be used in a reorderable view for any other purpose.
13045  *
13046  * This function does not give you any degree of control over the order -- any
13047  * reordering is allowed.  If more control is needed, you should probably
13048  * handle drag and drop manually.
13049  **/
13050 void
13051 gtk_tree_view_set_reorderable (GtkTreeView *tree_view,
13052                                gboolean     reorderable)
13053 {
13054   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
13055
13056   reorderable = reorderable != FALSE;
13057
13058   if (tree_view->priv->reorderable == reorderable)
13059     return;
13060
13061   if (reorderable)
13062     {
13063       const GtkTargetEntry row_targets[] = {
13064         { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 }
13065       };
13066
13067       gtk_tree_view_enable_model_drag_source (tree_view,
13068                                               GDK_BUTTON1_MASK,
13069                                               row_targets,
13070                                               G_N_ELEMENTS (row_targets),
13071                                               GDK_ACTION_MOVE);
13072       gtk_tree_view_enable_model_drag_dest (tree_view,
13073                                             row_targets,
13074                                             G_N_ELEMENTS (row_targets),
13075                                             GDK_ACTION_MOVE);
13076     }
13077   else
13078     {
13079       gtk_tree_view_unset_rows_drag_source (tree_view);
13080       gtk_tree_view_unset_rows_drag_dest (tree_view);
13081     }
13082
13083   tree_view->priv->reorderable = reorderable;
13084
13085   g_object_notify (G_OBJECT (tree_view), "reorderable");
13086 }
13087
13088 static void
13089 gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
13090                                GtkTreePath     *path,
13091                                gboolean         clear_and_select,
13092                                gboolean         clamp_node)
13093 {
13094   GtkRBTree *tree = NULL;
13095   GtkRBNode *node = NULL;
13096
13097   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
13098     {
13099       GtkTreePath *cursor_path;
13100       cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
13101       gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
13102       gtk_tree_path_free (cursor_path);
13103     }
13104
13105   gtk_tree_row_reference_free (tree_view->priv->cursor);
13106   tree_view->priv->cursor = NULL;
13107
13108   /* One cannot set the cursor on a separator.   Also, if
13109    * _gtk_tree_view_find_node returns TRUE, it ran out of tree
13110    * before finding the tree and node belonging to path.  The
13111    * path maps to a non-existing path and we will silently bail out.
13112    * We unset tree and node to avoid further processing.
13113    */
13114   if (!row_is_separator (tree_view, NULL, path)
13115       && _gtk_tree_view_find_node (tree_view, path, &tree, &node) == FALSE)
13116     {
13117       tree_view->priv->cursor =
13118           gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
13119                                             tree_view->priv->model,
13120                                             path);
13121     }
13122   else
13123     {
13124       tree = NULL;
13125       node = NULL;
13126     }
13127
13128   if (tree != NULL)
13129     {
13130       GtkRBTree *new_tree = NULL;
13131       GtkRBNode *new_node = NULL;
13132
13133       if (clear_and_select && !tree_view->priv->ctrl_pressed)
13134         {
13135           GtkTreeSelectMode mode = 0;
13136
13137           if (tree_view->priv->shift_pressed)
13138             mode |= GTK_TREE_SELECT_MODE_EXTEND;
13139
13140           _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
13141                                                     node, tree, path, mode,
13142                                                     FALSE);
13143         }
13144
13145       /* We have to re-find tree and node here again, somebody might have
13146        * cleared the node or the whole tree in the GtkTreeSelection::changed
13147        * callback. If the nodes differ we bail out here.
13148        */
13149       _gtk_tree_view_find_node (tree_view, path, &new_tree, &new_node);
13150
13151       if (tree != new_tree || node != new_node)
13152         return;
13153
13154       if (clamp_node)
13155         {
13156           gtk_tree_view_clamp_node_visible (tree_view, tree, node);
13157           _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
13158         }
13159     }
13160
13161   g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
13162 }
13163
13164 /**
13165  * gtk_tree_view_get_cursor:
13166  * @tree_view: A #GtkTreeView
13167  * @path: (out) (transfer full) (allow-none): A pointer to be filled with the current cursor path, or %NULL
13168  * @focus_column: (out) (transfer none) (allow-none): A pointer to be filled with the current focus column, or %NULL
13169  *
13170  * Fills in @path and @focus_column with the current path and focus column.  If
13171  * the cursor isn't currently set, then *@path will be %NULL.  If no column
13172  * currently has focus, then *@focus_column will be %NULL.
13173  *
13174  * The returned #GtkTreePath must be freed with gtk_tree_path_free() when
13175  * you are done with it.
13176  **/
13177 void
13178 gtk_tree_view_get_cursor (GtkTreeView        *tree_view,
13179                           GtkTreePath       **path,
13180                           GtkTreeViewColumn **focus_column)
13181 {
13182   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
13183
13184   if (path)
13185     {
13186       if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
13187         *path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
13188       else
13189         *path = NULL;
13190     }
13191
13192   if (focus_column)
13193     {
13194       *focus_column = tree_view->priv->focus_column;
13195     }
13196 }
13197
13198 /**
13199  * gtk_tree_view_set_cursor:
13200  * @tree_view: A #GtkTreeView
13201  * @path: A #GtkTreePath
13202  * @focus_column: (allow-none): A #GtkTreeViewColumn, or %NULL
13203  * @start_editing: %TRUE if the specified cell should start being edited.
13204  *
13205  * Sets the current keyboard focus to be at @path, and selects it.  This is
13206  * useful when you want to focus the user's attention on a particular row.  If
13207  * @focus_column is not %NULL, then focus is given to the column specified by 
13208  * it. Additionally, if @focus_column is specified, and @start_editing is 
13209  * %TRUE, then editing should be started in the specified cell.  
13210  * This function is often followed by @gtk_widget_grab_focus (@tree_view) 
13211  * in order to give keyboard focus to the widget.  Please note that editing 
13212  * can only happen when the widget is realized.
13213  *
13214  * If @path is invalid for @model, the current cursor (if any) will be unset
13215  * and the function will return without failing.
13216  **/
13217 void
13218 gtk_tree_view_set_cursor (GtkTreeView       *tree_view,
13219                           GtkTreePath       *path,
13220                           GtkTreeViewColumn *focus_column,
13221                           gboolean           start_editing)
13222 {
13223   gtk_tree_view_set_cursor_on_cell (tree_view, path, focus_column,
13224                                     NULL, start_editing);
13225 }
13226
13227 /**
13228  * gtk_tree_view_set_cursor_on_cell:
13229  * @tree_view: A #GtkTreeView
13230  * @path: A #GtkTreePath
13231  * @focus_column: (allow-none): A #GtkTreeViewColumn, or %NULL
13232  * @focus_cell: (allow-none): A #GtkCellRenderer, or %NULL
13233  * @start_editing: %TRUE if the specified cell should start being edited.
13234  *
13235  * Sets the current keyboard focus to be at @path, and selects it.  This is
13236  * useful when you want to focus the user's attention on a particular row.  If
13237  * @focus_column is not %NULL, then focus is given to the column specified by
13238  * it. If @focus_column and @focus_cell are not %NULL, and @focus_column
13239  * contains 2 or more editable or activatable cells, then focus is given to
13240  * the cell specified by @focus_cell. Additionally, if @focus_column is
13241  * specified, and @start_editing is %TRUE, then editing should be started in
13242  * the specified cell.  This function is often followed by
13243  * @gtk_widget_grab_focus (@tree_view) in order to give keyboard focus to the
13244  * widget.  Please note that editing can only happen when the widget is
13245  * realized.
13246  *
13247  * If @path is invalid for @model, the current cursor (if any) will be unset
13248  * and the function will return without failing.
13249  *
13250  * Since: 2.2
13251  **/
13252 void
13253 gtk_tree_view_set_cursor_on_cell (GtkTreeView       *tree_view,
13254                                   GtkTreePath       *path,
13255                                   GtkTreeViewColumn *focus_column,
13256                                   GtkCellRenderer   *focus_cell,
13257                                   gboolean           start_editing)
13258 {
13259   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
13260   g_return_if_fail (path != NULL);
13261   g_return_if_fail (focus_column == NULL || GTK_IS_TREE_VIEW_COLUMN (focus_column));
13262
13263   if (!tree_view->priv->model)
13264     return;
13265
13266   if (focus_cell)
13267     {
13268       g_return_if_fail (focus_column);
13269       g_return_if_fail (GTK_IS_CELL_RENDERER (focus_cell));
13270     }
13271
13272   /* cancel the current editing, if it exists */
13273   if (tree_view->priv->edited_column &&
13274       gtk_cell_area_get_edit_widget
13275       (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (tree_view->priv->edited_column))))
13276     gtk_tree_view_stop_editing (tree_view, TRUE);
13277
13278   gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
13279
13280   if (focus_column &&
13281       gtk_tree_view_column_get_visible (focus_column))
13282     {
13283       GList *list;
13284       gboolean column_in_tree = FALSE;
13285
13286       for (list = tree_view->priv->columns; list; list = list->next)
13287         if (list->data == focus_column)
13288           {
13289             column_in_tree = TRUE;
13290             break;
13291           }
13292       g_return_if_fail (column_in_tree);
13293       tree_view->priv->focus_column = focus_column;
13294       if (focus_cell)
13295         gtk_tree_view_column_focus_cell (focus_column, focus_cell);
13296       if (start_editing)
13297         gtk_tree_view_start_editing (tree_view, path, TRUE);
13298     }
13299 }
13300
13301 /**
13302  * gtk_tree_view_get_bin_window:
13303  * @tree_view: A #GtkTreeView
13304  *
13305  * Returns the window that @tree_view renders to.
13306  * This is used primarily to compare to <literal>event->window</literal>
13307  * to confirm that the event on @tree_view is on the right window.
13308  *
13309  * Return value: (transfer none): A #GdkWindow, or %NULL when @tree_view
13310  *     hasn't been realized yet
13311  **/
13312 GdkWindow *
13313 gtk_tree_view_get_bin_window (GtkTreeView *tree_view)
13314 {
13315   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
13316
13317   return tree_view->priv->bin_window;
13318 }
13319
13320 /**
13321  * gtk_tree_view_get_path_at_pos:
13322  * @tree_view: A #GtkTreeView.
13323  * @x: The x position to be identified (relative to bin_window).
13324  * @y: The y position to be identified (relative to bin_window).
13325  * @path: (out) (allow-none): A pointer to a #GtkTreePath pointer to be filled in, or %NULL
13326  * @column: (out) (transfer none) (allow-none): A pointer to a #GtkTreeViewColumn pointer to be filled in, or %NULL
13327  * @cell_x: (out) (allow-none): A pointer where the X coordinate relative to the cell can be placed, or %NULL
13328  * @cell_y: (out) (allow-none): A pointer where the Y coordinate relative to the cell can be placed, or %NULL
13329  *
13330  * Finds the path at the point (@x, @y), relative to bin_window coordinates
13331  * (please see gtk_tree_view_get_bin_window()).
13332  * That is, @x and @y are relative to an events coordinates. @x and @y must
13333  * come from an event on the @tree_view only where <literal>event->window ==
13334  * gtk_tree_view_get_bin_window (<!-- -->)</literal>. It is primarily for
13335  * things like popup menus. If @path is non-%NULL, then it will be filled
13336  * with the #GtkTreePath at that point.  This path should be freed with
13337  * gtk_tree_path_free().  If @column is non-%NULL, then it will be filled
13338  * with the column at that point.  @cell_x and @cell_y return the coordinates
13339  * relative to the cell background (i.e. the @background_area passed to
13340  * gtk_cell_renderer_render()).  This function is only meaningful if
13341  * @tree_view is realized.  Therefore this function will always return %FALSE
13342  * if @tree_view is not realized or does not have a model.
13343  *
13344  * For converting widget coordinates (eg. the ones you get from
13345  * GtkWidget::query-tooltip), please see
13346  * gtk_tree_view_convert_widget_to_bin_window_coords().
13347  *
13348  * Return value: %TRUE if a row exists at that coordinate.
13349  **/
13350 gboolean
13351 gtk_tree_view_get_path_at_pos (GtkTreeView        *tree_view,
13352                                gint                x,
13353                                gint                y,
13354                                GtkTreePath       **path,
13355                                GtkTreeViewColumn **column,
13356                                gint               *cell_x,
13357                                gint               *cell_y)
13358 {
13359   GtkRBTree *tree;
13360   GtkRBNode *node;
13361   gint y_offset;
13362
13363   g_return_val_if_fail (tree_view != NULL, FALSE);
13364
13365   if (path)
13366     *path = NULL;
13367   if (column)
13368     *column = NULL;
13369
13370   if (tree_view->priv->bin_window == NULL)
13371     return FALSE;
13372
13373   if (tree_view->priv->tree == NULL)
13374     return FALSE;
13375
13376   if (x > gtk_adjustment_get_upper (tree_view->priv->hadjustment))
13377     return FALSE;
13378
13379   if (x < 0 || y < 0)
13380     return FALSE;
13381
13382   if (column || cell_x)
13383     {
13384       GtkTreeViewColumn *tmp_column;
13385       GtkTreeViewColumn *last_column = NULL;
13386       GList *list;
13387       gint remaining_x = x;
13388       gboolean found = FALSE;
13389       gboolean rtl;
13390       gint width;
13391
13392       rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
13393       for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
13394            list;
13395            list = (rtl ? list->prev : list->next))
13396         {
13397           tmp_column = list->data;
13398
13399           if (gtk_tree_view_column_get_visible (tmp_column) == FALSE)
13400             continue;
13401
13402           last_column = tmp_column;
13403           width = gtk_tree_view_column_get_width (tmp_column);
13404           if (remaining_x <= width)
13405             {
13406               found = TRUE;
13407
13408               if (column)
13409                 *column = tmp_column;
13410
13411               if (cell_x)
13412                 *cell_x = remaining_x;
13413
13414               break;
13415             }
13416           remaining_x -= width;
13417         }
13418
13419       /* If found is FALSE and there is a last_column, then it the remainder
13420        * space is in that area
13421        */
13422       if (!found)
13423         {
13424           if (last_column)
13425             {
13426               if (column)
13427                 *column = last_column;
13428               
13429               if (cell_x)
13430                 *cell_x = gtk_tree_view_column_get_width (last_column) + remaining_x;
13431             }
13432           else
13433             {
13434               return FALSE;
13435             }
13436         }
13437     }
13438
13439   y_offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
13440                                       TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y),
13441                                       &tree, &node);
13442
13443   if (tree == NULL)
13444     return FALSE;
13445
13446   if (cell_y)
13447     *cell_y = y_offset;
13448
13449   if (path)
13450     *path = _gtk_tree_view_find_path (tree_view, tree, node);
13451
13452   return TRUE;
13453 }
13454
13455
13456 static inline gint
13457 gtk_tree_view_get_cell_area_height (GtkTreeView *tree_view,
13458                                     GtkRBNode   *node,
13459                                     gint         vertical_separator)
13460 {
13461   int height;
13462
13463   /* The "cell" areas are the cell_area passed in to gtk_cell_renderer_render(),
13464    * i.e. just the cells, no spacing.
13465    *
13466    * The cell area height is at least expander_size - vertical_separator.
13467    * For regular nodes, the height is then at least expander_size. We should
13468    * be able to enforce the expander_size minimum here, because this
13469    * function will not be called for irregular (e.g. separator) rows.
13470    */
13471   height = gtk_tree_view_get_row_height (tree_view, node);
13472   if (height < tree_view->priv->expander_size)
13473     height = tree_view->priv->expander_size;
13474
13475   return height - vertical_separator;
13476 }
13477
13478 static inline gint
13479 gtk_tree_view_get_cell_area_y_offset (GtkTreeView *tree_view,
13480                                       GtkRBTree   *tree,
13481                                       GtkRBNode   *node,
13482                                       gint         vertical_separator)
13483 {
13484   int offset;
13485
13486   offset = gtk_tree_view_get_row_y_offset (tree_view, tree, node);
13487   offset += vertical_separator / 2;
13488
13489   return offset;
13490 }
13491
13492 /**
13493  * gtk_tree_view_get_cell_area:
13494  * @tree_view: a #GtkTreeView
13495  * @path: (allow-none): a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
13496  * @column: (allow-none): a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordinates
13497  * @rect: (out): rectangle to fill with cell rect
13498  *
13499  * Fills the bounding rectangle in bin_window coordinates for the cell at the
13500  * row specified by @path and the column specified by @column.  If @path is
13501  * %NULL, or points to a path not currently displayed, the @y and @height fields
13502  * of the rectangle will be filled with 0. If @column is %NULL, the @x and @width
13503  * fields will be filled with 0.  The sum of all cell rects does not cover the
13504  * entire tree; there are extra pixels in between rows, for example. The
13505  * returned rectangle is equivalent to the @cell_area passed to
13506  * gtk_cell_renderer_render().  This function is only valid if @tree_view is
13507  * realized.
13508  **/
13509 void
13510 gtk_tree_view_get_cell_area (GtkTreeView        *tree_view,
13511                              GtkTreePath        *path,
13512                              GtkTreeViewColumn  *column,
13513                              GdkRectangle       *rect)
13514 {
13515   GtkRBTree *tree = NULL;
13516   GtkRBNode *node = NULL;
13517   gint vertical_separator;
13518   gint horizontal_separator;
13519
13520   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
13521   g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
13522   g_return_if_fail (rect != NULL);
13523   g_return_if_fail (!column || gtk_tree_view_column_get_tree_view (column) == (GtkWidget *) tree_view);
13524   g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (tree_view)));
13525
13526   gtk_widget_style_get (GTK_WIDGET (tree_view),
13527                         "vertical-separator", &vertical_separator,
13528                         "horizontal-separator", &horizontal_separator,
13529                         NULL);
13530
13531   rect->x = 0;
13532   rect->y = 0;
13533   rect->width = 0;
13534   rect->height = 0;
13535
13536   if (column)
13537     {
13538       rect->x = gtk_tree_view_column_get_x_offset (column) + horizontal_separator/2;
13539       rect->width = gtk_tree_view_column_get_width (column) - horizontal_separator;
13540     }
13541
13542   if (path)
13543     {
13544       gboolean ret = _gtk_tree_view_find_node (tree_view, path, &tree, &node);
13545
13546       /* Get vertical coords */
13547       if ((!ret && tree == NULL) || ret)
13548         return;
13549
13550       if (row_is_separator (tree_view, NULL, path))
13551         {
13552           /* There isn't really a "cell area" for separator, so we
13553            * return the y, height values for background area instead.
13554            */
13555           rect->y = gtk_tree_view_get_row_y_offset (tree_view, tree, node);
13556           rect->height = gtk_tree_view_get_row_height (tree_view, node);
13557         }
13558       else
13559         {
13560           rect->y = gtk_tree_view_get_cell_area_y_offset (tree_view, tree, node,
13561                                                           vertical_separator);
13562           rect->height = gtk_tree_view_get_cell_area_height (tree_view, node,
13563                                                              vertical_separator);
13564         }
13565
13566       if (column &&
13567           gtk_tree_view_is_expander_column (tree_view, column))
13568         {
13569           gint depth = gtk_tree_path_get_depth (path);
13570           gboolean rtl;
13571
13572           rtl = gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL;
13573
13574           if (!rtl)
13575             rect->x += (depth - 1) * tree_view->priv->level_indentation;
13576           rect->width -= (depth - 1) * tree_view->priv->level_indentation;
13577
13578           if (gtk_tree_view_draw_expanders (tree_view))
13579             {
13580               if (!rtl)
13581                 rect->x += depth * tree_view->priv->expander_size;
13582               rect->width -= depth * tree_view->priv->expander_size;
13583             }
13584
13585           rect->width = MAX (rect->width, 0);
13586         }
13587     }
13588 }
13589
13590 static inline gint
13591 gtk_tree_view_get_row_height (GtkTreeView *tree_view,
13592                               GtkRBNode   *node)
13593 {
13594   int height;
13595
13596   /* The "background" areas of all rows/cells add up to cover the entire tree.
13597    * The background includes all inter-row and inter-cell spacing.
13598    *
13599    * If the row pointed at by node does not have a height set, we default
13600    * to expander_size, which is the minimum height for regular nodes.
13601    * Non-regular nodes (e.g. separators) can have a height set smaller
13602    * than expander_size and should not be overruled here.
13603    */
13604   height = GTK_RBNODE_GET_HEIGHT (node);
13605   if (height <= 0)
13606     height = tree_view->priv->expander_size;
13607
13608   return height;
13609 }
13610
13611 static inline gint
13612 gtk_tree_view_get_row_y_offset (GtkTreeView *tree_view,
13613                                 GtkRBTree   *tree,
13614                                 GtkRBNode   *node)
13615 {
13616   int offset;
13617
13618   offset = _gtk_rbtree_node_find_offset (tree, node);
13619
13620   return RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, offset);
13621 }
13622
13623 /**
13624  * gtk_tree_view_get_background_area:
13625  * @tree_view: a #GtkTreeView
13626  * @path: (allow-none): a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
13627  * @column: (allow-none): a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes
13628  * @rect: (out): rectangle to fill with cell background rect
13629  *
13630  * Fills the bounding rectangle in bin_window coordinates for the cell at the
13631  * row specified by @path and the column specified by @column.  If @path is
13632  * %NULL, or points to a node not found in the tree, the @y and @height fields of
13633  * the rectangle will be filled with 0. If @column is %NULL, the @x and @width
13634  * fields will be filled with 0.  The returned rectangle is equivalent to the
13635  * @background_area passed to gtk_cell_renderer_render().  These background
13636  * areas tile to cover the entire bin window.  Contrast with the @cell_area,
13637  * returned by gtk_tree_view_get_cell_area(), which returns only the cell
13638  * itself, excluding surrounding borders and the tree expander area.
13639  *
13640  **/
13641 void
13642 gtk_tree_view_get_background_area (GtkTreeView        *tree_view,
13643                                    GtkTreePath        *path,
13644                                    GtkTreeViewColumn  *column,
13645                                    GdkRectangle       *rect)
13646 {
13647   GtkRBTree *tree = NULL;
13648   GtkRBNode *node = NULL;
13649
13650   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
13651   g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
13652   g_return_if_fail (rect != NULL);
13653
13654   rect->x = 0;
13655   rect->y = 0;
13656   rect->width = 0;
13657   rect->height = 0;
13658
13659   if (path)
13660     {
13661       /* Get vertical coords */
13662
13663       if (!_gtk_tree_view_find_node (tree_view, path, &tree, &node) &&
13664           tree == NULL)
13665         return;
13666
13667       rect->y = gtk_tree_view_get_row_y_offset (tree_view, tree, node);
13668       rect->height = gtk_tree_view_get_row_height (tree_view, node);
13669     }
13670
13671   if (column)
13672     {
13673       gint x2 = 0;
13674
13675       gtk_tree_view_get_background_xrange (tree_view, tree, column, &rect->x, &x2);
13676       rect->width = x2 - rect->x;
13677     }
13678 }
13679
13680 /**
13681  * gtk_tree_view_get_visible_rect:
13682  * @tree_view: a #GtkTreeView
13683  * @visible_rect: (out): rectangle to fill
13684  *
13685  * Fills @visible_rect with the currently-visible region of the
13686  * buffer, in tree coordinates. Convert to bin_window coordinates with
13687  * gtk_tree_view_convert_tree_to_bin_window_coords().
13688  * Tree coordinates start at 0,0 for row 0 of the tree, and cover the entire
13689  * scrollable area of the tree.
13690  **/
13691 void
13692 gtk_tree_view_get_visible_rect (GtkTreeView  *tree_view,
13693                                 GdkRectangle *visible_rect)
13694 {
13695   GtkAllocation allocation;
13696   GtkWidget *widget;
13697
13698   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
13699
13700   widget = GTK_WIDGET (tree_view);
13701
13702   if (visible_rect)
13703     {
13704       gtk_widget_get_allocation (widget, &allocation);
13705       visible_rect->x = gtk_adjustment_get_value (tree_view->priv->hadjustment);
13706       visible_rect->y = gtk_adjustment_get_value (tree_view->priv->vadjustment);
13707       visible_rect->width = allocation.width;
13708       visible_rect->height = allocation.height - gtk_tree_view_get_effective_header_height (tree_view);
13709     }
13710 }
13711
13712 /**
13713  * gtk_tree_view_convert_widget_to_tree_coords:
13714  * @tree_view: a #GtkTreeView
13715  * @wx: X coordinate relative to the widget
13716  * @wy: Y coordinate relative to the widget
13717  * @tx: (out): return location for tree X coordinate
13718  * @ty: (out): return location for tree Y coordinate
13719  *
13720  * Converts widget coordinates to coordinates for the
13721  * tree (the full scrollable area of the tree).
13722  *
13723  * Since: 2.12
13724  **/
13725 void
13726 gtk_tree_view_convert_widget_to_tree_coords (GtkTreeView *tree_view,
13727                                              gint         wx,
13728                                              gint         wy,
13729                                              gint        *tx,
13730                                              gint        *ty)
13731 {
13732   gint x, y;
13733
13734   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
13735
13736   gtk_tree_view_convert_widget_to_bin_window_coords (tree_view,
13737                                                      wx, wy,
13738                                                      &x, &y);
13739   gtk_tree_view_convert_bin_window_to_tree_coords (tree_view,
13740                                                    x, y,
13741                                                    tx, ty);
13742 }
13743
13744 /**
13745  * gtk_tree_view_convert_tree_to_widget_coords:
13746  * @tree_view: a #GtkTreeView
13747  * @tx: X coordinate relative to the tree
13748  * @ty: Y coordinate relative to the tree
13749  * @wx: (out): return location for widget X coordinate
13750  * @wy: (out): return location for widget Y coordinate
13751  *
13752  * Converts tree coordinates (coordinates in full scrollable area of the tree)
13753  * to widget coordinates.
13754  *
13755  * Since: 2.12
13756  **/
13757 void
13758 gtk_tree_view_convert_tree_to_widget_coords (GtkTreeView *tree_view,
13759                                              gint         tx,
13760                                              gint         ty,
13761                                              gint        *wx,
13762                                              gint        *wy)
13763 {
13764   gint x, y;
13765
13766   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
13767
13768   gtk_tree_view_convert_tree_to_bin_window_coords (tree_view,
13769                                                    tx, ty,
13770                                                    &x, &y);
13771   gtk_tree_view_convert_bin_window_to_widget_coords (tree_view,
13772                                                      x, y,
13773                                                      wx, wy);
13774 }
13775
13776 /**
13777  * gtk_tree_view_convert_widget_to_bin_window_coords:
13778  * @tree_view: a #GtkTreeView
13779  * @wx: X coordinate relative to the widget
13780  * @wy: Y coordinate relative to the widget
13781  * @bx: (out): return location for bin_window X coordinate
13782  * @by: (out): return location for bin_window Y coordinate
13783  *
13784  * Converts widget coordinates to coordinates for the bin_window
13785  * (see gtk_tree_view_get_bin_window()).
13786  *
13787  * Since: 2.12
13788  **/
13789 void
13790 gtk_tree_view_convert_widget_to_bin_window_coords (GtkTreeView *tree_view,
13791                                                    gint         wx,
13792                                                    gint         wy,
13793                                                    gint        *bx,
13794                                                    gint        *by)
13795 {
13796   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
13797
13798   if (bx)
13799     *bx = wx + gtk_adjustment_get_value (tree_view->priv->hadjustment);
13800   if (by)
13801     *by = wy - gtk_tree_view_get_effective_header_height (tree_view);
13802 }
13803
13804 /**
13805  * gtk_tree_view_convert_bin_window_to_widget_coords:
13806  * @tree_view: a #GtkTreeView
13807  * @bx: bin_window X coordinate
13808  * @by: bin_window Y coordinate
13809  * @wx: (out): return location for widget X coordinate
13810  * @wy: (out): return location for widget Y coordinate
13811  *
13812  * Converts bin_window coordinates (see gtk_tree_view_get_bin_window())
13813  * to widget relative coordinates.
13814  *
13815  * Since: 2.12
13816  **/
13817 void
13818 gtk_tree_view_convert_bin_window_to_widget_coords (GtkTreeView *tree_view,
13819                                                    gint         bx,
13820                                                    gint         by,
13821                                                    gint        *wx,
13822                                                    gint        *wy)
13823 {
13824   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
13825
13826   if (wx)
13827     *wx = bx - gtk_adjustment_get_value (tree_view->priv->hadjustment);
13828   if (wy)
13829     *wy = by + gtk_tree_view_get_effective_header_height (tree_view);
13830 }
13831
13832 /**
13833  * gtk_tree_view_convert_tree_to_bin_window_coords:
13834  * @tree_view: a #GtkTreeView
13835  * @tx: tree X coordinate
13836  * @ty: tree Y coordinate
13837  * @bx: (out): return location for X coordinate relative to bin_window
13838  * @by: (out): return location for Y coordinate relative to bin_window
13839  *
13840  * Converts tree coordinates (coordinates in full scrollable area of the tree)
13841  * to bin_window coordinates.
13842  *
13843  * Since: 2.12
13844  **/
13845 void
13846 gtk_tree_view_convert_tree_to_bin_window_coords (GtkTreeView *tree_view,
13847                                                  gint         tx,
13848                                                  gint         ty,
13849                                                  gint        *bx,
13850                                                  gint        *by)
13851 {
13852   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
13853
13854   if (bx)
13855     *bx = tx;
13856   if (by)
13857     *by = ty - tree_view->priv->dy;
13858 }
13859
13860 /**
13861  * gtk_tree_view_convert_bin_window_to_tree_coords:
13862  * @tree_view: a #GtkTreeView
13863  * @bx: X coordinate relative to bin_window
13864  * @by: Y coordinate relative to bin_window
13865  * @tx: (out): return location for tree X coordinate
13866  * @ty: (out): return location for tree Y coordinate
13867  *
13868  * Converts bin_window coordinates to coordinates for the
13869  * tree (the full scrollable area of the tree).
13870  *
13871  * Since: 2.12
13872  **/
13873 void
13874 gtk_tree_view_convert_bin_window_to_tree_coords (GtkTreeView *tree_view,
13875                                                  gint         bx,
13876                                                  gint         by,
13877                                                  gint        *tx,
13878                                                  gint        *ty)
13879 {
13880   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
13881
13882   if (tx)
13883     *tx = bx;
13884   if (ty)
13885     *ty = by + tree_view->priv->dy;
13886 }
13887
13888
13889
13890 /**
13891  * gtk_tree_view_get_visible_range:
13892  * @tree_view: A #GtkTreeView
13893  * @start_path: (out) (allow-none): Return location for start of region,
13894  *              or %NULL.
13895  * @end_path: (out) (allow-none): Return location for end of region, or %NULL.
13896  *
13897  * Sets @start_path and @end_path to be the first and last visible path.
13898  * Note that there may be invisible paths in between.
13899  *
13900  * The paths should be freed with gtk_tree_path_free() after use.
13901  *
13902  * Returns: %TRUE, if valid paths were placed in @start_path and @end_path.
13903  *
13904  * Since: 2.8
13905  **/
13906 gboolean
13907 gtk_tree_view_get_visible_range (GtkTreeView  *tree_view,
13908                                  GtkTreePath **start_path,
13909                                  GtkTreePath **end_path)
13910 {
13911   GtkRBTree *tree;
13912   GtkRBNode *node;
13913   gboolean retval;
13914   
13915   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
13916
13917   if (!tree_view->priv->tree)
13918     return FALSE;
13919
13920   retval = TRUE;
13921
13922   if (start_path)
13923     {
13924       _gtk_rbtree_find_offset (tree_view->priv->tree,
13925                                TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, 0),
13926                                &tree, &node);
13927       if (node)
13928         *start_path = _gtk_tree_view_find_path (tree_view, tree, node);
13929       else
13930         retval = FALSE;
13931     }
13932
13933   if (end_path)
13934     {
13935       gint y;
13936
13937       if (tree_view->priv->height < gtk_adjustment_get_page_size (tree_view->priv->vadjustment))
13938         y = tree_view->priv->height - 1;
13939       else
13940         y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, gtk_adjustment_get_page_size (tree_view->priv->vadjustment)) - 1;
13941
13942       _gtk_rbtree_find_offset (tree_view->priv->tree, y, &tree, &node);
13943       if (node)
13944         *end_path = _gtk_tree_view_find_path (tree_view, tree, node);
13945       else
13946         retval = FALSE;
13947     }
13948
13949   return retval;
13950 }
13951
13952 /**
13953  * gtk_tree_view_is_blank_at_pos:
13954  * @tree_view: A #GtkTreeView
13955  * @x: The x position to be identified (relative to bin_window)
13956  * @y: The y position to be identified (relative to bin_window)
13957  * @path: (out) (allow-none): A pointer to a #GtkTreePath pointer to be filled in, or %NULL
13958  * @column: (out) (allow-none): A pointer to a #GtkTreeViewColumn pointer to be filled in, or %NULL
13959  * @cell_x: (out) (allow-none): A pointer where the X coordinate relative to the cell can be placed, or %NULL
13960  * @cell_y: (out) (allow-none): A pointer where the Y coordinate relative to the cell can be placed, or %NULL
13961  *
13962  * Determine whether the point (@x, @y) in @tree_view is blank, that is no
13963  * cell content nor an expander arrow is drawn at the location. If so, the
13964  * location can be considered as the background. You might wish to take
13965  * special action on clicks on the background, such as clearing a current
13966  * selection, having a custom context menu or starting rubber banding.
13967  *
13968  * The @x and @y coordinate that are provided must be relative to bin_window
13969  * coordinates.  That is, @x and @y must come from an event on @tree_view
13970  * where <literal>event->window == gtk_tree_view_get_bin_window (<!-- -->)</literal>.
13971  *
13972  * For converting widget coordinates (eg. the ones you get from
13973  * GtkWidget::query-tooltip), please see
13974  * gtk_tree_view_convert_widget_to_bin_window_coords().
13975  *
13976  * The @path, @column, @cell_x and @cell_y arguments will be filled in
13977  * likewise as for gtk_tree_view_get_path_at_pos().  Please see
13978  * gtk_tree_view_get_path_at_pos() for more information.
13979  *
13980  * Return value: %TRUE if the area at the given coordinates is blank,
13981  * %FALSE otherwise.
13982  *
13983  * Since: 3.0
13984  */
13985 gboolean
13986 gtk_tree_view_is_blank_at_pos (GtkTreeView       *tree_view,
13987                                gint                x,
13988                                gint                y,
13989                                GtkTreePath       **path,
13990                                GtkTreeViewColumn **column,
13991                                gint               *cell_x,
13992                                gint               *cell_y)
13993 {
13994   GtkRBTree *tree;
13995   GtkRBNode *node;
13996   GtkTreeIter iter;
13997   GtkTreePath *real_path;
13998   GtkTreeViewColumn *real_column;
13999   GdkRectangle cell_area, background_area;
14000
14001   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
14002
14003   if (!gtk_tree_view_get_path_at_pos (tree_view, x, y,
14004                                       &real_path, &real_column,
14005                                       cell_x, cell_y))
14006     /* If there's no path here, it is blank */
14007     return TRUE;
14008
14009   if (path)
14010     *path = real_path;
14011
14012   if (column)
14013     *column = real_column;
14014
14015   gtk_tree_model_get_iter (tree_view->priv->model, &iter, real_path);
14016   _gtk_tree_view_find_node (tree_view, real_path, &tree, &node);
14017
14018   /* Check if there's an expander arrow at (x, y) */
14019   if (real_column == tree_view->priv->expander_column
14020       && gtk_tree_view_draw_expanders (tree_view))
14021     {
14022       gboolean over_arrow;
14023
14024       over_arrow = coords_are_over_arrow (tree_view, tree, node, x, y);
14025
14026       if (over_arrow)
14027         {
14028           if (!path)
14029             gtk_tree_path_free (real_path);
14030           return FALSE;
14031         }
14032     }
14033
14034   /* Otherwise, have the column see if there's a cell at (x, y) */
14035   gtk_tree_view_column_cell_set_cell_data (real_column,
14036                                            tree_view->priv->model,
14037                                            &iter,
14038                                            GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
14039                                            node->children ? TRUE : FALSE);
14040
14041   gtk_tree_view_get_background_area (tree_view, real_path, real_column,
14042                                      &background_area);
14043   gtk_tree_view_get_cell_area (tree_view, real_path, real_column,
14044                                &cell_area);
14045
14046   if (!path)
14047     gtk_tree_path_free (real_path);
14048
14049   return _gtk_tree_view_column_is_blank_at_pos (real_column,
14050                                                 &cell_area,
14051                                                 &background_area,
14052                                                 x, y);
14053 }
14054
14055 static void
14056 unset_reorderable (GtkTreeView *tree_view)
14057 {
14058   if (tree_view->priv->reorderable)
14059     {
14060       tree_view->priv->reorderable = FALSE;
14061       g_object_notify (G_OBJECT (tree_view), "reorderable");
14062     }
14063 }
14064
14065 /**
14066  * gtk_tree_view_enable_model_drag_source:
14067  * @tree_view: a #GtkTreeView
14068  * @start_button_mask: Mask of allowed buttons to start drag
14069  * @targets: (array length=n_targets): the table of targets that the drag will support
14070  * @n_targets: the number of items in @targets
14071  * @actions: the bitmask of possible actions for a drag from this
14072  *    widget
14073  *
14074  * Turns @tree_view into a drag source for automatic DND. Calling this
14075  * method sets #GtkTreeView:reorderable to %FALSE.
14076  **/
14077 void
14078 gtk_tree_view_enable_model_drag_source (GtkTreeView              *tree_view,
14079                                         GdkModifierType           start_button_mask,
14080                                         const GtkTargetEntry     *targets,
14081                                         gint                      n_targets,
14082                                         GdkDragAction             actions)
14083 {
14084   TreeViewDragInfo *di;
14085
14086   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
14087
14088   gtk_drag_source_set (GTK_WIDGET (tree_view),
14089                        0,
14090                        targets,
14091                        n_targets,
14092                        actions);
14093
14094   di = ensure_info (tree_view);
14095
14096   di->start_button_mask = start_button_mask;
14097   di->source_actions = actions;
14098   di->source_set = TRUE;
14099
14100   unset_reorderable (tree_view);
14101 }
14102
14103 /**
14104  * gtk_tree_view_enable_model_drag_dest:
14105  * @tree_view: a #GtkTreeView
14106  * @targets: (array length=n_targets): the table of targets that
14107  *           the drag will support
14108  * @n_targets: the number of items in @targets
14109  * @actions: the bitmask of possible actions for a drag from this
14110  *    widget
14111  * 
14112  * Turns @tree_view into a drop destination for automatic DND. Calling
14113  * this method sets #GtkTreeView:reorderable to %FALSE.
14114  **/
14115 void
14116 gtk_tree_view_enable_model_drag_dest (GtkTreeView              *tree_view,
14117                                       const GtkTargetEntry     *targets,
14118                                       gint                      n_targets,
14119                                       GdkDragAction             actions)
14120 {
14121   TreeViewDragInfo *di;
14122
14123   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
14124
14125   gtk_drag_dest_set (GTK_WIDGET (tree_view),
14126                      0,
14127                      targets,
14128                      n_targets,
14129                      actions);
14130
14131   di = ensure_info (tree_view);
14132   di->dest_set = TRUE;
14133
14134   unset_reorderable (tree_view);
14135 }
14136
14137 /**
14138  * gtk_tree_view_unset_rows_drag_source:
14139  * @tree_view: a #GtkTreeView
14140  *
14141  * Undoes the effect of
14142  * gtk_tree_view_enable_model_drag_source(). Calling this method sets
14143  * #GtkTreeView:reorderable to %FALSE.
14144  **/
14145 void
14146 gtk_tree_view_unset_rows_drag_source (GtkTreeView *tree_view)
14147 {
14148   TreeViewDragInfo *di;
14149
14150   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
14151
14152   di = get_info (tree_view);
14153
14154   if (di)
14155     {
14156       if (di->source_set)
14157         {
14158           gtk_drag_source_unset (GTK_WIDGET (tree_view));
14159           di->source_set = FALSE;
14160         }
14161
14162       if (!di->dest_set && !di->source_set)
14163         remove_info (tree_view);
14164     }
14165   
14166   unset_reorderable (tree_view);
14167 }
14168
14169 /**
14170  * gtk_tree_view_unset_rows_drag_dest:
14171  * @tree_view: a #GtkTreeView
14172  *
14173  * Undoes the effect of
14174  * gtk_tree_view_enable_model_drag_dest(). Calling this method sets
14175  * #GtkTreeView:reorderable to %FALSE.
14176  **/
14177 void
14178 gtk_tree_view_unset_rows_drag_dest (GtkTreeView *tree_view)
14179 {
14180   TreeViewDragInfo *di;
14181
14182   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
14183
14184   di = get_info (tree_view);
14185
14186   if (di)
14187     {
14188       if (di->dest_set)
14189         {
14190           gtk_drag_dest_unset (GTK_WIDGET (tree_view));
14191           di->dest_set = FALSE;
14192         }
14193
14194       if (!di->dest_set && !di->source_set)
14195         remove_info (tree_view);
14196     }
14197
14198   unset_reorderable (tree_view);
14199 }
14200
14201 /**
14202  * gtk_tree_view_set_drag_dest_row:
14203  * @tree_view: a #GtkTreeView
14204  * @path: (allow-none): The path of the row to highlight, or %NULL.
14205  * @pos: Specifies whether to drop before, after or into the row
14206  * 
14207  * Sets the row that is highlighted for feedback.
14208  **/
14209 void
14210 gtk_tree_view_set_drag_dest_row (GtkTreeView            *tree_view,
14211                                  GtkTreePath            *path,
14212                                  GtkTreeViewDropPosition pos)
14213 {
14214   GtkTreePath *current_dest;
14215
14216   /* Note; this function is exported to allow a custom DND
14217    * implementation, so it can't touch TreeViewDragInfo
14218    */
14219
14220   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
14221
14222   current_dest = NULL;
14223
14224   if (tree_view->priv->drag_dest_row)
14225     {
14226       current_dest = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
14227       gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
14228     }
14229
14230   /* special case a drop on an empty model */
14231   tree_view->priv->empty_view_drop = 0;
14232
14233   if (pos == GTK_TREE_VIEW_DROP_BEFORE && path
14234       && gtk_tree_path_get_depth (path) == 1
14235       && gtk_tree_path_get_indices (path)[0] == 0)
14236     {
14237       gint n_children;
14238
14239       n_children = gtk_tree_model_iter_n_children (tree_view->priv->model,
14240                                                    NULL);
14241
14242       if (!n_children)
14243         tree_view->priv->empty_view_drop = 1;
14244     }
14245
14246   tree_view->priv->drag_dest_pos = pos;
14247
14248   if (path)
14249     {
14250       tree_view->priv->drag_dest_row =
14251         gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
14252       gtk_tree_view_queue_draw_path (tree_view, path, NULL);
14253     }
14254   else
14255     tree_view->priv->drag_dest_row = NULL;
14256
14257   if (current_dest)
14258     {
14259       GtkRBTree *tree, *new_tree;
14260       GtkRBNode *node, *new_node;
14261
14262       _gtk_tree_view_find_node (tree_view, current_dest, &tree, &node);
14263       _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
14264
14265       if (tree && node)
14266         {
14267           _gtk_rbtree_next_full (tree, node, &new_tree, &new_node);
14268           if (new_tree && new_node)
14269             _gtk_tree_view_queue_draw_node (tree_view, new_tree, new_node, NULL);
14270
14271           _gtk_rbtree_prev_full (tree, node, &new_tree, &new_node);
14272           if (new_tree && new_node)
14273             _gtk_tree_view_queue_draw_node (tree_view, new_tree, new_node, NULL);
14274         }
14275       gtk_tree_path_free (current_dest);
14276     }
14277 }
14278
14279 /**
14280  * gtk_tree_view_get_drag_dest_row:
14281  * @tree_view: a #GtkTreeView
14282  * @path: (out) (allow-none): Return location for the path of the highlighted row, or %NULL.
14283  * @pos: (out) (allow-none): Return location for the drop position, or %NULL
14284  * 
14285  * Gets information about the row that is highlighted for feedback.
14286  **/
14287 void
14288 gtk_tree_view_get_drag_dest_row (GtkTreeView              *tree_view,
14289                                  GtkTreePath             **path,
14290                                  GtkTreeViewDropPosition  *pos)
14291 {
14292   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
14293
14294   if (path)
14295     {
14296       if (tree_view->priv->drag_dest_row)
14297         *path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
14298       else
14299         {
14300           if (tree_view->priv->empty_view_drop)
14301             *path = gtk_tree_path_new_from_indices (0, -1);
14302           else
14303             *path = NULL;
14304         }
14305     }
14306
14307   if (pos)
14308     *pos = tree_view->priv->drag_dest_pos;
14309 }
14310
14311 /**
14312  * gtk_tree_view_get_dest_row_at_pos:
14313  * @tree_view: a #GtkTreeView
14314  * @drag_x: the position to determine the destination row for
14315  * @drag_y: the position to determine the destination row for
14316  * @path: (out) (allow-none): Return location for the path of the highlighted row, or %NULL.
14317  * @pos: (out) (allow-none): Return location for the drop position, or %NULL
14318  * 
14319  * Determines the destination row for a given position.  @drag_x and
14320  * @drag_y are expected to be in widget coordinates.  This function is only
14321  * meaningful if @tree_view is realized.  Therefore this function will always
14322  * return %FALSE if @tree_view is not realized or does not have a model.
14323  * 
14324  * Return value: whether there is a row at the given position, %TRUE if this
14325  * is indeed the case.
14326  **/
14327 gboolean
14328 gtk_tree_view_get_dest_row_at_pos (GtkTreeView             *tree_view,
14329                                    gint                     drag_x,
14330                                    gint                     drag_y,
14331                                    GtkTreePath            **path,
14332                                    GtkTreeViewDropPosition *pos)
14333 {
14334   gint cell_y;
14335   gint bin_x, bin_y;
14336   gdouble offset_into_row;
14337   gdouble third;
14338   GdkRectangle cell;
14339   GtkTreeViewColumn *column = NULL;
14340   GtkTreePath *tmp_path = NULL;
14341
14342   /* Note; this function is exported to allow a custom DND
14343    * implementation, so it can't touch TreeViewDragInfo
14344    */
14345
14346   g_return_val_if_fail (tree_view != NULL, FALSE);
14347   g_return_val_if_fail (drag_x >= 0, FALSE);
14348   g_return_val_if_fail (drag_y >= 0, FALSE);
14349
14350   if (path)
14351     *path = NULL;
14352
14353   if (tree_view->priv->bin_window == NULL)
14354     return FALSE;
14355
14356   if (tree_view->priv->tree == NULL)
14357     return FALSE;
14358
14359   /* If in the top third of a row, we drop before that row; if
14360    * in the bottom third, drop after that row; if in the middle,
14361    * and the row has children, drop into the row.
14362    */
14363   gtk_tree_view_convert_widget_to_bin_window_coords (tree_view, drag_x, drag_y,
14364                                                      &bin_x, &bin_y);
14365
14366   if (!gtk_tree_view_get_path_at_pos (tree_view,
14367                                       bin_x,
14368                                       bin_y,
14369                                       &tmp_path,
14370                                       &column,
14371                                       NULL,
14372                                       &cell_y))
14373     return FALSE;
14374
14375   gtk_tree_view_get_background_area (tree_view, tmp_path, column,
14376                                      &cell);
14377
14378   offset_into_row = cell_y;
14379
14380   if (path)
14381     *path = tmp_path;
14382   else
14383     gtk_tree_path_free (tmp_path);
14384
14385   tmp_path = NULL;
14386
14387   third = cell.height / 3.0;
14388
14389   if (pos)
14390     {
14391       if (offset_into_row < third)
14392         {
14393           *pos = GTK_TREE_VIEW_DROP_BEFORE;
14394         }
14395       else if (offset_into_row < (cell.height / 2.0))
14396         {
14397           *pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE;
14398         }
14399       else if (offset_into_row < third * 2.0)
14400         {
14401           *pos = GTK_TREE_VIEW_DROP_INTO_OR_AFTER;
14402         }
14403       else
14404         {
14405           *pos = GTK_TREE_VIEW_DROP_AFTER;
14406         }
14407     }
14408
14409   return TRUE;
14410 }
14411
14412
14413
14414 /* KEEP IN SYNC WITH GTK_TREE_VIEW_BIN_EXPOSE */
14415 /**
14416  * gtk_tree_view_create_row_drag_icon:
14417  * @tree_view: a #GtkTreeView
14418  * @path: a #GtkTreePath in @tree_view
14419  *
14420  * Creates a #cairo_surface_t representation of the row at @path.  
14421  * This image is used for a drag icon.
14422  *
14423  * Return value: (transfer full): a newly-allocated surface of the drag icon.
14424  **/
14425 cairo_surface_t *
14426 gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
14427                                     GtkTreePath  *path)
14428 {
14429   GtkTreeIter   iter;
14430   GtkRBTree    *tree;
14431   GtkRBNode    *node;
14432   GtkStyleContext *context;
14433   GtkStateFlags state;
14434   gint cell_offset;
14435   GList *list;
14436   GdkRectangle background_area;
14437   GtkWidget *widget;
14438   gint depth;
14439   /* start drawing inside the black outline */
14440   gint x = 1, y = 1;
14441   cairo_surface_t *surface;
14442   gint bin_window_width;
14443   gboolean is_separator = FALSE;
14444   gboolean rtl, allow_rules;
14445   cairo_t *cr;
14446
14447   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
14448   g_return_val_if_fail (path != NULL, NULL);
14449
14450   widget = GTK_WIDGET (tree_view);
14451
14452   if (!gtk_widget_get_realized (widget))
14453     return NULL;
14454
14455   depth = gtk_tree_path_get_depth (path);
14456
14457   _gtk_tree_view_find_node (tree_view,
14458                             path,
14459                             &tree,
14460                             &node);
14461
14462   if (tree == NULL)
14463     return NULL;
14464
14465   if (!gtk_tree_model_get_iter (tree_view->priv->model,
14466                                 &iter,
14467                                 path))
14468     return NULL;
14469
14470   context = gtk_widget_get_style_context (widget);
14471
14472   gtk_style_context_save (context);
14473
14474   state = gtk_widget_get_state_flags (widget);
14475   gtk_style_context_set_state (context, state);
14476
14477   gtk_style_context_add_class (context, GTK_STYLE_CLASS_VIEW);
14478   gtk_style_context_add_region (context, GTK_STYLE_REGION_COLUMN, 0);
14479
14480   gtk_widget_style_get (widget,
14481                         "allow-rules", &allow_rules,
14482                         NULL);
14483
14484   if (allow_rules && tree_view->priv->has_rules)
14485     {
14486       GtkRegionFlags row_flags;
14487
14488       if (_gtk_rbtree_node_find_parity (tree, node))
14489         row_flags = GTK_REGION_ODD;
14490       else
14491         row_flags = GTK_REGION_EVEN;
14492
14493       gtk_style_context_add_region (context, GTK_STYLE_REGION_ROW, row_flags);
14494     }
14495
14496   is_separator = row_is_separator (tree_view, &iter, NULL);
14497
14498   cell_offset = x;
14499
14500   background_area.y = y;
14501   background_area.height = gtk_tree_view_get_row_height (tree_view, node);
14502
14503   bin_window_width = gdk_window_get_width (tree_view->priv->bin_window);
14504
14505   surface = gdk_window_create_similar_surface (tree_view->priv->bin_window,
14506                                                CAIRO_CONTENT_COLOR,
14507                                                bin_window_width + 2,
14508                                                background_area.height + 2);
14509
14510   cr = cairo_create (surface);
14511
14512   gtk_render_background (context, cr, 0, 0,
14513                          bin_window_width + 2,
14514                          background_area.height + 2);
14515
14516   rtl = gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL;
14517
14518   for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
14519       list;
14520       list = (rtl ? list->prev : list->next))
14521     {
14522       GtkTreeViewColumn *column = list->data;
14523       GdkRectangle cell_area;
14524       gint vertical_separator;
14525
14526       if (!gtk_tree_view_column_get_visible (column))
14527         continue;
14528
14529       gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, &iter,
14530                                                GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
14531                                                node->children?TRUE:FALSE);
14532
14533       background_area.x = cell_offset;
14534       background_area.width = gtk_tree_view_column_get_width (column);
14535
14536       gtk_widget_style_get (widget,
14537                             "vertical-separator", &vertical_separator,
14538                             NULL);
14539
14540       cell_area = background_area;
14541
14542       cell_area.y += vertical_separator / 2;
14543       cell_area.height -= vertical_separator;
14544
14545       if (gtk_tree_view_is_expander_column (tree_view, column))
14546         {
14547           if (!rtl)
14548             cell_area.x += (depth - 1) * tree_view->priv->level_indentation;
14549           cell_area.width -= (depth - 1) * tree_view->priv->level_indentation;
14550
14551           if (gtk_tree_view_draw_expanders (tree_view))
14552             {
14553               if (!rtl)
14554                 cell_area.x += depth * tree_view->priv->expander_size;
14555               cell_area.width -= depth * tree_view->priv->expander_size;
14556             }
14557         }
14558
14559       if (gtk_tree_view_column_cell_is_visible (column))
14560         {
14561           if (is_separator)
14562             gtk_render_line (context, cr,
14563                              cell_area.x,
14564                              cell_area.y + cell_area.height / 2,
14565                              cell_area.x + cell_area.width,
14566                              cell_area.y + cell_area.height / 2);
14567           else
14568             _gtk_tree_view_column_cell_render (column,
14569                                                cr,
14570                                                &background_area,
14571                                                &cell_area,
14572                                                0, FALSE);
14573         }
14574       cell_offset += gtk_tree_view_column_get_width (column);
14575     }
14576
14577   cairo_set_source_rgb (cr, 0, 0, 0);
14578   cairo_rectangle (cr, 
14579                    0.5, 0.5, 
14580                    bin_window_width + 1,
14581                    background_area.height + 1);
14582   cairo_set_line_width (cr, 1.0);
14583   cairo_stroke (cr);
14584
14585   cairo_destroy (cr);
14586
14587   cairo_surface_set_device_offset (surface, 2, 2);
14588
14589   gtk_style_context_restore (context);
14590
14591   return surface;
14592 }
14593
14594
14595 /**
14596  * gtk_tree_view_set_destroy_count_func:
14597  * @tree_view: A #GtkTreeView
14598  * @func: (allow-none): Function to be called when a view row is destroyed, or %NULL
14599  * @data: (allow-none): User data to be passed to @func, or %NULL
14600  * @destroy: (allow-none): Destroy notifier for @data, or %NULL
14601  *
14602  * This function should almost never be used.  It is meant for private use by
14603  * ATK for determining the number of visible children that are removed when the
14604  * user collapses a row, or a row is deleted.
14605  **/
14606 void
14607 gtk_tree_view_set_destroy_count_func (GtkTreeView             *tree_view,
14608                                       GtkTreeDestroyCountFunc  func,
14609                                       gpointer                 data,
14610                                       GDestroyNotify           destroy)
14611 {
14612   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
14613
14614   if (tree_view->priv->destroy_count_destroy)
14615     tree_view->priv->destroy_count_destroy (tree_view->priv->destroy_count_data);
14616
14617   tree_view->priv->destroy_count_func = func;
14618   tree_view->priv->destroy_count_data = data;
14619   tree_view->priv->destroy_count_destroy = destroy;
14620 }
14621
14622
14623 /*
14624  * Interactive search
14625  */
14626
14627 /**
14628  * gtk_tree_view_set_enable_search:
14629  * @tree_view: A #GtkTreeView
14630  * @enable_search: %TRUE, if the user can search interactively
14631  *
14632  * If @enable_search is set, then the user can type in text to search through
14633  * the tree interactively (this is sometimes called "typeahead find").
14634  * 
14635  * Note that even if this is %FALSE, the user can still initiate a search 
14636  * using the "start-interactive-search" key binding.
14637  */
14638 void
14639 gtk_tree_view_set_enable_search (GtkTreeView *tree_view,
14640                                  gboolean     enable_search)
14641 {
14642   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
14643
14644   enable_search = !!enable_search;
14645   
14646   if (tree_view->priv->enable_search != enable_search)
14647     {
14648        tree_view->priv->enable_search = enable_search;
14649        g_object_notify (G_OBJECT (tree_view), "enable-search");
14650     }
14651 }
14652
14653 /**
14654  * gtk_tree_view_get_enable_search:
14655  * @tree_view: A #GtkTreeView
14656  *
14657  * Returns whether or not the tree allows to start interactive searching 
14658  * by typing in text.
14659  *
14660  * Return value: whether or not to let the user search interactively
14661  */
14662 gboolean
14663 gtk_tree_view_get_enable_search (GtkTreeView *tree_view)
14664 {
14665   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
14666
14667   return tree_view->priv->enable_search;
14668 }
14669
14670
14671 /**
14672  * gtk_tree_view_get_search_column:
14673  * @tree_view: A #GtkTreeView
14674  *
14675  * Gets the column searched on by the interactive search code.
14676  *
14677  * Return value: the column the interactive search code searches in.
14678  */
14679 gint
14680 gtk_tree_view_get_search_column (GtkTreeView *tree_view)
14681 {
14682   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
14683
14684   return (tree_view->priv->search_column);
14685 }
14686
14687 /**
14688  * gtk_tree_view_set_search_column:
14689  * @tree_view: A #GtkTreeView
14690  * @column: the column of the model to search in, or -1 to disable searching
14691  *
14692  * Sets @column as the column where the interactive search code should
14693  * search in for the current model. 
14694  * 
14695  * If the search column is set, users can use the "start-interactive-search"
14696  * key binding to bring up search popup. The enable-search property controls
14697  * whether simply typing text will also start an interactive search.
14698  *
14699  * Note that @column refers to a column of the current model. The search 
14700  * column is reset to -1 when the model is changed.
14701  */
14702 void
14703 gtk_tree_view_set_search_column (GtkTreeView *tree_view,
14704                                  gint         column)
14705 {
14706   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
14707   g_return_if_fail (column >= -1);
14708
14709   if (tree_view->priv->search_column == column)
14710     return;
14711
14712   tree_view->priv->search_column = column;
14713   g_object_notify (G_OBJECT (tree_view), "search-column");
14714 }
14715
14716 /**
14717  * gtk_tree_view_get_search_equal_func: (skip)
14718  * @tree_view: A #GtkTreeView
14719  *
14720  * Returns the compare function currently in use.
14721  *
14722  * Return value: the currently used compare function for the search code.
14723  */
14724
14725 GtkTreeViewSearchEqualFunc
14726 gtk_tree_view_get_search_equal_func (GtkTreeView *tree_view)
14727 {
14728   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
14729
14730   return tree_view->priv->search_equal_func;
14731 }
14732
14733 /**
14734  * gtk_tree_view_set_search_equal_func:
14735  * @tree_view: A #GtkTreeView
14736  * @search_equal_func: the compare function to use during the search
14737  * @search_user_data: (allow-none): user data to pass to @search_equal_func, or %NULL
14738  * @search_destroy: (allow-none): Destroy notifier for @search_user_data, or %NULL
14739  *
14740  * Sets the compare function for the interactive search capabilities; note
14741  * that somewhat like strcmp() returning 0 for equality
14742  * #GtkTreeViewSearchEqualFunc returns %FALSE on matches.
14743  **/
14744 void
14745 gtk_tree_view_set_search_equal_func (GtkTreeView                *tree_view,
14746                                      GtkTreeViewSearchEqualFunc  search_equal_func,
14747                                      gpointer                    search_user_data,
14748                                      GDestroyNotify              search_destroy)
14749 {
14750   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
14751   g_return_if_fail (search_equal_func != NULL);
14752
14753   if (tree_view->priv->search_destroy)
14754     tree_view->priv->search_destroy (tree_view->priv->search_user_data);
14755
14756   tree_view->priv->search_equal_func = search_equal_func;
14757   tree_view->priv->search_user_data = search_user_data;
14758   tree_view->priv->search_destroy = search_destroy;
14759   if (tree_view->priv->search_equal_func == NULL)
14760     tree_view->priv->search_equal_func = gtk_tree_view_search_equal_func;
14761 }
14762
14763 /**
14764  * gtk_tree_view_get_search_entry:
14765  * @tree_view: A #GtkTreeView
14766  *
14767  * Returns the #GtkEntry which is currently in use as interactive search
14768  * entry for @tree_view.  In case the built-in entry is being used, %NULL
14769  * will be returned.
14770  *
14771  * Return value: (transfer none): the entry currently in use as search entry.
14772  *
14773  * Since: 2.10
14774  */
14775 GtkEntry *
14776 gtk_tree_view_get_search_entry (GtkTreeView *tree_view)
14777 {
14778   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
14779
14780   if (tree_view->priv->search_custom_entry_set)
14781     return GTK_ENTRY (tree_view->priv->search_entry);
14782
14783   return NULL;
14784 }
14785
14786 /**
14787  * gtk_tree_view_set_search_entry:
14788  * @tree_view: A #GtkTreeView
14789  * @entry: (allow-none): the entry the interactive search code of @tree_view should use or %NULL
14790  *
14791  * Sets the entry which the interactive search code will use for this
14792  * @tree_view.  This is useful when you want to provide a search entry
14793  * in our interface at all time at a fixed position.  Passing %NULL for
14794  * @entry will make the interactive search code use the built-in popup
14795  * entry again.
14796  *
14797  * Since: 2.10
14798  */
14799 void
14800 gtk_tree_view_set_search_entry (GtkTreeView *tree_view,
14801                                 GtkEntry    *entry)
14802 {
14803   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
14804   g_return_if_fail (entry == NULL || GTK_IS_ENTRY (entry));
14805
14806   if (tree_view->priv->search_custom_entry_set)
14807     {
14808       if (tree_view->priv->search_entry_changed_id)
14809         {
14810           g_signal_handler_disconnect (tree_view->priv->search_entry,
14811                                        tree_view->priv->search_entry_changed_id);
14812           tree_view->priv->search_entry_changed_id = 0;
14813         }
14814       g_signal_handlers_disconnect_by_func (tree_view->priv->search_entry,
14815                                             G_CALLBACK (gtk_tree_view_search_key_press_event),
14816                                             tree_view);
14817
14818       g_object_unref (tree_view->priv->search_entry);
14819     }
14820   else if (tree_view->priv->search_window)
14821     {
14822       gtk_widget_destroy (tree_view->priv->search_window);
14823
14824       tree_view->priv->search_window = NULL;
14825     }
14826
14827   if (entry)
14828     {
14829       tree_view->priv->search_entry = g_object_ref (entry);
14830       tree_view->priv->search_custom_entry_set = TRUE;
14831
14832       if (tree_view->priv->search_entry_changed_id == 0)
14833         {
14834           tree_view->priv->search_entry_changed_id =
14835             g_signal_connect (tree_view->priv->search_entry, "changed",
14836                               G_CALLBACK (gtk_tree_view_search_init),
14837                               tree_view);
14838         }
14839       
14840         g_signal_connect (tree_view->priv->search_entry, "key-press-event",
14841                           G_CALLBACK (gtk_tree_view_search_key_press_event),
14842                           tree_view);
14843
14844         gtk_tree_view_search_init (tree_view->priv->search_entry, tree_view);
14845     }
14846   else
14847     {
14848       tree_view->priv->search_entry = NULL;
14849       tree_view->priv->search_custom_entry_set = FALSE;
14850     }
14851 }
14852
14853 /**
14854  * gtk_tree_view_set_search_position_func:
14855  * @tree_view: A #GtkTreeView
14856  * @func: (allow-none): the function to use to position the search dialog, or %NULL
14857  *    to use the default search position function
14858  * @data: (allow-none): user data to pass to @func, or %NULL
14859  * @destroy: (allow-none): Destroy notifier for @data, or %NULL
14860  *
14861  * Sets the function to use when positioning the search dialog.
14862  *
14863  * Since: 2.10
14864  **/
14865 void
14866 gtk_tree_view_set_search_position_func (GtkTreeView                   *tree_view,
14867                                         GtkTreeViewSearchPositionFunc  func,
14868                                         gpointer                       user_data,
14869                                         GDestroyNotify                 destroy)
14870 {
14871   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
14872
14873   if (tree_view->priv->search_position_destroy)
14874     tree_view->priv->search_position_destroy (tree_view->priv->search_position_user_data);
14875
14876   tree_view->priv->search_position_func = func;
14877   tree_view->priv->search_position_user_data = user_data;
14878   tree_view->priv->search_position_destroy = destroy;
14879   if (tree_view->priv->search_position_func == NULL)
14880     tree_view->priv->search_position_func = gtk_tree_view_search_position_func;
14881 }
14882
14883 /**
14884  * gtk_tree_view_get_search_position_func: (skip)
14885  * @tree_view: A #GtkTreeView
14886  *
14887  * Returns the positioning function currently in use.
14888  *
14889  * Return value: the currently used function for positioning the search dialog.
14890  *
14891  * Since: 2.10
14892  */
14893 GtkTreeViewSearchPositionFunc
14894 gtk_tree_view_get_search_position_func (GtkTreeView *tree_view)
14895 {
14896   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
14897
14898   return tree_view->priv->search_position_func;
14899 }
14900
14901
14902 static void
14903 gtk_tree_view_search_dialog_hide (GtkWidget   *search_dialog,
14904                                   GtkTreeView *tree_view,
14905                                   GdkDevice   *device)
14906 {
14907   if (tree_view->priv->disable_popdown)
14908     return;
14909
14910   if (tree_view->priv->search_entry_changed_id)
14911     {
14912       g_signal_handler_disconnect (tree_view->priv->search_entry,
14913                                    tree_view->priv->search_entry_changed_id);
14914       tree_view->priv->search_entry_changed_id = 0;
14915     }
14916   if (tree_view->priv->typeselect_flush_timeout)
14917     {
14918       g_source_remove (tree_view->priv->typeselect_flush_timeout);
14919       tree_view->priv->typeselect_flush_timeout = 0;
14920     }
14921         
14922   if (gtk_widget_get_visible (search_dialog))
14923     {
14924       /* send focus-in event */
14925       send_focus_change (GTK_WIDGET (tree_view->priv->search_entry), device, FALSE);
14926       gtk_widget_hide (search_dialog);
14927       gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
14928       send_focus_change (GTK_WIDGET (tree_view), device, TRUE);
14929     }
14930 }
14931
14932 static void
14933 gtk_tree_view_search_position_func (GtkTreeView *tree_view,
14934                                     GtkWidget   *search_dialog,
14935                                     gpointer     user_data)
14936 {
14937   gint x, y;
14938   gint tree_x, tree_y;
14939   gint tree_width, tree_height;
14940   GdkWindow *tree_window = gtk_widget_get_window (GTK_WIDGET (tree_view));
14941   GdkScreen *screen = gdk_window_get_screen (tree_window);
14942   GtkRequisition requisition;
14943   gint monitor_num;
14944   GdkRectangle monitor;
14945
14946   monitor_num = gdk_screen_get_monitor_at_window (screen, tree_window);
14947   gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
14948
14949   gtk_widget_realize (search_dialog);
14950
14951   gdk_window_get_origin (tree_window, &tree_x, &tree_y);
14952   tree_width = gdk_window_get_width (tree_window);
14953   tree_height = gdk_window_get_height (tree_window);
14954   gtk_widget_get_preferred_size (search_dialog, &requisition, NULL);
14955
14956   if (tree_x + tree_width > gdk_screen_get_width (screen))
14957     x = gdk_screen_get_width (screen) - requisition.width;
14958   else if (tree_x + tree_width - requisition.width < 0)
14959     x = 0;
14960   else
14961     x = tree_x + tree_width - requisition.width;
14962
14963   if (tree_y + tree_height + requisition.height > gdk_screen_get_height (screen))
14964     y = gdk_screen_get_height (screen) - requisition.height;
14965   else if (tree_y + tree_height < 0) /* isn't really possible ... */
14966     y = 0;
14967   else
14968     y = tree_y + tree_height;
14969
14970   gtk_window_move (GTK_WINDOW (search_dialog), x, y);
14971 }
14972
14973 static void
14974 gtk_tree_view_search_disable_popdown (GtkEntry *entry,
14975                                       GtkMenu  *menu,
14976                                       gpointer  data)
14977 {
14978   GtkTreeView *tree_view = (GtkTreeView *)data;
14979
14980   tree_view->priv->disable_popdown = 1;
14981   g_signal_connect (menu, "hide",
14982                     G_CALLBACK (gtk_tree_view_search_enable_popdown), data);
14983 }
14984
14985 /* Because we're visible but offscreen, we just set a flag in the preedit
14986  * callback.
14987  */
14988 static void
14989 gtk_tree_view_search_preedit_changed (GtkIMContext *im_context,
14990                                       GtkTreeView  *tree_view)
14991 {
14992   tree_view->priv->imcontext_changed = 1;
14993   if (tree_view->priv->typeselect_flush_timeout)
14994     {
14995       g_source_remove (tree_view->priv->typeselect_flush_timeout);
14996       tree_view->priv->typeselect_flush_timeout =
14997         gdk_threads_add_timeout (GTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT,
14998                        (GSourceFunc) gtk_tree_view_search_entry_flush_timeout,
14999                        tree_view);
15000     }
15001
15002 }
15003
15004 static void
15005 gtk_tree_view_search_activate (GtkEntry    *entry,
15006                                GtkTreeView *tree_view)
15007 {
15008   GtkTreePath *path;
15009   GtkRBNode *node;
15010   GtkRBTree *tree;
15011
15012   gtk_tree_view_search_dialog_hide (tree_view->priv->search_window,
15013                                     tree_view,
15014                                     gtk_get_current_event_device ());
15015
15016   /* If we have a row selected and it's the cursor row, we activate
15017    * the row XXX */
15018   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
15019     {
15020       path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
15021       
15022       _gtk_tree_view_find_node (tree_view, path, &tree, &node);
15023       
15024       if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
15025         gtk_tree_view_row_activated (tree_view, path, tree_view->priv->focus_column);
15026       
15027       gtk_tree_path_free (path);
15028     }
15029 }
15030
15031 static gboolean
15032 gtk_tree_view_real_search_enable_popdown (gpointer data)
15033 {
15034   GtkTreeView *tree_view = (GtkTreeView *)data;
15035
15036   tree_view->priv->disable_popdown = 0;
15037
15038   return FALSE;
15039 }
15040
15041 static void
15042 gtk_tree_view_search_enable_popdown (GtkWidget *widget,
15043                                      gpointer   data)
15044 {
15045   gdk_threads_add_timeout_full (G_PRIORITY_HIGH, 200, gtk_tree_view_real_search_enable_popdown, g_object_ref (data), g_object_unref);
15046 }
15047
15048 static gboolean
15049 gtk_tree_view_search_delete_event (GtkWidget *widget,
15050                                    GdkEventAny *event,
15051                                    GtkTreeView *tree_view)
15052 {
15053   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
15054
15055   gtk_tree_view_search_dialog_hide (widget, tree_view, NULL);
15056
15057   return TRUE;
15058 }
15059
15060 static gboolean
15061 gtk_tree_view_search_button_press_event (GtkWidget *widget,
15062                                          GdkEventButton *event,
15063                                          GtkTreeView *tree_view)
15064 {
15065   GdkDevice *keyb_device;
15066
15067   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
15068
15069   keyb_device = gdk_device_get_associated_device (event->device);
15070   gtk_tree_view_search_dialog_hide (widget, tree_view, keyb_device);
15071
15072   if (event->window == tree_view->priv->bin_window)
15073     gtk_tree_view_button_press (GTK_WIDGET (tree_view), event);
15074
15075   return TRUE;
15076 }
15077
15078 static gboolean
15079 gtk_tree_view_search_scroll_event (GtkWidget *widget,
15080                                    GdkEventScroll *event,
15081                                    GtkTreeView *tree_view)
15082 {
15083   gboolean retval = FALSE;
15084
15085   if (event->direction == GDK_SCROLL_UP)
15086     {
15087       gtk_tree_view_search_move (widget, tree_view, TRUE);
15088       retval = TRUE;
15089     }
15090   else if (event->direction == GDK_SCROLL_DOWN)
15091     {
15092       gtk_tree_view_search_move (widget, tree_view, FALSE);
15093       retval = TRUE;
15094     }
15095
15096   /* renew the flush timeout */
15097   if (retval && tree_view->priv->typeselect_flush_timeout
15098       && !tree_view->priv->search_custom_entry_set)
15099     {
15100       g_source_remove (tree_view->priv->typeselect_flush_timeout);
15101       tree_view->priv->typeselect_flush_timeout =
15102         gdk_threads_add_timeout (GTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT,
15103                        (GSourceFunc) gtk_tree_view_search_entry_flush_timeout,
15104                        tree_view);
15105     }
15106
15107   return retval;
15108 }
15109
15110 static gboolean
15111 gtk_tree_view_search_key_press_event (GtkWidget *widget,
15112                                       GdkEventKey *event,
15113                                       GtkTreeView *tree_view)
15114 {
15115   gboolean retval = FALSE;
15116
15117   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
15118   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
15119
15120   /* close window and cancel the search */
15121   if (!tree_view->priv->search_custom_entry_set
15122       && (event->keyval == GDK_KEY_Escape ||
15123           event->keyval == GDK_KEY_Tab ||
15124             event->keyval == GDK_KEY_KP_Tab ||
15125             event->keyval == GDK_KEY_ISO_Left_Tab))
15126     {
15127       gtk_tree_view_search_dialog_hide (widget, tree_view,
15128                                         gdk_event_get_device ((GdkEvent *) event));
15129       return TRUE;
15130     }
15131
15132   /* select previous matching iter */
15133   if (event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_KP_Up)
15134     {
15135       if (!gtk_tree_view_search_move (widget, tree_view, TRUE))
15136         gtk_widget_error_bell (widget);
15137
15138       retval = TRUE;
15139     }
15140
15141   if (((event->state & (GTK_DEFAULT_ACCEL_MOD_MASK | GDK_SHIFT_MASK)) == (GTK_DEFAULT_ACCEL_MOD_MASK | GDK_SHIFT_MASK))
15142       && (event->keyval == GDK_KEY_g || event->keyval == GDK_KEY_G))
15143     {
15144       if (!gtk_tree_view_search_move (widget, tree_view, TRUE))
15145         gtk_widget_error_bell (widget);
15146
15147       retval = TRUE;
15148     }
15149
15150   /* select next matching iter */
15151   if (event->keyval == GDK_KEY_Down || event->keyval == GDK_KEY_KP_Down)
15152     {
15153       if (!gtk_tree_view_search_move (widget, tree_view, FALSE))
15154         gtk_widget_error_bell (widget);
15155
15156       retval = TRUE;
15157     }
15158
15159   if (((event->state & (GTK_DEFAULT_ACCEL_MOD_MASK | GDK_SHIFT_MASK)) == GTK_DEFAULT_ACCEL_MOD_MASK)
15160       && (event->keyval == GDK_KEY_g || event->keyval == GDK_KEY_G))
15161     {
15162       if (!gtk_tree_view_search_move (widget, tree_view, FALSE))
15163         gtk_widget_error_bell (widget);
15164
15165       retval = TRUE;
15166     }
15167
15168   /* renew the flush timeout */
15169   if (retval && tree_view->priv->typeselect_flush_timeout
15170       && !tree_view->priv->search_custom_entry_set)
15171     {
15172       g_source_remove (tree_view->priv->typeselect_flush_timeout);
15173       tree_view->priv->typeselect_flush_timeout =
15174         gdk_threads_add_timeout (GTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT,
15175                        (GSourceFunc) gtk_tree_view_search_entry_flush_timeout,
15176                        tree_view);
15177     }
15178
15179   return retval;
15180 }
15181
15182 /*  this function returns FALSE if there is a search string but
15183  *  nothing was found, and TRUE otherwise.
15184  */
15185 static gboolean
15186 gtk_tree_view_search_move (GtkWidget   *window,
15187                            GtkTreeView *tree_view,
15188                            gboolean     up)
15189 {
15190   gboolean ret;
15191   gint len;
15192   gint count = 0;
15193   const gchar *text;
15194   GtkTreeIter iter;
15195   GtkTreeModel *model;
15196   GtkTreeSelection *selection;
15197
15198   text = gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry));
15199
15200   g_return_val_if_fail (text != NULL, FALSE);
15201
15202   len = strlen (text);
15203
15204   if (up && tree_view->priv->selected_iter == 1)
15205     return strlen (text) < 1;
15206
15207   len = strlen (text);
15208
15209   if (len < 1)
15210     return TRUE;
15211
15212   model = gtk_tree_view_get_model (tree_view);
15213   selection = gtk_tree_view_get_selection (tree_view);
15214
15215   /* search */
15216   gtk_tree_selection_unselect_all (selection);
15217   if (!gtk_tree_model_get_iter_first (model, &iter))
15218     return TRUE;
15219
15220   ret = gtk_tree_view_search_iter (model, selection, &iter, text,
15221                                    &count, up?((tree_view->priv->selected_iter) - 1):((tree_view->priv->selected_iter + 1)));
15222
15223   if (ret)
15224     {
15225       /* found */
15226       tree_view->priv->selected_iter += up?(-1):(1);
15227       return TRUE;
15228     }
15229   else
15230     {
15231       /* return to old iter */
15232       count = 0;
15233       gtk_tree_model_get_iter_first (model, &iter);
15234       gtk_tree_view_search_iter (model, selection,
15235                                  &iter, text,
15236                                  &count, tree_view->priv->selected_iter);
15237       return FALSE;
15238     }
15239 }
15240
15241 static gboolean
15242 gtk_tree_view_search_equal_func (GtkTreeModel *model,
15243                                  gint          column,
15244                                  const gchar  *key,
15245                                  GtkTreeIter  *iter,
15246                                  gpointer      search_data)
15247 {
15248   gboolean retval = TRUE;
15249   const gchar *str;
15250   gchar *normalized_string;
15251   gchar *normalized_key;
15252   gchar *case_normalized_string = NULL;
15253   gchar *case_normalized_key = NULL;
15254   GValue value = {0,};
15255   GValue transformed = {0,};
15256
15257   gtk_tree_model_get_value (model, iter, column, &value);
15258
15259   g_value_init (&transformed, G_TYPE_STRING);
15260
15261   if (!g_value_transform (&value, &transformed))
15262     {
15263       g_value_unset (&value);
15264       return TRUE;
15265     }
15266
15267   g_value_unset (&value);
15268
15269   str = g_value_get_string (&transformed);
15270   if (!str)
15271     {
15272       g_value_unset (&transformed);
15273       return TRUE;
15274     }
15275
15276   normalized_string = g_utf8_normalize (str, -1, G_NORMALIZE_ALL);
15277   normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
15278
15279   if (normalized_string && normalized_key)
15280     {
15281       case_normalized_string = g_utf8_casefold (normalized_string, -1);
15282       case_normalized_key = g_utf8_casefold (normalized_key, -1);
15283
15284       if (strncmp (case_normalized_key, case_normalized_string, strlen (case_normalized_key)) == 0)
15285         retval = FALSE;
15286     }
15287
15288   g_value_unset (&transformed);
15289   g_free (normalized_key);
15290   g_free (normalized_string);
15291   g_free (case_normalized_key);
15292   g_free (case_normalized_string);
15293
15294   return retval;
15295 }
15296
15297 static gboolean
15298 gtk_tree_view_search_iter (GtkTreeModel     *model,
15299                            GtkTreeSelection *selection,
15300                            GtkTreeIter      *iter,
15301                            const gchar      *text,
15302                            gint             *count,
15303                            gint              n)
15304 {
15305   GtkRBTree *tree = NULL;
15306   GtkRBNode *node = NULL;
15307   GtkTreePath *path;
15308
15309   GtkTreeView *tree_view = gtk_tree_selection_get_tree_view (selection);
15310
15311   path = gtk_tree_model_get_path (model, iter);
15312   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
15313
15314   do
15315     {
15316       if (! tree_view->priv->search_equal_func (model, tree_view->priv->search_column, text, iter, tree_view->priv->search_user_data))
15317         {
15318           (*count)++;
15319           if (*count == n)
15320             {
15321               gtk_tree_view_scroll_to_cell (tree_view, path, NULL,
15322                                             TRUE, 0.5, 0.0);
15323               gtk_tree_selection_select_iter (selection, iter);
15324               gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
15325
15326               if (path)
15327                 gtk_tree_path_free (path);
15328
15329               return TRUE;
15330             }
15331         }
15332
15333       if (node->children)
15334         {
15335           gboolean has_child;
15336           GtkTreeIter tmp;
15337
15338           tree = node->children;
15339           node = tree->root;
15340
15341           while (node->left != tree->nil)
15342             node = node->left;
15343
15344           tmp = *iter;
15345           has_child = gtk_tree_model_iter_children (model, iter, &tmp);
15346           gtk_tree_path_down (path);
15347
15348           /* sanity check */
15349           TREE_VIEW_INTERNAL_ASSERT (has_child, FALSE);
15350         }
15351       else
15352         {
15353           gboolean done = FALSE;
15354
15355           do
15356             {
15357               node = _gtk_rbtree_next (tree, node);
15358
15359               if (node)
15360                 {
15361                   gboolean has_next;
15362
15363                   has_next = gtk_tree_model_iter_next (model, iter);
15364
15365                   done = TRUE;
15366                   gtk_tree_path_next (path);
15367
15368                   /* sanity check */
15369                   TREE_VIEW_INTERNAL_ASSERT (has_next, FALSE);
15370                 }
15371               else
15372                 {
15373                   gboolean has_parent;
15374                   GtkTreeIter tmp_iter = *iter;
15375
15376                   node = tree->parent_node;
15377                   tree = tree->parent_tree;
15378
15379                   if (!tree)
15380                     {
15381                       if (path)
15382                         gtk_tree_path_free (path);
15383
15384                       /* we've run out of tree, done with this func */
15385                       return FALSE;
15386                     }
15387
15388                   has_parent = gtk_tree_model_iter_parent (model,
15389                                                            iter,
15390                                                            &tmp_iter);
15391                   gtk_tree_path_up (path);
15392
15393                   /* sanity check */
15394                   TREE_VIEW_INTERNAL_ASSERT (has_parent, FALSE);
15395                 }
15396             }
15397           while (!done);
15398         }
15399     }
15400   while (1);
15401
15402   return FALSE;
15403 }
15404
15405 static void
15406 gtk_tree_view_search_init (GtkWidget   *entry,
15407                            GtkTreeView *tree_view)
15408 {
15409   gint ret;
15410   gint count = 0;
15411   const gchar *text;
15412   GtkTreeIter iter;
15413   GtkTreeModel *model;
15414   GtkTreeSelection *selection;
15415
15416   g_return_if_fail (GTK_IS_ENTRY (entry));
15417   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
15418
15419   text = gtk_entry_get_text (GTK_ENTRY (entry));
15420
15421   model = gtk_tree_view_get_model (tree_view);
15422   selection = gtk_tree_view_get_selection (tree_view);
15423
15424   /* search */
15425   gtk_tree_selection_unselect_all (selection);
15426   if (tree_view->priv->typeselect_flush_timeout
15427       && !tree_view->priv->search_custom_entry_set)
15428     {
15429       g_source_remove (tree_view->priv->typeselect_flush_timeout);
15430       tree_view->priv->typeselect_flush_timeout =
15431         gdk_threads_add_timeout (GTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT,
15432                        (GSourceFunc) gtk_tree_view_search_entry_flush_timeout,
15433                        tree_view);
15434     }
15435
15436   if (*text == '\0')
15437     return;
15438
15439   if (!gtk_tree_model_get_iter_first (model, &iter))
15440     return;
15441
15442   ret = gtk_tree_view_search_iter (model, selection,
15443                                    &iter, text,
15444                                    &count, 1);
15445
15446   if (ret)
15447     tree_view->priv->selected_iter = 1;
15448 }
15449
15450 void
15451 _gtk_tree_view_remove_editable (GtkTreeView       *tree_view,
15452                                 GtkTreeViewColumn *column,
15453                                 GtkCellEditable   *cell_editable)
15454 {
15455   if (tree_view->priv->edited_column == NULL)
15456     return;
15457
15458   g_return_if_fail (column == tree_view->priv->edited_column);
15459
15460   tree_view->priv->edited_column = NULL;
15461
15462   if (gtk_widget_has_focus (GTK_WIDGET (cell_editable)))
15463     gtk_widget_grab_focus (GTK_WIDGET (tree_view));
15464
15465   gtk_container_remove (GTK_CONTAINER (tree_view),
15466                         GTK_WIDGET (cell_editable));
15467
15468   /* FIXME should only redraw a single node */
15469   gtk_widget_queue_draw (GTK_WIDGET (tree_view));
15470 }
15471
15472 static gboolean
15473 gtk_tree_view_start_editing (GtkTreeView *tree_view,
15474                              GtkTreePath *cursor_path,
15475                              gboolean     edit_only)
15476 {
15477   GtkTreeIter iter;
15478   GdkRectangle cell_area;
15479   GtkTreeViewColumn *focus_column;
15480   guint flags = 0; /* can be 0, as the flags are primarily for rendering */
15481   gint retval = FALSE;
15482   GtkRBTree *cursor_tree;
15483   GtkRBNode *cursor_node;
15484
15485   g_assert (tree_view->priv->focus_column);
15486   focus_column = tree_view->priv->focus_column;
15487
15488   if (!gtk_widget_get_realized (GTK_WIDGET (tree_view)))
15489     return FALSE;
15490
15491   if (_gtk_tree_view_find_node (tree_view, cursor_path, &cursor_tree, &cursor_node) ||
15492       cursor_node == NULL)
15493     return FALSE;
15494
15495   gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path);
15496
15497   validate_row (tree_view, cursor_tree, cursor_node, &iter, cursor_path);
15498
15499   gtk_tree_view_column_cell_set_cell_data (focus_column,
15500                                            tree_view->priv->model,
15501                                            &iter,
15502                                            GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT),
15503                                            cursor_node->children ? TRUE : FALSE);
15504   gtk_tree_view_get_cell_area (tree_view,
15505                                cursor_path,
15506                                focus_column,
15507                                &cell_area);
15508
15509   if (gtk_cell_area_activate (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (focus_column)),
15510                               _gtk_tree_view_column_get_context (focus_column),
15511                               GTK_WIDGET (tree_view),
15512                               &cell_area,
15513                               flags, edit_only))
15514     retval = TRUE;
15515
15516   return retval;
15517 }
15518
15519 void
15520 _gtk_tree_view_add_editable (GtkTreeView       *tree_view,
15521                              GtkTreeViewColumn *column,
15522                              GtkTreePath       *path,
15523                              GtkCellEditable   *cell_editable,
15524                              GdkRectangle      *cell_area)
15525 {
15526   gint pre_val = gtk_adjustment_get_value (tree_view->priv->vadjustment);
15527   GtkRequisition requisition;
15528
15529   tree_view->priv->edited_column = column;
15530
15531   gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
15532   cell_area->y += pre_val - (int)gtk_adjustment_get_value (tree_view->priv->vadjustment);
15533
15534   gtk_widget_get_preferred_size (GTK_WIDGET (cell_editable),
15535                                  &requisition, NULL);
15536
15537   tree_view->priv->draw_keyfocus = TRUE;
15538
15539   if (requisition.height < cell_area->height)
15540     {
15541       gint diff = cell_area->height - requisition.height;
15542       gtk_tree_view_put (tree_view,
15543                          GTK_WIDGET (cell_editable),
15544                          cell_area->x, cell_area->y + diff/2,
15545                          cell_area->width, requisition.height);
15546     }
15547   else
15548     {
15549       gtk_tree_view_put (tree_view,
15550                          GTK_WIDGET (cell_editable),
15551                          cell_area->x, cell_area->y,
15552                          cell_area->width, cell_area->height);
15553     }
15554 }
15555
15556 static void
15557 gtk_tree_view_stop_editing (GtkTreeView *tree_view,
15558                             gboolean     cancel_editing)
15559 {
15560   GtkTreeViewColumn *column;
15561
15562   if (tree_view->priv->edited_column == NULL)
15563     return;
15564
15565   /*
15566    * This is very evil. We need to do this, because
15567    * gtk_cell_editable_editing_done may trigger gtk_tree_view_row_changed
15568    * later on. If gtk_tree_view_row_changed notices
15569    * tree_view->priv->edited_column != NULL, it'll call
15570    * gtk_tree_view_stop_editing again. Bad things will happen then.
15571    *
15572    * Please read that again if you intend to modify anything here.
15573    */
15574
15575   column = tree_view->priv->edited_column;
15576   gtk_cell_area_stop_editing (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (column)), cancel_editing);
15577   tree_view->priv->edited_column = NULL;
15578 }
15579
15580
15581 /**
15582  * gtk_tree_view_set_hover_selection:
15583  * @tree_view: a #GtkTreeView
15584  * @hover: %TRUE to enable hover selection mode
15585  *
15586  * Enables of disables the hover selection mode of @tree_view.
15587  * Hover selection makes the selected row follow the pointer.
15588  * Currently, this works only for the selection modes 
15589  * %GTK_SELECTION_SINGLE and %GTK_SELECTION_BROWSE.
15590  * 
15591  * Since: 2.6
15592  **/
15593 void     
15594 gtk_tree_view_set_hover_selection (GtkTreeView *tree_view,
15595                                    gboolean     hover)
15596 {
15597   hover = hover != FALSE;
15598
15599   if (hover != tree_view->priv->hover_selection)
15600     {
15601       tree_view->priv->hover_selection = hover;
15602
15603       g_object_notify (G_OBJECT (tree_view), "hover-selection");
15604     }
15605 }
15606
15607 /**
15608  * gtk_tree_view_get_hover_selection:
15609  * @tree_view: a #GtkTreeView
15610  * 
15611  * Returns whether hover selection mode is turned on for @tree_view.
15612  * 
15613  * Return value: %TRUE if @tree_view is in hover selection mode
15614  *
15615  * Since: 2.6 
15616  **/
15617 gboolean 
15618 gtk_tree_view_get_hover_selection (GtkTreeView *tree_view)
15619 {
15620   return tree_view->priv->hover_selection;
15621 }
15622
15623 /**
15624  * gtk_tree_view_set_hover_expand:
15625  * @tree_view: a #GtkTreeView
15626  * @expand: %TRUE to enable hover selection mode
15627  *
15628  * Enables of disables the hover expansion mode of @tree_view.
15629  * Hover expansion makes rows expand or collapse if the pointer 
15630  * moves over them.
15631  * 
15632  * Since: 2.6
15633  **/
15634 void     
15635 gtk_tree_view_set_hover_expand (GtkTreeView *tree_view,
15636                                 gboolean     expand)
15637 {
15638   expand = expand != FALSE;
15639
15640   if (expand != tree_view->priv->hover_expand)
15641     {
15642       tree_view->priv->hover_expand = expand;
15643
15644       g_object_notify (G_OBJECT (tree_view), "hover-expand");
15645     }
15646 }
15647
15648 /**
15649  * gtk_tree_view_get_hover_expand:
15650  * @tree_view: a #GtkTreeView
15651  * 
15652  * Returns whether hover expansion mode is turned on for @tree_view.
15653  * 
15654  * Return value: %TRUE if @tree_view is in hover expansion mode
15655  *
15656  * Since: 2.6 
15657  **/
15658 gboolean 
15659 gtk_tree_view_get_hover_expand (GtkTreeView *tree_view)
15660 {
15661   return tree_view->priv->hover_expand;
15662 }
15663
15664 /**
15665  * gtk_tree_view_set_rubber_banding:
15666  * @tree_view: a #GtkTreeView
15667  * @enable: %TRUE to enable rubber banding
15668  *
15669  * Enables or disables rubber banding in @tree_view.  If the selection mode
15670  * is #GTK_SELECTION_MULTIPLE, rubber banding will allow the user to select
15671  * multiple rows by dragging the mouse.
15672  * 
15673  * Since: 2.10
15674  **/
15675 void
15676 gtk_tree_view_set_rubber_banding (GtkTreeView *tree_view,
15677                                   gboolean     enable)
15678 {
15679   enable = enable != FALSE;
15680
15681   if (enable != tree_view->priv->rubber_banding_enable)
15682     {
15683       tree_view->priv->rubber_banding_enable = enable;
15684
15685       g_object_notify (G_OBJECT (tree_view), "rubber-banding");
15686     }
15687 }
15688
15689 /**
15690  * gtk_tree_view_get_rubber_banding:
15691  * @tree_view: a #GtkTreeView
15692  * 
15693  * Returns whether rubber banding is turned on for @tree_view.  If the
15694  * selection mode is #GTK_SELECTION_MULTIPLE, rubber banding will allow the
15695  * user to select multiple rows by dragging the mouse.
15696  * 
15697  * Return value: %TRUE if rubber banding in @tree_view is enabled.
15698  *
15699  * Since: 2.10
15700  **/
15701 gboolean
15702 gtk_tree_view_get_rubber_banding (GtkTreeView *tree_view)
15703 {
15704   return tree_view->priv->rubber_banding_enable;
15705 }
15706
15707 /**
15708  * gtk_tree_view_is_rubber_banding_active:
15709  * @tree_view: a #GtkTreeView
15710  * 
15711  * Returns whether a rubber banding operation is currently being done
15712  * in @tree_view.
15713  *
15714  * Return value: %TRUE if a rubber banding operation is currently being
15715  * done in @tree_view.
15716  *
15717  * Since: 2.12
15718  **/
15719 gboolean
15720 gtk_tree_view_is_rubber_banding_active (GtkTreeView *tree_view)
15721 {
15722   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
15723
15724   if (tree_view->priv->rubber_banding_enable
15725       && tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
15726     return TRUE;
15727
15728   return FALSE;
15729 }
15730
15731 /**
15732  * gtk_tree_view_get_row_separator_func: (skip)
15733  * @tree_view: a #GtkTreeView
15734  * 
15735  * Returns the current row separator function.
15736  * 
15737  * Return value: the current row separator function.
15738  *
15739  * Since: 2.6
15740  **/
15741 GtkTreeViewRowSeparatorFunc 
15742 gtk_tree_view_get_row_separator_func (GtkTreeView *tree_view)
15743 {
15744   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
15745
15746   return tree_view->priv->row_separator_func;
15747 }
15748
15749 /**
15750  * gtk_tree_view_set_row_separator_func:
15751  * @tree_view: a #GtkTreeView
15752  * @func: (allow-none): a #GtkTreeViewRowSeparatorFunc
15753  * @data: (allow-none): user data to pass to @func, or %NULL
15754  * @destroy: (allow-none): destroy notifier for @data, or %NULL
15755  * 
15756  * Sets the row separator function, which is used to determine
15757  * whether a row should be drawn as a separator. If the row separator
15758  * function is %NULL, no separators are drawn. This is the default value.
15759  *
15760  * Since: 2.6
15761  **/
15762 void
15763 gtk_tree_view_set_row_separator_func (GtkTreeView                 *tree_view,
15764                                       GtkTreeViewRowSeparatorFunc  func,
15765                                       gpointer                     data,
15766                                       GDestroyNotify               destroy)
15767 {
15768   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
15769
15770   if (tree_view->priv->row_separator_destroy)
15771     tree_view->priv->row_separator_destroy (tree_view->priv->row_separator_data);
15772
15773   tree_view->priv->row_separator_func = func;
15774   tree_view->priv->row_separator_data = data;
15775   tree_view->priv->row_separator_destroy = destroy;
15776
15777   /* Have the tree recalculate heights */
15778   _gtk_rbtree_mark_invalid (tree_view->priv->tree);
15779   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
15780 }
15781
15782   
15783 static void
15784 gtk_tree_view_grab_notify (GtkWidget *widget,
15785                            gboolean   was_grabbed)
15786 {
15787   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
15788
15789   tree_view->priv->in_grab = !was_grabbed;
15790
15791   if (!was_grabbed)
15792     {
15793       tree_view->priv->pressed_button = -1;
15794
15795       if (tree_view->priv->rubber_band_status)
15796         gtk_tree_view_stop_rubber_band (tree_view);
15797     }
15798 }
15799
15800 static void
15801 gtk_tree_view_state_flags_changed (GtkWidget     *widget,
15802                                    GtkStateFlags  previous_state)
15803 {
15804   if (gtk_widget_get_realized (widget))
15805     {
15806       GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
15807       GtkStyleContext *context;
15808
15809       context = gtk_widget_get_style_context (widget);
15810       gtk_style_context_set_background (context, tree_view->priv->bin_window);
15811     }
15812
15813   gtk_widget_queue_draw (widget);
15814 }
15815
15816 /**
15817  * gtk_tree_view_get_grid_lines:
15818  * @tree_view: a #GtkTreeView
15819  *
15820  * Returns which grid lines are enabled in @tree_view.
15821  *
15822  * Return value: a #GtkTreeViewGridLines value indicating which grid lines
15823  * are enabled.
15824  *
15825  * Since: 2.10
15826  */
15827 GtkTreeViewGridLines
15828 gtk_tree_view_get_grid_lines (GtkTreeView *tree_view)
15829 {
15830   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), 0);
15831
15832   return tree_view->priv->grid_lines;
15833 }
15834
15835 /**
15836  * gtk_tree_view_set_grid_lines:
15837  * @tree_view: a #GtkTreeView
15838  * @grid_lines: a #GtkTreeViewGridLines value indicating which grid lines to
15839  * enable.
15840  *
15841  * Sets which grid lines to draw in @tree_view.
15842  *
15843  * Since: 2.10
15844  */
15845 void
15846 gtk_tree_view_set_grid_lines (GtkTreeView           *tree_view,
15847                               GtkTreeViewGridLines   grid_lines)
15848 {
15849   GtkTreeViewPrivate *priv;
15850   GtkWidget *widget;
15851   GtkTreeViewGridLines old_grid_lines;
15852
15853   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
15854
15855   priv = tree_view->priv;
15856   widget = GTK_WIDGET (tree_view);
15857
15858   old_grid_lines = priv->grid_lines;
15859   priv->grid_lines = grid_lines;
15860   
15861   if (gtk_widget_get_realized (widget))
15862     {
15863       if (grid_lines == GTK_TREE_VIEW_GRID_LINES_NONE &&
15864           priv->grid_line_width)
15865         {
15866           priv->grid_line_width = 0;
15867         }
15868       
15869       if (grid_lines != GTK_TREE_VIEW_GRID_LINES_NONE && 
15870           !priv->grid_line_width)
15871         {
15872           gint8 *dash_list;
15873
15874           gtk_widget_style_get (widget,
15875                                 "grid-line-width", &priv->grid_line_width,
15876                                 "grid-line-pattern", (gchar *)&dash_list,
15877                                 NULL);
15878       
15879           if (dash_list)
15880             {
15881               priv->grid_line_dashes[0] = dash_list[0];
15882               if (dash_list[0])
15883                 priv->grid_line_dashes[1] = dash_list[1];
15884               
15885               g_free (dash_list);
15886             }
15887           else
15888             {
15889               priv->grid_line_dashes[0] = 1;
15890               priv->grid_line_dashes[1] = 1;
15891             }
15892         }      
15893     }
15894
15895   if (old_grid_lines != grid_lines)
15896     {
15897       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
15898       
15899       g_object_notify (G_OBJECT (tree_view), "enable-grid-lines");
15900     }
15901 }
15902
15903 /**
15904  * gtk_tree_view_get_enable_tree_lines:
15905  * @tree_view: a #GtkTreeView.
15906  *
15907  * Returns whether or not tree lines are drawn in @tree_view.
15908  *
15909  * Return value: %TRUE if tree lines are drawn in @tree_view, %FALSE
15910  * otherwise.
15911  *
15912  * Since: 2.10
15913  */
15914 gboolean
15915 gtk_tree_view_get_enable_tree_lines (GtkTreeView *tree_view)
15916 {
15917   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
15918
15919   return tree_view->priv->tree_lines_enabled;
15920 }
15921
15922 /**
15923  * gtk_tree_view_set_enable_tree_lines:
15924  * @tree_view: a #GtkTreeView
15925  * @enabled: %TRUE to enable tree line drawing, %FALSE otherwise.
15926  *
15927  * Sets whether to draw lines interconnecting the expanders in @tree_view.
15928  * This does not have any visible effects for lists.
15929  *
15930  * Since: 2.10
15931  */
15932 void
15933 gtk_tree_view_set_enable_tree_lines (GtkTreeView *tree_view,
15934                                      gboolean     enabled)
15935 {
15936   GtkTreeViewPrivate *priv;
15937   GtkWidget *widget;
15938   gboolean was_enabled;
15939
15940   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
15941
15942   enabled = enabled != FALSE;
15943
15944   priv = tree_view->priv;
15945   widget = GTK_WIDGET (tree_view);
15946
15947   was_enabled = priv->tree_lines_enabled;
15948
15949   priv->tree_lines_enabled = enabled;
15950
15951   if (gtk_widget_get_realized (widget))
15952     {
15953       if (!enabled && priv->tree_line_width)
15954         {
15955           priv->tree_line_width = 0;
15956         }
15957       
15958       if (enabled && !priv->tree_line_width)
15959         {
15960           gint8 *dash_list;
15961           gtk_widget_style_get (widget,
15962                                 "tree-line-width", &priv->tree_line_width,
15963                                 "tree-line-pattern", (gchar *)&dash_list,
15964                                 NULL);
15965           
15966           if (dash_list)
15967             {
15968               priv->tree_line_dashes[0] = dash_list[0];
15969               if (dash_list[0])
15970                 priv->tree_line_dashes[1] = dash_list[1];
15971               
15972               g_free (dash_list);
15973             }
15974           else
15975             {
15976               priv->tree_line_dashes[0] = 1;
15977               priv->tree_line_dashes[1] = 1;
15978             }
15979         }
15980     }
15981
15982   if (was_enabled != enabled)
15983     {
15984       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
15985
15986       g_object_notify (G_OBJECT (tree_view), "enable-tree-lines");
15987     }
15988 }
15989
15990
15991 /**
15992  * gtk_tree_view_set_show_expanders:
15993  * @tree_view: a #GtkTreeView
15994  * @enabled: %TRUE to enable expander drawing, %FALSE otherwise.
15995  *
15996  * Sets whether to draw and enable expanders and indent child rows in
15997  * @tree_view.  When disabled there will be no expanders visible in trees
15998  * and there will be no way to expand and collapse rows by default.  Also
15999  * note that hiding the expanders will disable the default indentation.  You
16000  * can set a custom indentation in this case using
16001  * gtk_tree_view_set_level_indentation().
16002  * This does not have any visible effects for lists.
16003  *
16004  * Since: 2.12
16005  */
16006 void
16007 gtk_tree_view_set_show_expanders (GtkTreeView *tree_view,
16008                                   gboolean     enabled)
16009 {
16010   gboolean was_enabled;
16011
16012   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
16013
16014   enabled = enabled != FALSE;
16015   was_enabled = tree_view->priv->show_expanders;
16016
16017   tree_view->priv->show_expanders = enabled == TRUE;
16018
16019   if (enabled != was_enabled)
16020     gtk_widget_queue_draw (GTK_WIDGET (tree_view));
16021 }
16022
16023 /**
16024  * gtk_tree_view_get_show_expanders:
16025  * @tree_view: a #GtkTreeView.
16026  *
16027  * Returns whether or not expanders are drawn in @tree_view.
16028  *
16029  * Return value: %TRUE if expanders are drawn in @tree_view, %FALSE
16030  * otherwise.
16031  *
16032  * Since: 2.12
16033  */
16034 gboolean
16035 gtk_tree_view_get_show_expanders (GtkTreeView *tree_view)
16036 {
16037   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
16038
16039   return tree_view->priv->show_expanders;
16040 }
16041
16042 /**
16043  * gtk_tree_view_set_level_indentation:
16044  * @tree_view: a #GtkTreeView
16045  * @indentation: the amount, in pixels, of extra indentation in @tree_view.
16046  *
16047  * Sets the amount of extra indentation for child levels to use in @tree_view
16048  * in addition to the default indentation.  The value should be specified in
16049  * pixels, a value of 0 disables this feature and in this case only the default
16050  * indentation will be used.
16051  * This does not have any visible effects for lists.
16052  *
16053  * Since: 2.12
16054  */
16055 void
16056 gtk_tree_view_set_level_indentation (GtkTreeView *tree_view,
16057                                      gint         indentation)
16058 {
16059   tree_view->priv->level_indentation = indentation;
16060
16061   gtk_widget_queue_draw (GTK_WIDGET (tree_view));
16062 }
16063
16064 /**
16065  * gtk_tree_view_get_level_indentation:
16066  * @tree_view: a #GtkTreeView.
16067  *
16068  * Returns the amount, in pixels, of extra indentation for child levels
16069  * in @tree_view.
16070  *
16071  * Return value: the amount of extra indentation for child levels in
16072  * @tree_view.  A return value of 0 means that this feature is disabled.
16073  *
16074  * Since: 2.12
16075  */
16076 gint
16077 gtk_tree_view_get_level_indentation (GtkTreeView *tree_view)
16078 {
16079   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), 0);
16080
16081   return tree_view->priv->level_indentation;
16082 }
16083
16084 /**
16085  * gtk_tree_view_set_tooltip_row:
16086  * @tree_view: a #GtkTreeView
16087  * @tooltip: a #GtkTooltip
16088  * @path: a #GtkTreePath
16089  *
16090  * Sets the tip area of @tooltip to be the area covered by the row at @path.
16091  * See also gtk_tree_view_set_tooltip_column() for a simpler alternative.
16092  * See also gtk_tooltip_set_tip_area().
16093  *
16094  * Since: 2.12
16095  */
16096 void
16097 gtk_tree_view_set_tooltip_row (GtkTreeView *tree_view,
16098                                GtkTooltip  *tooltip,
16099                                GtkTreePath *path)
16100 {
16101   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
16102   g_return_if_fail (GTK_IS_TOOLTIP (tooltip));
16103
16104   gtk_tree_view_set_tooltip_cell (tree_view, tooltip, path, NULL, NULL);
16105 }
16106
16107 /**
16108  * gtk_tree_view_set_tooltip_cell:
16109  * @tree_view: a #GtkTreeView
16110  * @tooltip: a #GtkTooltip
16111  * @path: (allow-none): a #GtkTreePath or %NULL
16112  * @column: (allow-none): a #GtkTreeViewColumn or %NULL
16113  * @cell: (allow-none): a #GtkCellRenderer or %NULL
16114  *
16115  * Sets the tip area of @tooltip to the area @path, @column and @cell have
16116  * in common.  For example if @path is %NULL and @column is set, the tip
16117  * area will be set to the full area covered by @column.  See also
16118  * gtk_tooltip_set_tip_area().
16119  *
16120  * Note that if @path is not specified and @cell is set and part of a column
16121  * containing the expander, the tooltip might not show and hide at the correct
16122  * position.  In such cases @path must be set to the current node under the
16123  * mouse cursor for this function to operate correctly.
16124  *
16125  * See also gtk_tree_view_set_tooltip_column() for a simpler alternative.
16126  *
16127  * Since: 2.12
16128  */
16129 void
16130 gtk_tree_view_set_tooltip_cell (GtkTreeView       *tree_view,
16131                                 GtkTooltip        *tooltip,
16132                                 GtkTreePath       *path,
16133                                 GtkTreeViewColumn *column,
16134                                 GtkCellRenderer   *cell)
16135 {
16136   GtkAllocation allocation;
16137   GdkRectangle rect;
16138
16139   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
16140   g_return_if_fail (GTK_IS_TOOLTIP (tooltip));
16141   g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
16142   g_return_if_fail (cell == NULL || GTK_IS_CELL_RENDERER (cell));
16143
16144   /* Determine x values. */
16145   if (column && cell)
16146     {
16147       GdkRectangle tmp;
16148       gint start, width;
16149
16150       /* We always pass in path here, whether it is NULL or not.
16151        * For cells in expander columns path must be specified so that
16152        * we can correctly account for the indentation.  This also means
16153        * that the tooltip is constrained vertically by the "Determine y
16154        * values" code below; this is not a real problem since cells actually
16155        * don't stretch vertically in constrast to columns.
16156        */
16157       gtk_tree_view_get_cell_area (tree_view, path, column, &tmp);
16158       gtk_tree_view_column_cell_get_position (column, cell, &start, &width);
16159
16160       gtk_tree_view_convert_bin_window_to_widget_coords (tree_view,
16161                                                          tmp.x + start, 0,
16162                                                          &rect.x, NULL);
16163       rect.width = width;
16164     }
16165   else if (column)
16166     {
16167       GdkRectangle tmp;
16168
16169       gtk_tree_view_get_background_area (tree_view, NULL, column, &tmp);
16170       gtk_tree_view_convert_bin_window_to_widget_coords (tree_view,
16171                                                          tmp.x, 0,
16172                                                          &rect.x, NULL);
16173       rect.width = tmp.width;
16174     }
16175   else
16176     {
16177       gtk_widget_get_allocation (GTK_WIDGET (tree_view), &allocation);
16178       rect.x = 0;
16179       rect.width = allocation.width;
16180     }
16181
16182   /* Determine y values. */
16183   if (path)
16184     {
16185       GdkRectangle tmp;
16186
16187       gtk_tree_view_get_background_area (tree_view, path, NULL, &tmp);
16188       gtk_tree_view_convert_bin_window_to_widget_coords (tree_view,
16189                                                          0, tmp.y,
16190                                                          NULL, &rect.y);
16191       rect.height = tmp.height;
16192     }
16193   else
16194     {
16195       rect.y = 0;
16196       rect.height = gtk_adjustment_get_page_size (tree_view->priv->vadjustment);
16197     }
16198
16199   gtk_tooltip_set_tip_area (tooltip, &rect);
16200 }
16201
16202 /**
16203  * gtk_tree_view_get_tooltip_context:
16204  * @tree_view: a #GtkTreeView
16205  * @x: (inout): the x coordinate (relative to widget coordinates)
16206  * @y: (inout): the y coordinate (relative to widget coordinates)
16207  * @keyboard_tip: whether this is a keyboard tooltip or not
16208  * @model: (out) (allow-none): a pointer to receive a #GtkTreeModel or %NULL
16209  * @path: (out) (allow-none): a pointer to receive a #GtkTreePath or %NULL
16210  * @iter: (out) (allow-none): a pointer to receive a #GtkTreeIter or %NULL
16211  *
16212  * This function is supposed to be used in a #GtkWidget::query-tooltip
16213  * signal handler for #GtkTreeView.  The @x, @y and @keyboard_tip values
16214  * which are received in the signal handler, should be passed to this
16215  * function without modification.
16216  *
16217  * The return value indicates whether there is a tree view row at the given
16218  * coordinates (%TRUE) or not (%FALSE) for mouse tooltips.  For keyboard
16219  * tooltips the row returned will be the cursor row.  When %TRUE, then any of
16220  * @model, @path and @iter which have been provided will be set to point to
16221  * that row and the corresponding model.  @x and @y will always be converted
16222  * to be relative to @tree_view's bin_window if @keyboard_tooltip is %FALSE.
16223  *
16224  * Return value: whether or not the given tooltip context points to a row.
16225  *
16226  * Since: 2.12
16227  */
16228 gboolean
16229 gtk_tree_view_get_tooltip_context (GtkTreeView   *tree_view,
16230                                    gint          *x,
16231                                    gint          *y,
16232                                    gboolean       keyboard_tip,
16233                                    GtkTreeModel **model,
16234                                    GtkTreePath  **path,
16235                                    GtkTreeIter   *iter)
16236 {
16237   GtkTreePath *tmppath = NULL;
16238
16239   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
16240   g_return_val_if_fail (x != NULL, FALSE);
16241   g_return_val_if_fail (y != NULL, FALSE);
16242
16243   if (keyboard_tip)
16244     {
16245       gtk_tree_view_get_cursor (tree_view, &tmppath, NULL);
16246
16247       if (!tmppath)
16248         return FALSE;
16249     }
16250   else
16251     {
16252       gtk_tree_view_convert_widget_to_bin_window_coords (tree_view, *x, *y,
16253                                                          x, y);
16254
16255       if (!gtk_tree_view_get_path_at_pos (tree_view, *x, *y,
16256                                           &tmppath, NULL, NULL, NULL))
16257         return FALSE;
16258     }
16259
16260   if (model)
16261     *model = gtk_tree_view_get_model (tree_view);
16262
16263   if (iter)
16264     gtk_tree_model_get_iter (gtk_tree_view_get_model (tree_view),
16265                              iter, tmppath);
16266
16267   if (path)
16268     *path = tmppath;
16269   else
16270     gtk_tree_path_free (tmppath);
16271
16272   return TRUE;
16273 }
16274
16275 static gboolean
16276 gtk_tree_view_set_tooltip_query_cb (GtkWidget  *widget,
16277                                     gint        x,
16278                                     gint        y,
16279                                     gboolean    keyboard_tip,
16280                                     GtkTooltip *tooltip,
16281                                     gpointer    data)
16282 {
16283   GValue value = { 0, };
16284   GValue transformed = { 0, };
16285   GtkTreeIter iter;
16286   GtkTreePath *path;
16287   GtkTreeModel *model;
16288   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
16289
16290   if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (widget),
16291                                           &x, &y,
16292                                           keyboard_tip,
16293                                           &model, &path, &iter))
16294     return FALSE;
16295
16296   gtk_tree_model_get_value (model, &iter,
16297                             tree_view->priv->tooltip_column, &value);
16298
16299   g_value_init (&transformed, G_TYPE_STRING);
16300
16301   if (!g_value_transform (&value, &transformed))
16302     {
16303       g_value_unset (&value);
16304       gtk_tree_path_free (path);
16305
16306       return FALSE;
16307     }
16308
16309   g_value_unset (&value);
16310
16311   if (!g_value_get_string (&transformed))
16312     {
16313       g_value_unset (&transformed);
16314       gtk_tree_path_free (path);
16315
16316       return FALSE;
16317     }
16318
16319   gtk_tooltip_set_markup (tooltip, g_value_get_string (&transformed));
16320   gtk_tree_view_set_tooltip_row (tree_view, tooltip, path);
16321
16322   gtk_tree_path_free (path);
16323   g_value_unset (&transformed);
16324
16325   return TRUE;
16326 }
16327
16328 /**
16329  * gtk_tree_view_set_tooltip_column:
16330  * @tree_view: a #GtkTreeView
16331  * @column: an integer, which is a valid column number for @tree_view's model
16332  *
16333  * If you only plan to have simple (text-only) tooltips on full rows, you
16334  * can use this function to have #GtkTreeView handle these automatically
16335  * for you. @column should be set to the column in @tree_view's model
16336  * containing the tooltip texts, or -1 to disable this feature.
16337  *
16338  * When enabled, #GtkWidget::has-tooltip will be set to %TRUE and
16339  * @tree_view will connect a #GtkWidget::query-tooltip signal handler.
16340  *
16341  * Note that the signal handler sets the text with gtk_tooltip_set_markup(),
16342  * so &amp;, &lt;, etc have to be escaped in the text.
16343  *
16344  * Since: 2.12
16345  */
16346 void
16347 gtk_tree_view_set_tooltip_column (GtkTreeView *tree_view,
16348                                   gint         column)
16349 {
16350   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
16351
16352   if (column == tree_view->priv->tooltip_column)
16353     return;
16354
16355   if (column == -1)
16356     {
16357       g_signal_handlers_disconnect_by_func (tree_view,
16358                                             gtk_tree_view_set_tooltip_query_cb,
16359                                             NULL);
16360       gtk_widget_set_has_tooltip (GTK_WIDGET (tree_view), FALSE);
16361     }
16362   else
16363     {
16364       if (tree_view->priv->tooltip_column == -1)
16365         {
16366           g_signal_connect (tree_view, "query-tooltip",
16367                             G_CALLBACK (gtk_tree_view_set_tooltip_query_cb), NULL);
16368           gtk_widget_set_has_tooltip (GTK_WIDGET (tree_view), TRUE);
16369         }
16370     }
16371
16372   tree_view->priv->tooltip_column = column;
16373   g_object_notify (G_OBJECT (tree_view), "tooltip-column");
16374 }
16375
16376 /**
16377  * gtk_tree_view_get_tooltip_column:
16378  * @tree_view: a #GtkTreeView
16379  *
16380  * Returns the column of @tree_view's model which is being used for
16381  * displaying tooltips on @tree_view's rows.
16382  *
16383  * Return value: the index of the tooltip column that is currently being
16384  * used, or -1 if this is disabled.
16385  *
16386  * Since: 2.12
16387  */
16388 gint
16389 gtk_tree_view_get_tooltip_column (GtkTreeView *tree_view)
16390 {
16391   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), 0);
16392
16393   return tree_view->priv->tooltip_column;
16394 }