Merge master into gtk3.
[pspp] / src / ui / gui / pspp-sheet-view.c
index 955b8f42d6eef87c27f193ace313ddfbf23db7c6..ccdbd10e9919b5d61cbc059bd6d4c7284c66e277 100644 (file)
@@ -135,6 +135,8 @@ enum {
   PROP_MODEL,
   PROP_HADJUSTMENT,
   PROP_VADJUSTMENT,
+  PROP_HSCROLL_POLICY,
+  PROP_VSCROLL_POLICY,
   PROP_HEADERS_VISIBLE,
   PROP_HEADERS_CLICKABLE,
   PROP_REORDERABLE,
@@ -171,8 +173,8 @@ static void     pspp_sheet_view_size_request         (GtkWidget        *widget,
                                                    GtkRequisition   *requisition);
 static void     pspp_sheet_view_size_allocate        (GtkWidget        *widget,
                                                    GtkAllocation    *allocation);
-static gboolean pspp_sheet_view_expose               (GtkWidget        *widget,
-                                                   GdkEventExpose   *event);
+static gboolean pspp_sheet_view_draw               (GtkWidget        *widget,
+                                                   cairo_t *cr);
 static gboolean pspp_sheet_view_key_press            (GtkWidget        *widget,
                                                    GdkEventKey      *event);
 static gboolean pspp_sheet_view_key_release          (GtkWidget        *widget,
@@ -295,6 +297,12 @@ static void     pspp_sheet_view_top_row_to_dy (PsppSheetView *tree_view);
 static void     invalidate_empty_focus      (PsppSheetView *tree_view);
 
 /* Internal functions */
+static GtkAdjustment *pspp_sheet_view_do_get_hadjustment (PsppSheetView *);
+static GtkAdjustment *pspp_sheet_view_do_get_vadjustment (PsppSheetView *);
+static void pspp_sheet_view_do_set_hadjustment (PsppSheetView   *tree_view,
+                                              GtkAdjustment *adjustment);
+static void pspp_sheet_view_do_set_vadjustment (PsppSheetView   *tree_view,
+                                              GtkAdjustment *adjustment);
 static void     pspp_sheet_view_add_move_binding               (GtkBindingSet      *binding_set,
                                                              guint               keyval,
                                                              guint               modmask,
@@ -451,7 +459,32 @@ static GtkBindingSet *edit_bindings;
 
 G_DEFINE_TYPE_WITH_CODE (PsppSheetView, pspp_sheet_view, GTK_TYPE_CONTAINER,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
-                                               pspp_sheet_view_buildable_init))
+                                               pspp_sheet_view_buildable_init)
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
+
+static void
+pspp_sheet_view_get_preferred_width (GtkWidget *widget,
+                               gint      *minimal_width,
+                               gint      *natural_width)
+{
+  GtkRequisition requisition;
+
+  pspp_sheet_view_size_request (widget, &requisition);
+
+  *minimal_width = *natural_width = requisition.width;
+}
+
+static void
+pspp_sheet_view_get_preferred_height (GtkWidget *widget,
+                                gint      *minimal_height,
+                                gint      *natural_height)
+{
+  GtkRequisition requisition;
+
+  pspp_sheet_view_size_request (widget, &requisition);
+
+  *minimal_height = *natural_height = requisition.height;
+}
 
 static void
 pspp_sheet_view_class_init (PsppSheetViewClass *class)
@@ -481,14 +514,15 @@ pspp_sheet_view_class_init (PsppSheetViewClass *class)
   widget_class->map = pspp_sheet_view_map;
   widget_class->realize = pspp_sheet_view_realize;
   widget_class->unrealize = pspp_sheet_view_unrealize;
-  widget_class->size_request = pspp_sheet_view_size_request;
+  widget_class->get_preferred_width = pspp_sheet_view_get_preferred_width;
+  widget_class->get_preferred_height = pspp_sheet_view_get_preferred_height;
   widget_class->size_allocate = pspp_sheet_view_size_allocate;
   widget_class->button_press_event = pspp_sheet_view_button_press;
   widget_class->button_release_event = pspp_sheet_view_button_release;
   widget_class->grab_broken_event = pspp_sheet_view_grab_broken;
   /*widget_class->configure_event = pspp_sheet_view_configure;*/
   widget_class->motion_notify_event = pspp_sheet_view_motion;
-  widget_class->expose_event = pspp_sheet_view_expose;
+  widget_class->draw = pspp_sheet_view_draw;
   widget_class->key_press_event = pspp_sheet_view_key_press;
   widget_class->key_release_event = pspp_sheet_view_key_release;
   widget_class->enter_notify_event = pspp_sheet_view_enter_notify;
@@ -531,21 +565,10 @@ pspp_sheet_view_class_init (PsppSheetViewClass *class)
                                                        GTK_TYPE_TREE_MODEL,
                                                        GTK_PARAM_READWRITE));
 
