diff --git a/src/vte.cc b/src/vte.cc
index 292725c..c1c1b4e 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -1787,11 +1787,11 @@ vte_terminal_emit_adjustment_changed(VteTerminal *terminal)
 		terminal->pvt->adjustment_changed_pending = FALSE;
 	}
 	if (terminal->pvt->adjustment_value_changed_pending) {
-		glong v, delta;
+		double v, delta;
 		_vte_debug_print(VTE_DEBUG_SIGNALS,
 				"Emitting adjustment_value_changed.\n");
 		terminal->pvt->adjustment_value_changed_pending = FALSE;
-		v = round (gtk_adjustment_get_value(terminal->pvt->vadjustment));
+		v = gtk_adjustment_get_value(terminal->pvt->vadjustment);
 		if (v != terminal->pvt->screen->scroll_delta) {
 			/* this little dance is so that the scroll_delta is
 			 * updated immediately, but we still handled scrolling
@@ -1814,9 +1814,12 @@ vte_terminal_queue_adjustment_changed(VteTerminal *terminal)
 }
 
 static void
-vte_terminal_queue_adjustment_value_changed(VteTerminal *terminal, glong v)
+vte_terminal_queue_adjustment_value_changed(VteTerminal *terminal, double v)
 {
 	if (v != terminal->pvt->screen->scroll_delta) {
+                _vte_debug_print(VTE_DEBUG_ADJ,
+                                 "Adjustment value changed to %f\n",
+                                 v);
 		terminal->pvt->screen->scroll_delta = v;
 		terminal->pvt->adjustment_value_changed_pending = TRUE;
 		add_update_timeout (terminal);
@@ -1824,7 +1827,7 @@ vte_terminal_queue_adjustment_value_changed(VteTerminal *terminal, glong v)
 }
 
 static void
-vte_terminal_queue_adjustment_value_changed_clamped(VteTerminal *terminal, glong v)
+vte_terminal_queue_adjustment_value_changed_clamped(VteTerminal *terminal, double v)
 {
 	gdouble lower, upper;
 
@@ -1925,7 +1928,7 @@ _vte_terminal_adjust_adjustments_full (VteTerminal *terminal)
 static void
 vte_terminal_scroll_lines(VteTerminal *terminal, gint lines)
 {
-	glong destination;
+	double destination;
 	_vte_debug_print(VTE_DEBUG_ADJ, "Scrolling %d lines.\n", lines);
 	/* Calculate the ideal position where we want to be before clamping. */
 	destination = terminal->pvt->screen->scroll_delta;
@@ -7337,10 +7340,11 @@ vte_terminal_motion_notify(GtkWidget *widget, GdkEventMotion *event)
 	width = terminal->pvt->char_width;
 	height = terminal->pvt->char_height;
 
-	_vte_debug_print(VTE_DEBUG_EVENTS,
-			"Motion notify (%ld,%ld) [%ld, %ld].\n",
-			x, y,
-			x / width, y / height + terminal->pvt->screen->scroll_delta);
+// FIXME
+//	_vte_debug_print(VTE_DEBUG_EVENTS,
+//			"Motion notify (%ld,%ld) [%ld, %ld].\n",
+//			x, y,
+//			x / width, y / height + terminal->pvt->screen->scroll_delta);
 
 	vte_terminal_read_modifiers (terminal, (GdkEvent*) event);
 
@@ -8058,19 +8062,19 @@ vte_terminal_screen_set_size(VteTerminal *terminal, VteScreen *screen, glong old
 	gboolean was_scrolled_to_top = (screen->scroll_delta == _vte_ring_delta(ring));
 	gboolean was_scrolled_to_bottom = (screen->scroll_delta == screen->insert_delta);
 	glong old_top_lines;
-	glong new_scroll_delta;
+	double new_scroll_delta;
 
         if (terminal->pvt->selection_block_mode && do_rewrap && old_columns != terminal->pvt->column_count)
                 vte_terminal_deselect_all(terminal);
 
 	_vte_debug_print(VTE_DEBUG_RESIZE,
 			"Resizing %s screen\n"
-			"Old  insert_delta=%ld  scroll_delta=%ld\n"
-                        "     cursor (absolute)  row=%ld  (visual line %ld)  col=%ld\n"
+			"Old  insert_delta=%ld  scroll_delta=%f\n"
+                        "     cursor (absolute)  row=%ld  col=%ld\n"
 			"     cursor_saved (relative to insert_delta)  row=%ld  col=%ld\n",
 			screen == &terminal->pvt->normal_screen ? "normal" : "alternate",
 			screen->insert_delta, screen->scroll_delta,
-                        terminal->pvt->cursor.row, terminal->pvt->cursor.row - screen->scroll_delta + 1, terminal->pvt->cursor.col,
+                        terminal->pvt->cursor.row, terminal->pvt->cursor.col,
                         screen->saved.cursor.row, screen->saved.cursor.col);
 
         cursor_saved_absolute.row = screen->saved.cursor.row + screen->insert_delta;
@@ -8156,6 +8160,8 @@ vte_terminal_screen_set_size(VteTerminal *terminal, VteScreen *screen, glong old
 			   TODO: What would be the best behavior if the bottom of the screen is a
 			   soft line break, i.e. only a partial line is visible at the bottom? */
 			new_scroll_delta = below_viewport.row - terminal->pvt->row_count;
+			/* Keep the old fractional part. */
+			new_scroll_delta += screen->scroll_delta - floor(screen->scroll_delta);
 			_vte_debug_print(VTE_DEBUG_RESIZE,
 					"Scroll so bottom row stays\n");
 		}
@@ -8167,11 +8173,11 @@ vte_terminal_screen_set_size(VteTerminal *terminal, VteScreen *screen, glong old
         screen->saved.cursor.col = cursor_saved_absolute.col;
 
 	_vte_debug_print(VTE_DEBUG_RESIZE,
-			"New  insert_delta=%ld  scroll_delta=%ld\n"
-                        "     cursor (absolute)  row=%ld  (visual line %ld)  col=%ld\n"
+			"New  insert_delta=%ld  scroll_delta=%f\n"
+                        "     cursor (absolute)  row=%ld  col=%ld\n"
 			"     cursor_saved (relative to insert_delta)  row=%ld  col=%ld\n\n",
 			screen->insert_delta, new_scroll_delta,
-                        terminal->pvt->cursor.row, terminal->pvt->cursor.row - new_scroll_delta + 1, terminal->pvt->cursor.col,
+                        terminal->pvt->cursor.row, terminal->pvt->cursor.col,
                         screen->saved.cursor.row, screen->saved.cursor.col);
 
 	if (screen == terminal->pvt->screen)
@@ -8252,13 +8258,13 @@ vte_terminal_set_size(VteTerminal *terminal, glong columns, glong rows)
 static void
 vte_terminal_handle_scroll(VteTerminal *terminal)
 {
-	long dy, adj;
+	double dy, adj;
 	VteScreen *screen;
 
 	screen = terminal->pvt->screen;
 
 	/* Read the new adjustment value and save the difference. */
-	adj = round (gtk_adjustment_get_value(terminal->pvt->vadjustment));
+	adj = gtk_adjustment_get_value(terminal->pvt->vadjustment);
 	dy = adj - screen->scroll_delta;
 	screen->scroll_delta = adj;
 
@@ -8271,9 +8277,9 @@ vte_terminal_handle_scroll(VteTerminal *terminal)
 
 	if (dy != 0) {
 		_vte_debug_print(VTE_DEBUG_ADJ,
-			    "Scrolling by %ld\n", dy);
+			    "Scrolling by %f\n", dy);
 		_vte_terminal_scroll_region(terminal, screen->scroll_delta,
-					   terminal->pvt->row_count, -dy);
+					   terminal->pvt->row_count, dy < 0 ? -dy + 1 : -dy - 1); // FIXME
 		vte_terminal_emit_text_scrolled(terminal, dy);
 		_vte_terminal_queue_contents_changed(terminal);
 	} else {
@@ -9877,7 +9883,7 @@ vte_terminal_expand_region (VteTerminal *terminal, cairo_region_t *region, const
 	 * inclusion of neighbouring cells */
 	row = MAX(0, (area->y - terminal->pvt->padding.top - 1) / height);
 	row_stop = MIN(howmany(area->height + area->y - terminal->pvt->padding.top + 1, height),
-		       terminal->pvt->row_count);
+		       terminal->pvt->row_count) + 1; // FIXME
 	if (row_stop <= row) {
 		return;
 	}
@@ -9921,7 +9927,7 @@ vte_terminal_paint_area (VteTerminal *terminal, const GdkRectangle *area)
 
 	row = MAX(0, (area->y - terminal->pvt->padding.top) / height);
 	row_stop = MIN((area->height + area->y - terminal->pvt->padding.top) / height,
-		       terminal->pvt->row_count);
+		       terminal->pvt->row_count) + 1; // FIXME
 	if (row_stop <= row) {
 		return;
 	}
@@ -9951,7 +9957,7 @@ vte_terminal_paint_area (VteTerminal *terminal, const GdkRectangle *area)
 			      row + delta, row_stop - row,
 			      col, col_stop - col,
 			      col * width,
-			      row * height,
+			      row * height - ((long)(screen->scroll_delta * height)) % height,
 			      width,
 			      height);
 }
@@ -10361,19 +10367,19 @@ vte_terminal_scroll(GtkWidget *widget, GdkEventScroll *event)
 	_vte_debug_print(VTE_DEBUG_EVENTS,
 			"Scroll speed is %d lines per non-smooth scroll unit\n",
 			(int) v);
-	cnt = v * terminal->pvt->mouse_smooth_scroll_delta;
-	if (cnt == 0)
-		return TRUE;
-	terminal->pvt->mouse_smooth_scroll_delta -= cnt / v;
-	_vte_debug_print(VTE_DEBUG_EVENTS,
-			"Scroll by %d lines, smooth scroll delta set back to %f\n",
-			cnt, terminal->pvt->mouse_smooth_scroll_delta);
-
 	if (terminal->pvt->screen == &terminal->pvt->alternate_screen &&
             terminal->pvt->alternate_screen_scroll) {
 		char *normal;
 		gssize normal_length;
 
+		cnt = v * terminal->pvt->mouse_smooth_scroll_delta;
+		if (cnt == 0)
+			return TRUE;
+		terminal->pvt->mouse_smooth_scroll_delta -= cnt / v;
+		_vte_debug_print(VTE_DEBUG_EVENTS,
+				"Scroll by %d lines, smooth scroll delta set back to %f\n",
+				cnt, terminal->pvt->mouse_smooth_scroll_delta);
+
 		/* In the alternate screen there is no scrolling,
 		 * so fake a few cursor keystrokes. */
 
@@ -10393,8 +10399,11 @@ vte_terminal_scroll(GtkWidget *widget, GdkEventScroll *event)
 		g_free (normal);
 	} else {
 		/* Perform a history scroll. */
-		cnt += terminal->pvt->screen->scroll_delta;
-		vte_terminal_queue_adjustment_value_changed_clamped (terminal, cnt);
+		// Fixme: ugly
+		double dcnt = v * terminal->pvt->mouse_smooth_scroll_delta;
+		dcnt += terminal->pvt->screen->scroll_delta;
+		terminal->pvt->mouse_smooth_scroll_delta = 0;
+		vte_terminal_queue_adjustment_value_changed_clamped (terminal, dcnt);
 	}
 
 	return TRUE;
diff --git a/src/vteaccess.cc b/src/vteaccess.cc
index e33b3fd..4349ba9 100644
--- a/src/vteaccess.cc
+++ b/src/vteaccess.cc
@@ -509,7 +509,9 @@ vte_terminal_accessible_text_scrolled(VteTerminal *terminal,
 	long delta, row_count;
 	guint i, len;
 
-	g_assert(howmuch != 0);
+// FIXME!
+//	g_assert(howmuch != 0);
+	if (howmuch == 0) return;
 
         row_count = vte_terminal_get_row_count(terminal);
 	if (((howmuch < 0) && (howmuch <= -row_count)) ||
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index 04d8104..d585365 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -102,7 +102,7 @@ struct _vte_incoming_chunk{
 typedef struct _VteScreen VteScreen;
 struct _VteScreen {
         VteRing row_data[1];	/* buffer contents */
-        long scroll_delta;	/* scroll offset */
+        double scroll_delta;	/* scroll offset */
         long insert_delta;	/* insertion offset */
 
         /* Stuff saved along with the cursor */
