diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 7d7c38c..4e4fb13 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -1071,8 +1071,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
 	void register_region_actions ();
 
         void load_bindings ();
-        Gtkmm2ext::ActionMap editor_action_map;
-        Gtkmm2ext::Bindings  key_bindings;
+	Gtkmm2ext::ActionMap editor_action_map;
+	Gtkmm2ext::Bindings  key_bindings;
 
 	int ensure_cursor (framepos_t* pos);
 
@@ -1700,13 +1700,11 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
 	uint32_t autoscroll_cnt;
 	framecnt_t autoscroll_x_distance;
 	double autoscroll_y_distance;
-
-	bool _autoscroll_fudging;
-	int autoscroll_fudge_threshold () const;
+	double _autoscroll_rightmost_pixel;
 
 	static gint _autoscroll_canvas (void *);
 	bool autoscroll_canvas ();
-	void start_canvas_autoscroll (int x, int y);
+	void start_canvas_autoscroll (int, int);
 	void stop_canvas_autoscroll ();
 
 	/* trimming */
diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc
index 479784a..0c7d306 100644
--- a/gtk2_ardour/editor_canvas.cc
+++ b/gtk2_ardour/editor_canvas.cc
@@ -479,22 +479,9 @@ Editor::drop_regions (const RefPtr<Gdk::DragContext>& /*context*/,
 	_drags->end_grab (0);
 }
 
-/** If the editor window is arranged such that the edge of the trackview is right up
- *  against the edge of the screen, autoscroll will not work very well.  In this situation,
- *  we start autoscrolling some distance in from the right-hand-side of the screen edge;
- *  this is the distance at which that happens.
- */
-int
-Editor::autoscroll_fudge_threshold () const
-{
-	return current_page_frames() / 6;
-}
-
 void
 Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert)
 {
-	bool startit = false;
-
 	/* Work out the distance between the right hand edge of the trackview and the edge of
 	   the monitor that it is on.
 	*/
@@ -514,48 +501,51 @@ Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert)
 		distance += pixel_to_frame (editor_list.get_width());
 	}
 
-	/* Note whether we're fudging the autoscroll (see autoscroll_fudge_threshold) */
-	_autoscroll_fudging = (distance < autoscroll_fudge_threshold ());
+	/* If the editor window is arranged such that the edge of the trackview is right up
+	   against the edge of the screen, autoscroll will not work very well.  In this situation,
+	   we start autoscrolling some distance in from the right-hand-side of the screen edge;
+	   this is the distance (in frames) at which that happens.
+	 */
+	framecnt_t autoscroll_fudge_threshold = current_page_frames() / 6;
+
+	/* Decide whether to autoscroll y */
 
 	double const ty = _drags->current_pointer_y() - get_trackview_group_vertical_offset ();
 
-	autoscroll_y = 0;
-	autoscroll_x = 0;
+	int ax = 0;
+	int ay = 0;
+	
 	if (ty < canvas_timebars_vsize && allow_vert) {
-		autoscroll_y = -1;
-		startit = true;
+		ay = -1;
 	} else if (ty > _canvas_height && allow_vert) {
-		autoscroll_y = 1;
-		startit = true;
+		ay = 1;
 	}
 