-  g_object_class_install_property (o_class,
-                                   PROP_HADJUSTMENT,
-                                   g_param_spec_object ("hadjustment",
-                                                       P_("Horizontal Adjustment"),
-                                                        P_("Horizontal Adjustment for the widget"),
-                                                        GTK_TYPE_ADJUSTMENT,
-                                                        GTK_PARAM_READWRITE));
-
-  g_object_class_install_property (o_class,
-                                   PROP_VADJUSTMENT,
-                                   g_param_spec_object ("vadjustment",
-                                                       P_("Vertical Adjustment"),
-                                                        P_("Vertical Adjustment for the widget"),
-                                                        GTK_TYPE_ADJUSTMENT,
-                                                        GTK_PARAM_READWRITE));
+  g_object_class_override_property (o_class, PROP_HADJUSTMENT,    "hadjustment");
+  g_object_class_override_property (o_class, PROP_VADJUSTMENT,    "vadjustment");
+  g_object_class_override_property (o_class, PROP_HSCROLL_POLICY, "hscroll-policy");
+  g_object_class_override_property (o_class, PROP_VSCROLL_POLICY, "vscroll-policy");
 
   g_object_class_install_property (o_class,
                                    PROP_HEADERS_VISIBLE,
@@ -754,6 +777,7 @@ pspp_sheet_view_class_init (PsppSheetViewClass *class)
                                                                GTK_PARAM_READABLE));
 
   /* Signals */
+#if GTK3_TRANSITION
   /**
    * PsppSheetView::set-scroll-adjustments
    * @horizontal: the horizontal #GtkAdjustment
@@ -773,6 +797,7 @@ pspp_sheet_view_class_init (PsppSheetViewClass *class)
                  G_TYPE_NONE, 2,
                  GTK_TYPE_ADJUSTMENT,
                  GTK_TYPE_ADJUSTMENT);
+#endif
 
   /**
    * PsppSheetView::row-activated:
@@ -1094,6 +1119,9 @@ pspp_sheet_view_init (PsppSheetView *tree_view)
   tree_view->priv->button_style = NULL;
 
   tree_view->dispose_has_run = FALSE;
+
+  pspp_sheet_view_do_set_vadjustment (tree_view, NULL);
+  pspp_sheet_view_do_set_hadjustment (tree_view, NULL);
 }
 
 \f
@@ -1117,12 +1145,20 @@ pspp_sheet_view_set_property (GObject         *object,
       pspp_sheet_view_set_model (tree_view, g_value_get_object (value));
       break;
     case PROP_HADJUSTMENT:
-      pspp_sheet_view_set_hadjustment (tree_view, g_value_get_object (value));
+      pspp_sheet_view_do_set_hadjustment (tree_view, g_value_get_object (value));
       break;
     case PROP_VADJUSTMENT:
-      pspp_sheet_view_set_vadjustment (tree_view, g_value_get_object (value));
+      pspp_sheet_view_do_set_vadjustment (tree_view, g_value_get_object (value));
       break;
-    case PROP_HEADERS_VISIBLE:
+    case PROP_HSCROLL_POLICY:
+      tree_view->priv->hscroll_policy = g_value_get_enum (value);
+      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+      break;
+    case PROP_VSCROLL_POLICY:
+      tree_view->priv->vscroll_policy = g_value_get_enum (value);
+      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+      break;
+     case PROP_HEADERS_VISIBLE:
       pspp_sheet_view_set_headers_visible (tree_view, g_value_get_boolean (value));
       break;
     case PROP_HEADERS_CLICKABLE:
@@ -1205,6 +1241,12 @@ pspp_sheet_view_get_property (GObject    *object,
     case PROP_VADJUSTMENT:
       g_value_set_object (value, tree_view->priv->vadjustment);
       break;
+    case PROP_HSCROLL_POLICY:
+      g_value_set_enum (value, tree_view->priv->hscroll_policy);
+      break;
+    case PROP_VSCROLL_POLICY:
+      g_value_set_enum (value, tree_view->priv->vscroll_policy);
+      break;
     case PROP_HEADERS_VISIBLE:
       g_value_set_boolean (value, pspp_sheet_view_get_headers_visible (tree_view));
       break;
@@ -1477,10 +1519,9 @@ pspp_sheet_view_realize (GtkWidget *widget)
   attributes.height = allocation.height;
   attributes.wclass = GDK_INPUT_OUTPUT;
   attributes.visual = gtk_widget_get_visual (widget);
-  attributes.colormap = gtk_widget_get_colormap (widget);
   attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
 
-  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
 
   gtk_widget_set_window (widget,
                         gdk_window_new (gtk_widget_get_parent_window (widget),
@@ -3749,10 +3790,11 @@ invalidate_empty_focus (PsppSheetView *tree_view)
  * is empty.
  */
 static void
-draw_empty_focus (PsppSheetView *tree_view, GdkRectangle *clip_area)
+draw_empty_focus (PsppSheetView *tree_view)
 {
   GtkWidget *widget = GTK_WIDGET (tree_view);
   gint w, h;
+  cairo_t *cr = gdk_cairo_create (tree_view->priv->bin_window);
 
   if (!gtk_widget_has_focus (widget))
     return;
@@ -3765,12 +3807,12 @@ draw_empty_focus (PsppSheetView *tree_view, GdkRectangle *clip_area)
 
   if (w > 0 && h > 0)
     gtk_paint_focus (gtk_widget_get_style (widget),
-                    tree_view->priv->bin_window,
+                    cr,
                     gtk_widget_get_state (widget),
-                    clip_area,
                     widget,
                     NULL,
                     1, 1, w, h);
+  cairo_destroy (cr);
 }
 
 static void
@@ -3792,21 +3834,24 @@ pspp_sheet_view_draw_vertical_grid_lines (PsppSheetView    *tree_view,
   for (list = tree_view->priv->columns; list; list = list->next, i++)
     {
       PsppSheetViewColumn *column = list->data;
-
-      /* We don't want a line for the last column */
-      if (i == n_visible_columns - 1)
-       break;
+      gint x;
 
       if (! column->visible)
        continue;
 
       current_x += column->width;
 
+      /* Generally the grid lines should fit within the column, but for the
+         last visible column we put it just past the end of the column.
+         (Otherwise horizontal grid lines sometimes stick out by one pixel.) */
+      x = current_x;
+      if (i != n_visible_columns - 1)
+        x--;
+
       cairo_set_line_width (cr, 1.0);
       cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
-      cairo_move_to (cr, current_x - 0.5, min_y);
-      cairo_line_to (cr, current_x - 0.5 , max_y - min_y);
-      
+      cairo_move_to (cr, x + 0.5, min_y);
+      cairo_line_to (cr, x + 0.5, max_y - min_y);
       cairo_stroke (cr);
     }
 }