-	framepos_t rightmost_frame = leftmost_frame + current_page_frames();
-	if (_autoscroll_fudging) {
-		rightmost_frame -= autoscroll_fudge_threshold ();
+	/* And similarly x */
+
+	_autoscroll_rightmost_pixel = window_rect.get_x () + _canvas_width;
+	if (distance < autoscroll_fudge_threshold) {
+		_autoscroll_rightmost_pixel -= frame_to_pixel (autoscroll_fudge_threshold);
 	}
 
-	if (_drags->current_pointer_frame() > rightmost_frame && allow_horiz) {
-		if (rightmost_frame < max_framepos) {
-			autoscroll_x = 1;
-			startit = true;
-		}
-	} else if (_drags->current_pointer_frame() < leftmost_frame && allow_horiz) {
-		if (leftmost_frame > 0) {
-			autoscroll_x = -1;
-			startit = true;
-		}
+	if (_drags->current_pointer_event_x() > _autoscroll_rightmost_pixel && allow_horiz) {
+		ax = 1;
+	} else if (_drags->current_pointer_event_x() < 0 && allow_horiz) {
+		ax = -1;
 	}
 
+	/* Stop if things have changed, or if no autoscroll is required */
 	if (autoscroll_active && ((autoscroll_x != last_autoscroll_x) || (autoscroll_y != last_autoscroll_y) || (autoscroll_x == 0 && autoscroll_y == 0))) {
 		stop_canvas_autoscroll ();
 	}
 
-	if (startit && autoscroll_timeout_tag < 0) {
-		start_canvas_autoscroll (autoscroll_x, autoscroll_y);
+	/* (Re)start if appropriate */
+	if ((ax != 0 || ay != 0) && autoscroll_timeout_tag < 0) {
+		start_canvas_autoscroll (ax, ay);
 	}
 
-	last_autoscroll_x = autoscroll_x;
-	last_autoscroll_y = autoscroll_y;
+	last_autoscroll_x = ax;
+	last_autoscroll_y = ay;
 }
 
 gint
@@ -572,27 +562,17 @@ Editor::autoscroll_canvas ()
 	GdkEventMotion ev;
 	double new_pixel;
 	double target_pixel;
-	
-	if (autoscroll_x_distance != 0) {
-
-		if (autoscroll_x > 0) {
-			autoscroll_x_distance = (_drags->current_pointer_frame() - (leftmost_frame + current_page_frames())) / 3;
-			if (_autoscroll_fudging) {
-				autoscroll_x_distance += autoscroll_fudge_threshold () / 3;
-			}
-		} else if (autoscroll_x < 0) {
-			autoscroll_x_distance = (leftmost_frame - _drags->current_pointer_frame()) / 3;
 
-		}
+	if (autoscroll_x > 0) {
+		autoscroll_x_distance = pixel_to_frame ((_drags->current_pointer_event_x() - _autoscroll_rightmost_pixel) / 3);
+	} else if (autoscroll_x < 0) {
+		autoscroll_x_distance = pixel_to_frame (- _drags->current_pointer_event_x() / 3);
 	}
 
-	if (autoscroll_y_distance != 0) {
-		if (autoscroll_y > 0) {
-			autoscroll_y_distance = (_drags->current_pointer_y() - (get_trackview_group_vertical_offset() + _canvas_height)) / 3;
-		} else if (autoscroll_y < 0) {
-
-			autoscroll_y_distance = (vertical_adjustment.get_value () - _drags->current_pointer_y()) / 3;
-		}
+	if (autoscroll_y > 0) {
+		autoscroll_y_distance = (_drags->current_pointer_y() - (get_trackview_group_vertical_offset() + _canvas_height)) / 3;
+	} else if (autoscroll_y < 0) {
+		autoscroll_y_distance = (vertical_adjustment.get_value () - _drags->current_pointer_y()) / 3;
 	}
 
 	if (autoscroll_x < 0) {
@@ -679,7 +659,7 @@ Editor::autoscroll_canvas ()
 
 		/* connect the timeout so that we get called repeatedly */
 
-		autoscroll_timeout_tag = g_idle_add ( _autoscroll_canvas, this);
+		autoscroll_timeout_tag = g_idle_add (_autoscroll_canvas, this);
 		return false;
 
 	}
@@ -699,8 +679,6 @@ Editor::start_canvas_autoscroll (int dx, int dy)
 	autoscroll_active = true;
 	autoscroll_x = dx;
 	autoscroll_y = dy;
-	autoscroll_x_distance = (framepos_t) floor (current_page_frames()/50.0);
-	autoscroll_y_distance = fabs (dy * 5); /* pixels */
 	autoscroll_cnt = 0;
 
 	/* do it right now, which will start the repeated callbacks */
diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc
index 3eeca0a..647feb5 100644
--- a/gtk2_ardour/editor_drag.cc
+++ b/gtk2_ardour/editor_drag.cc
@@ -125,6 +125,7 @@ DragManager::start_grab (GdkEvent* e, Gdk::Cursor* c)
 	_editor->set_follow_playhead (false);
 
 	_current_pointer_frame = _editor->event_frame (e, &_current_pointer_x, &_current_pointer_y);
+	_current_pointer_event_x = e->button.x;
 
 	for (list<Drag*>::const_iterator i = _drags.begin(); i != _drags.end(); ++i) {
 		(*i)->start_grab (e, c);
@@ -163,6 +164,7 @@ DragManager::motion_handler (GdkEvent* e, bool from_autoscroll)
 	bool r = false;
 
 	_current_pointer_frame = _editor->event_frame (e, &_current_pointer_x, &_current_pointer_y);
+	_current_pointer_event_x = e->motion.x;
 
 	for (list<Drag*>::iterator i = _drags.begin(); i != _drags.end(); ++i) {
 		bool const t = (*i)->motion_handler (e, from_autoscroll);
diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h
index 44b2d50..5e256dc 100644
--- a/gtk2_ardour/editor_drag.h
+++ b/gtk2_ardour/editor_drag.h
@@ -77,6 +77,11 @@ public:
 		return !_drags.empty ();
 	}
 
+	/** @return the current raw GDK event pointer position */
+	double current_pointer_event_x () const {
+		return _current_pointer_event_x;
+	}
+	
 	/** @return current pointer x position in trackview coordinates */
 	double current_pointer_x () const {
 		return _current_pointer_x;
@@ -96,6 +101,7 @@ private:
 	Editor* _editor;
 	std::list<Drag*> _drags;
 	bool _ending; ///< true if end_grab or abort is in progress, otherwise false
+	double _current_pointer_event_x; ///< the current raw GDK event pointer position
 	double _current_pointer_x; ///< trackview x of the current pointer
 	double _current_pointer_y; ///< trackview y of the current pointer
 	ARDOUR::framepos_t _current_pointer_frame; ///< frame that the pointer is now at