@@ -3819,7 +3864,7 @@ pspp_sheet_view_draw_vertical_grid_lines (PsppSheetView    *tree_view,
  */
 static gboolean
 pspp_sheet_view_bin_expose (GtkWidget      *widget,
-                           GdkEventExpose *event)
+                           cairo_t *cr)
 {
   PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
   GtkTreePath *path;
@@ -3850,7 +3895,14 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
   gboolean row_ending_details;
   gboolean draw_vgrid_lines, draw_hgrid_lines;
   gint min_y, max_y;
-  cairo_t *cr = gdk_cairo_create (event->window);
+
+  GdkRectangle Zarea;
+  GtkAllocation allocation;
+  gtk_widget_get_allocation (widget, &allocation);
+
+  Zarea.x =      0;
+  Zarea.y =      0;
+  Zarea.height = allocation.height;
 
   rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
 
@@ -3864,17 +3916,19 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
 
   if (tree_view->priv->row_count == 0)
     {
-      draw_empty_focus (tree_view, &event->area);
+      draw_empty_focus (tree_view);
       return TRUE;
     }
 
+#if GTK3_TRANSITION
   /* clip event->area to the visible area */
-  if (event->area.height < 0.5)
+  if (Zarea.height < 0.5)
     return TRUE;
+#endif
 
   validate_visible_area (tree_view);
 
-  new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, event->area.y);
+  new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, Zarea.y);
 
   if (new_y < 0)
     new_y = 0;
@@ -3889,10 +3943,9 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
   if (tree_view->priv->height < bin_window_height)
     {
       gtk_paint_flat_box (gtk_widget_get_style (widget),
-                          event->window,
+                          cr,
                           gtk_widget_get_state (widget),
                           GTK_SHADOW_NONE,
-                          &event->area,
                           widget,
                           "cell_even",
                           0, tree_view->priv->height,
@@ -3974,7 +4027,7 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
 
       cell_offset = 0;
 
-      background_area.y = y_offset + event->area.y;
+      background_area.y = y_offset + Zarea.y;
       background_area.height = max_height;
       max_y = background_area.y + max_height;
 
@@ -4025,12 +4078,14 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
           else
             selected_column = TRUE;
 
-         if (cell_offset > event->area.x + event->area.width ||
-             cell_offset + column->width < event->area.x)
+#if GTK3_TRANSITION
+         if (cell_offset > Zarea.x + Zarea.width ||
+             cell_offset + column->width < Zarea.x)
            {
              cell_offset += column->width;
              continue;
            }
+#endif
 
           if (selected && selected_column)
             flags |= GTK_CELL_RENDERER_SELECTED;
@@ -4163,10 +4218,9 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
                g_snprintf (new_detail, 128, "%s_middle", detail);
 
              gtk_paint_flat_box (gtk_widget_get_style (widget),
-                                 event->window,
+                                 cr,
                                  state,
                                  GTK_SHADOW_NONE,
-                                 &event->area,
                                  widget,
                                  new_detail,
                                  background_area.x,
@@ -4177,10 +4231,9 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
          else
            {
              gtk_paint_flat_box (gtk_widget_get_style (widget),
-                                 event->window,
+                                 cr,
                                  state,
                                  GTK_SHADOW_NONE,
-                                 &event->area,
                                  widget,
                                  detail,
                                  background_area.x,
@@ -4209,7 +4262,7 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
 #endif
                }
 
-             if (y_offset + max_height >= event->area.height - 0.5)
+             if (y_offset + max_height <= Zarea.height - 0.5)
                {
 #if GTK3_TRANSITION
                  gdk_draw_line (event->window,
@@ -4228,10 +4281,9 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
            }
 
           _pspp_sheet_view_column_cell_render (column,
-                                               event->window,
+                                               cr,
                                                &background_area,
                                                &cell_area,
-                                               &event->area,
                                                flags);
 
           if (node == cursor && has_special_cell &&
@@ -4241,28 +4293,26 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
               (column == tree_view->priv->edited_column)))
            {
              _pspp_sheet_view_column_cell_draw_focus (column,
-                                                    event->window,
+                                                      cr,
                                                     &background_area,
                                                     &cell_area,
-                                                    &event->area,
                                                     flags);
            }
 
          cell_offset += column->width;
        }
 
-      if (cell_offset < event->area.x)
+      if (cell_offset < Zarea.x)
         {
           gtk_paint_flat_box (gtk_widget_get_style (widget),
-                              event->window,
+                              cr,
                               GTK_STATE_NORMAL,
                               GTK_SHADOW_NONE,
-                              &event->area,
                               widget,
                               "base",
                               cell_offset,
                               background_area.y,
-                              event->area.x - cell_offset,
+                              Zarea.x - cell_offset,
                               background_area.height);
         }
 
@@ -4296,9 +4346,8 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
 
              if (row_ending_details)
                gtk_paint_focus (gtk_widget_get_style (widget),
-                                tree_view->priv->bin_window,
+                                cr,
                                 gtk_widget_get_state (widget),
-                                &event->area,
                                 widget,
                                 (is_first
                                  ? (is_last ? "treeview-drop-indicator" : "treeview-drop-indicator-left" )
@@ -4309,9 +4358,8 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
                               - focus_line_width + 1);
              else
                gtk_paint_focus (gtk_widget_get_style (widget),
-                                tree_view->priv->bin_window,
+                                cr,
                                 gtk_widget_get_state (widget),
-                                &event->area,
                                 widget,
                                 "treeview-drop-indicator",
                                 0, BACKGROUND_FIRST_PIXEL (tree_view, node)
@@ -4364,9 +4412,8 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
 
          if (row_ending_details)
            gtk_paint_focus (gtk_widget_get_style (widget),
-                            tree_view->priv->bin_window,
+                            cr,
                             focus_rect_state,
-                            &event->area,
                             widget,
                             (is_first
                              ? (is_last ? "treeview" : "treeview-left" )
@@ -4375,9 +4422,8 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
                             width, tmp_height);
          else
            gtk_paint_focus (gtk_widget_get_style (widget),
-                            tree_view->priv->bin_window,
+                            cr,
                             focus_rect_state,
-                            &event->area,
                             widget,
                             "treeview",
                             0, tmp_y,
@@ -4402,7 +4448,7 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
         }
       while (!done);
     }
-  while (y_offset < event->area.height);
+  while (y_offset < Zarea.height);
 
 done:
   pspp_sheet_view_draw_vertical_grid_lines (tree_view, cr, n_visible_columns,
@@ -4434,19 +4480,24 @@ done:
   return FALSE;
 }
 
+
 static gboolean
-pspp_sheet_view_expose (GtkWidget      *widget,
-                        GdkEventExpose *event)
+pspp_sheet_view_draw (GtkWidget      *widget,
+                     cairo_t *cr)
 {
   PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
-  cairo_t *cr = gdk_cairo_create (event->window);
-
-  if (event->window == tree_view->priv->bin_window)
+  GtkAllocation allocation;
+  gtk_widget_get_allocation (widget, &allocation);
+  
+  if (gtk_cairo_should_draw_window (cr, tree_view->priv->bin_window))
     {
       gboolean retval;
       GList *tmp_list;
 
-      retval = pspp_sheet_view_bin_expose (widget, event);
+      cairo_save (cr);
+      cairo_translate (cr, 0, gdk_window_get_height (tree_view->priv->header_window));
+      retval = pspp_sheet_view_bin_expose (widget, cr);
+      cairo_restore (cr);
 
       /* We can't just chain up to Container::expose as it will try to send the
        * event to the headers, so we handle propagating it to our children
@@ -4458,27 +4509,27 @@ pspp_sheet_view_expose (GtkWidget      *widget,
          PsppSheetViewChild *child = tmp_list->data;
          tmp_list = tmp_list->next;
 
-         gtk_container_propagate_expose (GTK_CONTAINER (tree_view), child->widget, event);
+         gtk_container_propagate_draw (GTK_CONTAINER (tree_view), child->widget, cr);
        }
 
       return retval;
     }
-  else if (event->window == tree_view->priv->header_window)
+  else if (gtk_cairo_should_draw_window (cr, tree_view->priv->header_window))
     {
       gint n_visible_columns;
       GList *list;
 
       gtk_paint_flat_box (gtk_widget_get_style (widget),
-                          event->window,
+                          cr,
                           GTK_STATE_NORMAL,
                           GTK_SHADOW_NONE,
-                          &event->area,
                           widget,
                           "cell_odd",
-                          event->area.x,
-                          event->area.y,
-                          event->area.width,
-                          event->area.height);
+                         allocation.x,
+                         allocation.y,
+                         allocation.width,
+                         allocation.height
+                         );
 
       for (list = tree_view->priv->columns; list != NULL; list = list->next)
        {
@@ -4488,10 +4539,10 @@ pspp_sheet_view_expose (GtkWidget      *widget,
            continue;
 
           if (span_intersects (column->allocation.x, column->allocation.width,
-                               event->area.x, event->area.width)
+                              allocation.x, allocation.width)
               && column->button != NULL)
-            gtk_container_propagate_expose (GTK_CONTAINER (tree_view),
-                                            column->button, event);
+            gtk_container_propagate_draw (GTK_CONTAINER (tree_view),
+                                         column->button, cr);
        }
 
       n_visible_columns = 0;
@@ -4504,16 +4555,21 @@ pspp_sheet_view_expose (GtkWidget      *widget,
       pspp_sheet_view_draw_vertical_grid_lines (tree_view,
                                                cr,
                                                n_visible_columns,
-                                               event->area.y,
-                                               event->area.height);
+                                               allocation.y,
+                                               allocation.height);
+
+      return TRUE;
     }
-  else if (event->window == tree_view->priv->drag_window)
+  else if (gtk_cairo_should_draw_window (cr, tree_view->priv->drag_window))
     {
-      gtk_container_propagate_expose (GTK_CONTAINER (tree_view),
-                                     tree_view->priv->drag_column->button,
-                                     event);
+      gtk_container_propagate_draw (GTK_CONTAINER (tree_view),
+                                   tree_view->priv->drag_column->button,
+                                   cr);
+     
+      return TRUE;
     }
-  return TRUE;
+
+  return FALSE;
 }
 
 enum
@@ -7691,9 +7747,8 @@ _pspp_sheet_view_column_start_drag (PsppSheetView       *tree_view,
       attributes.width = column->allocation.width;
       attributes.height = column->allocation.height;
       attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
-      attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
       attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
-      attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+      attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL ;
 
       tree_view->priv->drag_window = gdk_window_new (tree_view->priv->bin_window,
                                                     &attributes,
@@ -7725,7 +7780,9 @@ _pspp_sheet_view_column_start_drag (PsppSheetView       *tree_view,
   send_event->button.axes = NULL;
   send_event->button.state = 0;
   send_event->button.button = 1;
-  send_event->button.device = gdk_display_get_core_pointer (display);
+  send_event->button.device = 
+    gdk_device_manager_get_client_pointer (gdk_display_get_device_manager (display));
+
   send_event->button.x_root = 0;
   send_event->button.y_root = 0;
 
@@ -9175,9 +9232,12 @@ pspp_sheet_view_get_hadjustment (PsppSheetView *tree_view)
 {
   g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
 
-  if (tree_view->priv->hadjustment == NULL)
-    pspp_sheet_view_set_hadjustment (tree_view, NULL);
+  return pspp_sheet_view_do_get_hadjustment (tree_view);
+}
 
+static GtkAdjustment *
+pspp_sheet_view_do_get_hadjustment (PsppSheetView *tree_view)
+{
   return tree_view->priv->hadjustment;
 }
 
@@ -9201,23 +9261,60 @@ pspp_sheet_view_set_hadjustment (PsppSheetView   *tree_view,
   g_object_notify (G_OBJECT (tree_view), "hadjustment");
 }
 
+static void
+pspp_sheet_view_do_set_hadjustment (PsppSheetView   *tree_view,
+                                  GtkAdjustment *adjustment)
+{
+  PsppSheetViewPrivate *priv = tree_view->priv;
+
+  if (adjustment && priv->hadjustment == adjustment)
+    return;
+
+  if (priv->hadjustment != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (priv->hadjustment,
+                                            pspp_sheet_view_adjustment_changed,
+                                            tree_view);
+      g_object_unref (priv->hadjustment);
+    }
+
+  if (adjustment == NULL)
+    adjustment = gtk_adjustment_new (0.0, 0.0, 0.0,
+                                     0.0, 0.0, 0.0);
+
+  g_signal_connect (adjustment, "value-changed",
+                    G_CALLBACK (pspp_sheet_view_adjustment_changed), tree_view);
+  priv->hadjustment = g_object_ref_sink (adjustment);
+  /* FIXME: Adjustment should probably be populated here with fresh values, but
+   * internal details are too complicated for me to decipher right now.
+   */
+  pspp_sheet_view_adjustment_changed (NULL, tree_view);
+
+  g_object_notify (G_OBJECT (tree_view), "hadjustment");
+}
+
 /**
  * pspp_sheet_view_get_vadjustment:
  * @tree_view: A #PsppSheetView
  *
  * Gets the #GtkAdjustment currently being used for the vertical aspect.
  *
- * Return value: A #GtkAdjustment object, or %NULL if none is currently being
- * used.
+ * Return value: (transfer none): A #GtkAdjustment object, or %NULL
+ *     if none is currently being used.
+ *
+ * Deprecated: 3.0: Use gtk_scrollable_get_vadjustment()
  **/
 GtkAdjustment *
 pspp_sheet_view_get_vadjustment (PsppSheetView *tree_view)
 {
   g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
 
-  if (tree_view->priv->vadjustment == NULL)
-    pspp_sheet_view_set_vadjustment (tree_view, NULL);
+  return pspp_sheet_view_do_get_vadjustment (tree_view);
+}
 
+static GtkAdjustment *
+pspp_sheet_view_do_get_vadjustment (PsppSheetView *tree_view)
+{
   return tree_view->priv->vadjustment;
 }
 
@@ -9227,17 +9324,47 @@ pspp_sheet_view_get_vadjustment (PsppSheetView *tree_view)
  * @adjustment: (allow-none): The #GtkAdjustment to set, or %NULL
  *
  * Sets the #GtkAdjustment for the current vertical aspect.
+ *
+ * Deprecated: 3.0: Use gtk_scrollable_set_vadjustment()
  **/
 void
 pspp_sheet_view_set_vadjustment (PsppSheetView   *tree_view,
-                              GtkAdjustment *adjustment)
+                               GtkAdjustment *adjustment)
 {
   g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
+  g_return_if_fail (adjustment == NULL || GTK_IS_ADJUSTMENT (adjustment));
 
-  pspp_sheet_view_set_adjustments (tree_view,
-                                tree_view->priv->hadjustment,
-                                adjustment);
+  pspp_sheet_view_do_set_vadjustment (tree_view, adjustment);
+}
 
+static void
+pspp_sheet_view_do_set_vadjustment (PsppSheetView   *tree_view,
+                                  GtkAdjustment *adjustment)
+{
+  PsppSheetViewPrivate *priv = tree_view->priv;
+
+  if (adjustment && priv->vadjustment == adjustment)
+    return;
+
+  if (priv->vadjustment != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (priv->vadjustment,
+                                            pspp_sheet_view_adjustment_changed,
+                                            tree_view);
+      g_object_unref (priv->vadjustment);
+    }
+
+  if (adjustment == NULL)
+    adjustment = gtk_adjustment_new (0.0, 0.0, 0.0,
+                                     0.0, 0.0, 0.0);
+
+  g_signal_connect (adjustment, "value-changed",
+                    G_CALLBACK (pspp_sheet_view_adjustment_changed), tree_view);
+  priv->vadjustment = g_object_ref_sink (adjustment);
+  /* FIXME: Adjustment should probably be populated here with fresh values, but
+   * internal details are too complicated for me to decipher right now.
+   */
+  pspp_sheet_view_adjustment_changed (NULL, tree_view);
   g_object_notify (G_OBJECT (tree_view), "vadjustment");
 }
 
@@ -12525,7 +12652,7 @@ pspp_sheet_view_event (GtkWidget *widget,
   gtk_tree_path_free (path);
 
   handled = gtk_binding_set_activate (edit_bindings, keyval, event->state,
-                                      GTK_OBJECT (tree_view));
+                                      G_OBJECT (tree_view));
   if (handled)
     g_signal_stop_emission_by_name (widget, "event");