Fix some set-but-not-used variable warnings from gcc 4.6
[ardour.git] / gtk2_ardour / editor_drag.cc
index f8e810232d1f0a0f53ffa451f78aa4ce4bad3ff2..c889921db774b7ed5ac9f29edd9c1859d2f4e0c1 100644 (file)
@@ -54,6 +54,7 @@
 #include "debug.h"
 #include "editor_cursors.h"
 #include "mouse_cursors.h"
+#include "verbose_cursor.h"
 
 using namespace std;
 using namespace ARDOUR;
@@ -65,14 +66,13 @@ using namespace ArdourCanvas;
 
 using Gtkmm2ext::Keyboard;
 
-double const ControlPointDrag::_zero_gain_fraction = gain_to_slider_position (dB_to_coefficient (0.0));
+double ControlPointDrag::_zero_gain_fraction = -1.0;
 
 DragManager::DragManager (Editor* e)
        : _editor (e)
        , _ending (false)
        , _current_pointer_frame (0)
 {
-
 }
 
 DragManager::~DragManager ()
@@ -85,16 +85,18 @@ void
 DragManager::abort ()
 {
        _ending = true;
-       
+
        for (list<Drag*>::const_iterator i = _drags.begin(); i != _drags.end(); ++i) {
                (*i)->abort ();
                delete *i;
        }
 
+       if (!_drags.empty ()) {
+               _editor->set_follow_playhead (_old_follow_playhead, false);
+       }
+
        _drags.clear ();
 
-       _editor->set_follow_playhead (_old_follow_playhead, false);
-       
        _ending = false;
 }
 
@@ -119,9 +121,9 @@ DragManager::start_grab (GdkEvent* e, Gdk::Cursor* c)
        /* Prevent follow playhead during the drag to be nice to the user */
        _old_follow_playhead = _editor->follow_playhead ();
        _editor->set_follow_playhead (false);
-               
+
        _current_pointer_frame = _editor->event_frame (e, &_current_pointer_x, &_current_pointer_y);
-       
+
        for (list<Drag*>::const_iterator i = _drags.begin(); i != _drags.end(); ++i) {
                (*i)->start_grab (e, c);
        }
@@ -134,7 +136,7 @@ bool
 DragManager::end_grab (GdkEvent* e)
 {
        _ending = true;
-       
+
        bool r = false;
        for (list<Drag*>::iterator i = _drags.begin(); i != _drags.end(); ++i) {
                bool const t = (*i)->end_grab (e);
@@ -149,7 +151,7 @@ DragManager::end_grab (GdkEvent* e)
        _ending = false;
 
        _editor->set_follow_playhead (_old_follow_playhead, false);
-       
+
        return r;
 }
 
@@ -159,13 +161,13 @@ DragManager::motion_handler (GdkEvent* e, bool from_autoscroll)
        bool r = false;
 
        _current_pointer_frame = _editor->event_frame (e, &_current_pointer_x, &_current_pointer_y);
-       
+
        for (list<Drag*>::iterator i = _drags.begin(); i != _drags.end(); ++i) {
                bool const t = (*i)->motion_handler (e, from_autoscroll);
                if (t) {
                        r = true;
                }
-               
+
        }
 
        return r;
@@ -182,7 +184,7 @@ DragManager::have_item (ArdourCanvas::Item* i) const
        return j != _drags.end ();
 }
 
-Drag::Drag (Editor* e, ArdourCanvas::Item* i) 
+Drag::Drag (Editor* e, ArdourCanvas::Item* i)
        : _editor (e)
        , _item (i)
        , _pointer_frame_offset (0)
@@ -273,7 +275,7 @@ Drag::end_grab (GdkEvent* event)
 
        finished (event, _move_threshold_passed);
 
-       _editor->hide_verbose_canvas_cursor();
+       _editor->verbose_cursor()->hide ();
 
        return _move_threshold_passed;
 }
@@ -316,7 +318,7 @@ Drag::motion_handler (GdkEvent* event, bool from_autoscroll)
 
        if (!from_autoscroll && !_move_threshold_passed) {
 
-               bool const xp = (::llabs (_drags->current_pointer_frame () - _grab_frame) >= threshold.first);
+               bool const xp = (::llabs (_drags->current_pointer_frame () - _raw_grab_frame) >= threshold.first);
                bool const yp = (::fabs ((_drags->current_pointer_y () - _grab_y)) >= threshold.second);
 
                _move_threshold_passed = ((xp && x_movement_matters()) || (yp && y_movement_matters()));
@@ -334,7 +336,7 @@ Drag::motion_handler (GdkEvent* event, bool from_autoscroll)
                        _last_pointer_x = _drags->current_pointer_x ();
                        _last_pointer_y = _drags->current_pointer_y ();
                        _last_pointer_frame = adjusted_current_frame (event);
-                       
+
                        return true;
                }
        }
@@ -352,9 +354,46 @@ Drag::abort ()
        aborted (_move_threshold_passed);
 
        _editor->stop_canvas_autoscroll ();
-       _editor->hide_verbose_canvas_cursor ();
+       _editor->verbose_cursor()->hide ();
 }
 
+void
+Drag::show_verbose_cursor_time (framepos_t frame)
+{
+       _editor->verbose_cursor()->set_time (
+               frame,
+               _drags->current_pointer_x() + 10 - _editor->horizontal_position(),
+               _drags->current_pointer_y() + 10 - _editor->vertical_adjustment.get_value() + _editor->canvas_timebars_vsize
+               );
+
+       _editor->verbose_cursor()->show ();
+}
+
+void
+Drag::show_verbose_cursor_duration (framepos_t start, framepos_t end, double xoffset)
+{
+       _editor->verbose_cursor()->show (xoffset);
+
+       _editor->verbose_cursor()->set_duration (
+               start, end,
+               _drags->current_pointer_x() + 10 - _editor->horizontal_position(),
+               _drags->current_pointer_y() + 10 - _editor->vertical_adjustment.get_value() + _editor->canvas_timebars_vsize
+               );
+}
+
+void
+Drag::show_verbose_cursor_text (string const & text)
+{
+       _editor->verbose_cursor()->show ();
+
+       _editor->verbose_cursor()->set (
+               text,
+               _drags->current_pointer_x() + 10 - _editor->horizontal_position(),
+               _drags->current_pointer_y() + 10 - _editor->vertical_adjustment.get_value() + _editor->canvas_timebars_vsize
+               );
+}
+
+
 struct EditorOrderTimeAxisViewSorter {
     bool operator() (TimeAxisView* a, TimeAxisView* b) {
            RouteTimeAxisView* ra = dynamic_cast<RouteTimeAxisView*> (a);
@@ -377,7 +416,7 @@ RegionDrag::RegionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<Re
 
        for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
                if (!(*i)->hidden()) {
-                       
+
                        _time_axis_views.push_back (*i);
 
                        TimeAxisView::Children children_list = (*i)->get_child_list ();
@@ -389,11 +428,11 @@ RegionDrag::RegionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<Re
 
        /* the list of views can be empty at this point if this is a region list-insert drag
         */
-       
+
        for (list<RegionView*>::const_iterator i = v.begin(); i != v.end(); ++i) {
                _views.push_back (DraggingView (*i, this));
        }
-       
+
        RegionView::RegionViewGoingAway.connect (death_connection, invalidator (*this), ui_bind (&RegionDrag::region_going_away, this, _1), gui_context());
 }
 
@@ -423,7 +462,7 @@ RegionDrag::find_time_axis_view (TimeAxisView* t) const
        if (i == N) {
                return -1;
        }
-       
+
        return i;
 }
 
@@ -441,7 +480,7 @@ RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
 {
        Drag::start_grab (event, cursor);
 
-       _editor->show_verbose_time_cursor (_last_frame_position, 10);
+       show_verbose_cursor_time (_last_frame_position);
 
        pair<TimeAxisView*, int> const tv = _editor->trackview_by_y_position (_drags->current_pointer_y ());
        _last_pointer_time_axis_view = find_time_axis_view (tv.first);
@@ -459,19 +498,19 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r
        framepos_t sync_frame;
        framecnt_t sync_offset;
        int32_t sync_dir;
-       
+
        sync_offset = _primary->region()->sync_offset (sync_dir);
-       
+
        /* we don't handle a sync point that lies before zero.
         */
        if (sync_dir >= 0 || (sync_dir < 0 && *pending_region_position >= sync_offset)) {
-               
+
                sync_frame = *pending_region_position + (sync_dir*sync_offset);
-               
+
                _editor->snap_to_with_modifier (sync_frame, event);
-               
+
                *pending_region_position = _primary->region()->adjust_to_sync (sync_frame);
-               
+
        } else {
                *pending_region_position = _last_frame_position;
        }
@@ -487,13 +526,13 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r
 
        if ((*pending_region_position != _last_frame_position) && x_move_allowed) {
 
-               /* x movement since last time */
+               /* x movement since last time (in pixels) */
                dx = (static_cast<double> (*pending_region_position) - _last_frame_position) / _editor->frames_per_unit;
 
                /* total x movement */
                framecnt_t total_dx = *pending_region_position;
                if (regions_came_from_canvas()) {
-                       total_dx = total_dx - grab_frame () + _pointer_frame_offset;
+                       total_dx = total_dx - grab_frame ();
                }
 
                /* check that no regions have gone off the start of the session */
@@ -526,7 +565,7 @@ RegionMotionDrag::y_movement_allowed (int delta_track, layer_t delta_layer) cons
                        /* not a track, or the wrong type */
                        return false;
                }
-               
+
                int const l = i->layer + delta_layer;
                if (delta_track == 0 && (l < 0 || l >= int (to->view()->layers()))) {
                        /* Off the top or bottom layer; note that we only refuse if the track hasn't changed.
@@ -551,7 +590,7 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
        /* Bail early if we're not over a track */
        RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv.first);
        if (!rtv || !rtv->is_track()) {
-               _editor->hide_verbose_canvas_cursor ();
+               _editor->verbose_cursor()->hide ();
                return;
        }
 
@@ -597,39 +636,39 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
                        /* here we are calculating the y distance from the
                           top of the first track view to the top of the region
                           area of the track view that we're working on */
-                       
+
                        /* this x value is just a dummy value so that we have something
                           to pass to i2w () */
-                       
+
                        double ix1 = 0;
-                       
+
                        /* distance from the top of this track view to the region area
                           of our track view is always 1 */
-                       
+
                        double iy1 = 1;
-                       
+
                        /* convert to world coordinates, ie distance from the top of
                           the ruler section */
-                       
+
                        rv->get_canvas_frame()->i2w (ix1, iy1);
-                       
+
                        /* compensate for the ruler section and the vertical scrollbar position */
                        iy1 += _editor->get_trackview_group_vertical_offset ();
-                       
+
                        // hide any dependent views
-                       
+
                        rv->get_time_axis_view().hide_dependent_views (*rv);
-                       
+
                        /*
                          reparent to a non scrolling group so that we can keep the
                          region selection above all time axis views.
                          reparenting means we have to move the rv as the two
                          parent groups have different coordinates.
                        */
-                       
+
                        rv->get_canvas_group()->property_y() = iy1 - 1;
                        rv->get_canvas_group()->reparent (*(_editor->_region_motion_group));
-                       
+
                        rv->fake_set_opaque (true);
                }
 
@@ -687,13 +726,13 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
        } /* foreach region */
 
        _total_x_delta += x_delta;
-       
+
        if (first_move) {
                _editor->cursor_group->raise_to_top();
        }
 
        if (x_delta != 0 && !_brushing) {
-               _editor->show_verbose_time_cursor (_last_frame_position, 10);
+               show_verbose_cursor_time (_last_frame_position);
        }
 
        _last_pointer_time_axis_view += delta_time_axis_view;
@@ -710,20 +749,20 @@ RegionMoveDrag::motion (GdkEvent* event, bool first_move)
                list<DraggingView> new_regionviews;
 
                for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
-                       
+
                        RegionView* rv = i->view;
                        AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
                        MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(rv);
 
                        const boost::shared_ptr<const Region> original = rv->region();
                        boost::shared_ptr<Region> region_copy = RegionFactory::create (original, true);
-                       region_copy->set_position (original->position(), this);
-                       
+                       region_copy->set_position (original->position());
+
                        RegionView* nrv;
                        if (arv) {
                                boost::shared_ptr<AudioRegion> audioregion_copy
                                = boost::dynamic_pointer_cast<AudioRegion>(region_copy);
-                               
+
                                nrv = new AudioRegionView (*arv, audioregion_copy);
                        } else if (mrv) {
                                boost::shared_ptr<MidiRegion> midiregion_copy
@@ -732,29 +771,29 @@ RegionMoveDrag::motion (GdkEvent* event, bool first_move)
                        } else {
                                continue;
                        }
-                       
+
                        nrv->get_canvas_group()->show ();
                        new_regionviews.push_back (DraggingView (nrv, this));
-                       
+
                        /* swap _primary to the copy */
-                       
+
                        if (rv == _primary) {
                                _primary = nrv;
                        }
-                       
+
                        /* ..and deselect the one we copied */
-                       
+
                        rv->set_selected (false);
                }
-               
+
                if (!new_regionviews.empty()) {
-                       
+
                        /* reflect the fact that we are dragging the copies */
-                       
+
                        _views = new_regionviews;
-                       
+
                        swap_grab (new_regionviews.front().view->get_canvas_group (), 0, event ? event->motion.time : 0);
-                       
+
                        /*
                          sync the canvas to what we think is its current state
                          without it, the canvas seems to
@@ -792,23 +831,23 @@ RegionMoveDrag::finished (GdkEvent *, bool movement_occurred)
        framecnt_t const drag_delta = _primary->region()->position() - _last_frame_position;
 
        _editor->update_canvas_now ();
-       
+
        if (_copy) {
-               
+
                finished_copy (
                        changed_position,
                        changed_tracks,
                        drag_delta
                        );
-               
+
        } else {
-               
+
                finished_no_copy (
                        changed_position,
                        changed_tracks,
                        drag_delta
                        );
-               
+
        }
 }
 
@@ -831,9 +870,9 @@ RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed
        }
 
        if (_x_constrained) {
-               _editor->begin_reversible_command (_("fixed time region copy"));
+               _editor->begin_reversible_command (Operations::fixed_time_region_copy);
        } else {
-               _editor->begin_reversible_command (_("region copy"));
+               _editor->begin_reversible_command (Operations::region_copy);
        }
 
        /* insert the regions into their new playlists */
@@ -854,13 +893,13 @@ RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed
                RegionView* new_view = insert_region_into_playlist (
                        i->view->region(), dynamic_cast<RouteTimeAxisView*> (_time_axis_views[i->time_axis_view]), i->layer, where, modified_playlists
                        );
-               
+
                if (new_view == 0) {
                        continue;
                }
 
                new_views.push_back (new_view);
-               
+
                /* we don't need the copied RegionView any more */
                views_to_delete.push_back (i->view);
        }
@@ -873,8 +912,8 @@ RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed
                delete *i;
        }
 
-       /* If we've created new regions either by copying or moving 
-          to a new track, we want to replace the old selection with the new ones 
+       /* If we've created new regions either by copying or moving
+          to a new track, we want to replace the old selection with the new ones
        */
 
        if (new_views.size() > 0) {
@@ -958,7 +997,7 @@ RegionMoveDrag::finished_no_copy (
                        remove_region_from_playlist (rv->region(), i->initial_playlist, modified_playlists);
 
                } else {
-                       
+
                        rv->region()->clear_changes ();
 
                        /*
@@ -974,12 +1013,12 @@ RegionMoveDrag::finished_no_copy (
                        /* just change the model */
 
                        boost::shared_ptr<Playlist> playlist = dest_rtv->playlist();
-                       
+
                        if (dest_rtv->view()->layer_display() == Stacked) {
                                rv->region()->set_layer (dest_layer);
                                rv->region()->set_pending_explicit_relayer (true);
                        }
-                       
+
                        /* freeze playlist to avoid lots of relayering in the case of a multi-region drag */
 
                        pair<PlaylistSet::iterator, bool> r = frozen_playlists.insert (playlist);
@@ -991,19 +1030,19 @@ RegionMoveDrag::finished_no_copy (
                        /* this movement may result in a crossfade being modified, so we need to get undo
                           data from the playlist as well as the region.
                        */
-                       
+
                        r = modified_playlists.insert (playlist);
                        if (r.second) {
                                playlist->clear_changes ();
                        }
 
-                       rv->region()->set_position (where, (void*) this);
+                       rv->region()->set_position (where);
 
                        _editor->session()->add_command (new StatefulDiffCommand (rv->region()));
                }
 
                if (changed_tracks) {
-                       
+
                        /* OK, this is where it gets tricky. If the playlist was being used by >1 tracks, and the region
                           was selected in all of them, then removing it from a playlist will have removed all
                           trace of it from _views (i.e. there were N regions selected, we removed 1,
@@ -1021,7 +1060,7 @@ RegionMoveDrag::finished_no_copy (
                           we can just iterate.
                        */
 
-                       
+
                        if (_views.empty()) {
                                break;
                        } else {
@@ -1033,8 +1072,8 @@ RegionMoveDrag::finished_no_copy (
                }
        }
 
-       /* If we've created new regions either by copying or moving 
-          to a new track, we want to replace the old selection with the new ones 
+       /* If we've created new regions either by copying or moving
+          to a new track, we want to replace the old selection with the new ones
        */
 
        if (new_views.size() > 0) {
@@ -1072,7 +1111,7 @@ RegionMoveDrag::remove_region_from_playlist (
 
        playlist->remove_region (region);
 }
-       
+
 
 /** Insert a region into a playlist, handling the recovery of the resulting new RegionView, and
  *  clearing the playlist's diff history first if necessary.
@@ -1081,7 +1120,7 @@ RegionMoveDrag::remove_region_from_playlist (
  *  @param dest_layer Destination layer.
  *  @param where Destination position.
  *  @param modified_playlists The playlist will be added to this if it is not there already; used to ensure
- *  that clear_changes () is only called once per playlist. 
+ *  that clear_changes () is only called once per playlist.
  *  @return New RegionView, or 0 if no insert was performed.
  */
 RegionView *
@@ -1102,7 +1141,7 @@ RegionMoveDrag::insert_region_into_playlist (
        _new_region_view = 0;
        sigc::connection c = dest_rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &RegionMoveDrag::collect_new_region_view));
 
-       /* clear history for the playlist we are about to insert to, provided we haven't already done so */     
+       /* clear history for the playlist we are about to insert to, provided we haven't already done so */
        pair<PlaylistSet::iterator, bool> r = modified_playlists.insert (dest_playlist);
        if (r.second) {
                dest_playlist->clear_changes ();
@@ -1185,7 +1224,7 @@ RegionMoveDrag::RegionMoveDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p,
          _copy (c)
 {
        DEBUG_TRACE (DEBUG::Drags, "New RegionMoveDrag\n");
-       
+
        double speed = 1;
        RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&_primary->get_time_axis_view ());
        if (rtv && rtv->is_track()) {
@@ -1205,7 +1244,7 @@ RegionInsertDrag::RegionInsertDrag (Editor* e, boost::shared_ptr<Region> r, Rout
        : RegionMotionDrag (e, 0, 0, list<RegionView*> (), false)
 {
        DEBUG_TRACE (DEBUG::Drags, "New RegionInsertDrag\n");
-       
+
        assert ((boost::dynamic_pointer_cast<AudioRegion> (r) && dynamic_cast<AudioTimeAxisView*> (v)) ||
                (boost::dynamic_pointer_cast<MidiRegion> (r) && dynamic_cast<MidiTimeAxisView*> (v)));
 
@@ -1270,11 +1309,6 @@ RegionSpliceDrag::motion (GdkEvent* event, bool)
 
        pair<TimeAxisView*, int> const tvp = _editor->trackview_by_y_position (_drags->current_pointer_y ());
        RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*> (tvp.first);
-       layer_t layer = tvp.second;
-
-       if (tv && tv->layer_display() == Overlaid) {
-               layer = 0;
-       }
 
        /* The region motion is only processed if the pointer is over
           an audio track.
@@ -1284,7 +1318,7 @@ RegionSpliceDrag::motion (GdkEvent* event, bool)
                /* To make sure we hide the verbose canvas cursor when the mouse is
                   not held over and audiotrack.
                */
-               _editor->hide_verbose_canvas_cursor ();
+               _editor->verbose_cursor()->hide ();
                return;
        }
 
@@ -1353,7 +1387,7 @@ RegionCreateDrag::RegionCreateDrag (Editor* e, ArdourCanvas::Item* i, TimeAxisVi
          _view (dynamic_cast<MidiTimeAxisView*> (v))
 {
        DEBUG_TRACE (DEBUG::Drags, "New RegionCreateDrag\n");
-       
+
        assert (_view);
 }
 
@@ -1367,12 +1401,18 @@ RegionCreateDrag::motion (GdkEvent* event, bool first_move)
                if (_region) {
                        framepos_t const f = adjusted_current_frame (event);
                        if (f < grab_frame()) {
-                               _region->set_position (f, this);
+                               _region->set_position (f);
                        }
-                        
-                       /* again, don't use a zero-length region (see above) */
-                       framecnt_t const len = abs (f - grab_frame ());
-                       _region->set_length (len < 1 ? 1 : len, this);
+
+                       /* Don't use a zero-length region, and subtract 1 frame from the snapped length
+                          so that if this region is duplicated, its duplicate starts on
+                          a snap point rather than 1 frame after a snap point.  Otherwise things get
+                          a bit confusing as if a region starts 1 frame after a snap point, one cannot
+                          place snapped notes at the start of the region.
+                       */
+
+                       framecnt_t const len = abs (f - grab_frame () - 1);
+                       _region->set_length (len < 1 ? 1 : len);
                }
        }
 }
@@ -1570,16 +1610,16 @@ TrimDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
 
        switch (_operation) {
        case StartTrim:
-               _editor->show_verbose_time_cursor (region_start, 10);
+               show_verbose_cursor_time (region_start);
                for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
                        i->view->trim_front_starting ();
                }
                break;
        case EndTrim:
-               _editor->show_verbose_time_cursor (region_end, 10);
+               show_verbose_cursor_time (region_end);
                break;
        case ContentsTrim:
-               _editor->show_verbose_time_cursor (pf, 10);
+               show_verbose_cursor_time (pf);
                break;
        }
 
@@ -1671,7 +1711,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
                        }
 
                        framecnt_t frame_delta = 0;
-                       
+
                        bool left_direction = false;
                        if (last_pointer_frame() > adjusted_current_frame(event)) {
                                left_direction = true;
@@ -1692,13 +1732,13 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
 
        switch (_operation) {
        case StartTrim:
-               _editor->show_verbose_time_cursor ((framepos_t) (rv->region()->position() / speed), 10);
+               show_verbose_cursor_time ((framepos_t) (rv->region()->position() / speed));
                break;
        case EndTrim:
-               _editor->show_verbose_time_cursor ((framepos_t) (rv->region()->last_frame() / speed), 10);
+               show_verbose_cursor_time ((framepos_t) (rv->region()->last_frame() / speed));
                break;
        case ContentsTrim:
-               _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
+               show_verbose_cursor_time (adjusted_current_frame (event));
                break;
        }
 }
@@ -1719,7 +1759,7 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred)
                                i->view->trim_front_ending ();
                        }
                }
-               
+
                if (!_editor->selection->selected (_primary)) {
                        _primary->thaw_after_trim ();
                } else {
@@ -1761,7 +1801,7 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred)
                if (_operation == StartTrim) {
                        i->view->trim_front_ending ();
                }
-               
+
                i->view->region()->resume_property_changes ();
        }
 }
@@ -1775,7 +1815,7 @@ TrimDrag::aborted (bool movement_occurred)
        */
 
        finished (0, true);
-       
+
        if (movement_occurred) {
                _editor->undo ();
        }
@@ -1814,7 +1854,7 @@ MeterMarkerDrag::MeterMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c)
          _copy (c)
 {
        DEBUG_TRACE (DEBUG::Drags, "New MeterMarkerDrag\n");
-       
+
        _marker = reinterpret_cast<MeterMarker*> (_item->get_data ("marker"));
        assert (_marker);
 }
@@ -1851,7 +1891,7 @@ MeterMarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
 
        Drag::start_grab (event, cursor);
 
-       _editor->show_verbose_time_cursor (adjusted_current_frame(event), 10);
+       show_verbose_cursor_time (adjusted_current_frame(event));
 }
 
 void
@@ -1866,8 +1906,8 @@ MeterMarkerDrag::motion (GdkEvent* event, bool)
        framepos_t const pf = adjusted_current_frame (event);
 
        _marker->set_position (pf);
-       
-       _editor->show_verbose_time_cursor (pf, 10);
+
+       show_verbose_cursor_time (pf);
 }
 
 void
@@ -1916,7 +1956,7 @@ TempoMarkerDrag::TempoMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c)
          _copy (c)
 {
        DEBUG_TRACE (DEBUG::Drags, "New TempoMarkerDrag\n");
-       
+
        _marker = reinterpret_cast<TempoMarker*> (_item->get_data ("marker"));
        assert (_marker);
 }
@@ -1946,21 +1986,21 @@ TempoMarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
 
        Drag::start_grab (event, cursor);
 
-       _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
+       show_verbose_cursor_time (adjusted_current_frame (event));
 }
 
 void
 TempoMarkerDrag::setup_pointer_frame_offset ()
 {
        _pointer_frame_offset = raw_grab_frame() - _marker->tempo().frame();
-}      
+}
 
 void
 TempoMarkerDrag::motion (GdkEvent* event, bool)
 {
        framepos_t const pf = adjusted_current_frame (event);
        _marker->set_position (pf);
-       _editor->show_verbose_time_cursor (pf, 10);
+       show_verbose_cursor_time (pf);
 }
 
 void
@@ -2019,7 +2059,7 @@ void
 CursorDrag::fake_locate (framepos_t t)
 {
        _editor->playhead_cursor->set_position (t);
-       
+
        Session* s = _editor->session ();
        if (s->timecode_transmission_suspended ()) {
                framepos_t const f = _editor->playhead_cursor->current_frame;
@@ -2027,7 +2067,7 @@ CursorDrag::fake_locate (framepos_t t)
                s->send_full_time_code (f);
        }
 
-       _editor->show_verbose_time_cursor (t, 10);
+       show_verbose_cursor_time (t);
        _editor->UpdateAllTransportClocks (t);
 }
 
@@ -2036,45 +2076,76 @@ CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
 {
        Drag::start_grab (event, c);
 
+       _grab_zoom = _editor->frames_per_unit;
+
        framepos_t where = _editor->event_frame (event, 0, 0);
        _editor->snap_to_with_modifier (where, event);
 
        _editor->_dragging_playhead = true;
-       
+
        Session* s = _editor->session ();
-       
+
        if (s) {
                if (_was_rolling && _stop) {
                        s->request_stop ();
                }
-               
+
                if (s->is_auditioning()) {
                        s->cancel_audition ();
                }
-               
+
                s->request_suspend_timecode_transmission ();
                while (!s->timecode_transmission_suspended ()) {
                        /* twiddle our thumbs */
                }
        }
-       
+
        fake_locate (where);
 }
 
 void
 CursorDrag::motion (GdkEvent* event, bool)
 {
-       framepos_t const adjusted_frame = adjusted_current_frame (event);
+       if (_drags->current_pointer_y() != last_pointer_y()) {
 
-       if (adjusted_frame == last_pointer_frame()) {
-               return;
+               /* zoom when we move the pointer up and down */
+
+               /* y range to operate over (pixels) */
+               double const y_range = 512;
+               /* we will multiply the grab zoom by a factor between scale_range and scale_range^-1 */
+               double const scale_range = 4;
+               /* dead zone around the grab point in which to do no zooming (pixels) */
+               double const dead_zone = 100;
+
+               /* current dy */
+               double dy = _drags->current_pointer_y() - grab_y();
+
+               if (dy < -dead_zone || dy > dead_zone) {
+                       /* we are outside the dead zone; remove it from our calculation */
+                       if (dy < 0) {
+                               dy += dead_zone;
+                       } else {
+                               dy -= dead_zone;
+                       }
+
+                       /* get a number from -1 to 1 as dy ranges from -y_range to y_range */
+                       double udy = max (min (dy / y_range, 1.0), -1.0);
+
+                       /* and zoom, using playhead focus temporarily */
+                       Editing::ZoomFocus const zf = _editor->get_zoom_focus ();
+                       _editor->set_zoom_focus (Editing::ZoomFocusPlayhead);
+                       _editor->temporal_zoom (_grab_zoom * pow (scale_range, -udy));
+                       _editor->set_zoom_focus (zf);
+               }
        }
 
-       fake_locate (adjusted_frame);
-       
+       framepos_t const adjusted_frame = adjusted_current_frame (event);
+       if (adjusted_frame != last_pointer_frame()) {
+               fake_locate (adjusted_frame);
 #ifdef GTKOSX
-       _editor->update_canvas_now ();
+               _editor->update_canvas_now ();
 #endif
+       }
 }
 
 void
@@ -2103,7 +2174,7 @@ CursorDrag::aborted (bool)
                _editor->session()->request_resume_timecode_transmission ();
                _editor->_dragging_playhead = false;
        }
-       
+
        _editor->playhead_cursor->set_position (adjusted_frame (grab_frame (), 0, false));
 }
 
@@ -2121,8 +2192,8 @@ FadeInDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
        AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
        boost::shared_ptr<AudioRegion> const r = arv->audio_region ();
 
-       _editor->show_verbose_duration_cursor (r->position(), r->position() + r->fade_in()->back()->when, 10);
-       
+       show_verbose_cursor_duration (r->position(), r->position() + r->fade_in()->back()->when, 32);
+
        arv->show_fade_line((framepos_t) r->fade_in()->back()->when);
 }
 
@@ -2163,7 +2234,7 @@ FadeInDrag::motion (GdkEvent* event, bool)
                tmp->show_fade_line((framecnt_t) fade_length);
        }
 
-       _editor->show_verbose_duration_cursor (region->position(), region->position() + fade_length, 10);
+       show_verbose_cursor_duration (region->position(), region->position() + fade_length, 32);
 }
 
 void
@@ -2240,8 +2311,8 @@ FadeOutDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
        AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
        boost::shared_ptr<AudioRegion> r = arv->audio_region ();
 
-       _editor->show_verbose_duration_cursor (r->last_frame() - r->fade_out()->back()->when, r->last_frame(), 10);
-       
+       show_verbose_cursor_duration (r->last_frame() - r->fade_out()->back()->when, r->last_frame());
+
        arv->show_fade_line(r->length() - r->fade_out()->back()->when);
 }
 
@@ -2251,7 +2322,7 @@ FadeOutDrag::setup_pointer_frame_offset ()
        AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
        boost::shared_ptr<AudioRegion> r = arv->audio_region ();
        _pointer_frame_offset = raw_grab_frame() - (r->length() - (framecnt_t) r->fade_out()->back()->when + r->position());
-}      
+}
 
 void
 FadeOutDrag::motion (GdkEvent* event, bool)
@@ -2284,7 +2355,7 @@ FadeOutDrag::motion (GdkEvent* event, bool)
                tmp->show_fade_line(region->length() - fade_length);
        }
 
-       _editor->show_verbose_duration_cursor (region->last_frame() - fade_length, region->last_frame(), 10);
+       show_verbose_cursor_duration (region->last_frame() - fade_length, region->last_frame());
 }
 
 void
@@ -2353,7 +2424,7 @@ MarkerDrag::MarkerDrag (Editor* e, ArdourCanvas::Item* i)
        : Drag (e, i)
 {
        DEBUG_TRACE (DEBUG::Drags, "New MarkerDrag\n");
-       
+
        _marker = reinterpret_cast<Marker*> (_item->get_data ("marker"));
        assert (_marker);
 
@@ -2384,9 +2455,9 @@ MarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
        // _line->raise_to_top();
 
        if (is_start) {
-               _editor->show_verbose_time_cursor (location->start(), 10);
+               show_verbose_cursor_time (location->start());
        } else {
-               _editor->show_verbose_time_cursor (location->end(), 10);
+               show_verbose_cursor_time (location->end());
        }
 
        Selection::Operation op = ArdourKeyboard::selection_type (event->button.state);
@@ -2465,10 +2536,6 @@ MarkerDrag::motion (GdkEvent* event, bool)
 
        framepos_t next = newframe;
 
-       if (newframe == last_pointer_frame()) {
-               return;
-       }
-
        if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
                move_both = true;
        }
@@ -2594,7 +2661,7 @@ MarkerDrag::motion (GdkEvent* event, bool)
 
        assert (!_copied_locations.empty());
 
-       _editor->show_verbose_time_cursor (newframe, 10);
+       show_verbose_cursor_time (newframe);
 
 #ifdef GTKOSX
        _editor->update_canvas_now ();
@@ -2679,8 +2746,12 @@ ControlPointDrag::ControlPointDrag (Editor* e, ArdourCanvas::Item* i)
          _cumulative_x_drag (0),
          _cumulative_y_drag (0)
 {
+       if (_zero_gain_fraction < 0.0) {
+               _zero_gain_fraction = gain_to_slider_position_with_max (dB_to_coefficient (0.0), Config->get_max_gain());
+       }
+
        DEBUG_TRACE (DEBUG::Drags, "New ControlPointDrag\n");
-       
+
        _point = reinterpret_cast<ControlPoint*> (_item->get_data ("control_point"));
        assert (_point);
 }
@@ -2700,10 +2771,10 @@ ControlPointDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
 
        _point->line().start_drag_single (_point, _fixed_grab_x, fraction);
 
-       _editor->set_verbose_canvas_cursor (_point->line().get_verbose_cursor_string (fraction),
-                                           event->button.x + 10, event->button.y + 10);
+       _editor->verbose_cursor()->set (_point->line().get_verbose_cursor_string (fraction),
+                                       event->button.x + 10, event->button.y + 10);
 
-       _editor->show_verbose_canvas_cursor ();
+       _editor->verbose_cursor()->show ();
 }
 
 void
@@ -2746,7 +2817,7 @@ ControlPointDrag::motion (GdkEvent* event, bool)
        cy = min ((double) _point->line().height(), cy);
 
        framepos_t cx_frames = _editor->unit_to_frame (cx);
-       
+
        if (!_x_constrained) {
                _editor->snap_to_with_modifier (cx_frames, event);
        }
@@ -2759,7 +2830,7 @@ ControlPointDrag::motion (GdkEvent* event, bool)
 
        _point->line().drag_motion (_editor->frame_to_unit (cx_frames), fraction, false, push);
 
-       _editor->set_verbose_canvas_cursor_text (_point->line().get_verbose_cursor_string (fraction));
+       _editor->verbose_cursor()->set_text (_point->line().get_verbose_cursor_string (fraction));
 }
 
 void
@@ -2776,7 +2847,7 @@ ControlPointDrag::finished (GdkEvent* event, bool movement_occurred)
        } else {
                motion (event, false);
        }
-       
+
        _point->line().end_drag ();
        _editor->session()->commit_reversible_command ();
 }
@@ -2828,7 +2899,7 @@ LineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
 
        uint32_t before;
        uint32_t after;
-       
+
        if (!_line->control_points_adjacent (frame_within_region, before, after)) {
                /* no adjacent points */
                return;
@@ -2845,10 +2916,10 @@ LineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
 
        _line->start_drag_line (before, after, fraction);
 
-       _editor->set_verbose_canvas_cursor (_line->get_verbose_cursor_string (fraction),
-                                           event->button.x + 10, event->button.y + 10);
+       _editor->verbose_cursor()->set (_line->get_verbose_cursor_string (fraction),
+                                       event->button.x + 10, event->button.y + 10);
 
-       _editor->show_verbose_canvas_cursor ();
+       _editor->verbose_cursor()->show ();
 }
 
 void
@@ -2880,7 +2951,7 @@ LineDrag::motion (GdkEvent* event, bool)
        /* we are ignoring x position for this drag, so we can just pass in anything */
        _line->drag_motion (0, fraction, true, push);
 
-       _editor->set_verbose_canvas_cursor_text (_line->get_verbose_cursor_string (fraction));
+       _editor->verbose_cursor()->set_text (_line->get_verbose_cursor_string (fraction));
 }
 
 void
@@ -2909,7 +2980,7 @@ void
 FeatureLineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
 {
        Drag::start_grab (event);
-       
+
        _line = reinterpret_cast<Line*> (_item);
        assert (_line);
 
@@ -2922,9 +2993,9 @@ FeatureLineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
 
        /* store grab start in parent frame */
        _region_view_grab_x = cx;
-       
+
        _before = *(float*) _item->get_data ("position");
-       
+
        _arv = reinterpret_cast<AudioRegionView*> (_item->get_data ("regionview"));
 
        _max_x = _editor->frame_to_pixel(_arv->get_duration());
@@ -2934,34 +3005,34 @@ void
 FeatureLineDrag::motion (GdkEvent*, bool)
 {
        double dx = _drags->current_pointer_x() - last_pointer_x();
-       
+
        double cx = _region_view_grab_x + _cumulative_x_drag + dx;
-       
+
        _cumulative_x_drag += dx;
-               
+
        /* Clamp the min and max extent of the drag to keep it within the region view bounds */
-       
+
        if (cx > _max_x){
                cx = _max_x;
        }
        else if(cx < 0){
                cx = 0;
        }
-       
+
        ArdourCanvas::Points points;
-       
+
        double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
 
        _line->get_bounds(x1, y2, x2, y2);
-       
+
        points.push_back(Gnome::Art::Point(cx, 2.0)); // first x-coord needs to be a non-normal value
        points.push_back(Gnome::Art::Point(cx, y2 - y1));
 
        _line->property_points() = points;
-       
+
        float *pos = new float;
        *pos = cx;
-       
+
        _line->set_data ("position", pos);
 
        _before = cx;
@@ -2990,7 +3061,7 @@ void
 RubberbandSelectDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
 {
        Drag::start_grab (event);
-       _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
+       show_verbose_cursor_time (adjusted_current_frame (event));
 }
 
 void
@@ -3040,7 +3111,7 @@ RubberbandSelectDrag::motion (GdkEvent* event, bool)
                _editor->rubberband_rect->show();
                _editor->rubberband_rect->raise_to_top();
 
-               _editor->show_verbose_time_cursor (pf, 10);
+               show_verbose_cursor_time (pf);
        }
 }
 
@@ -3102,7 +3173,7 @@ TimeFXDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
 {
        Drag::start_grab (event, cursor);
 
-       _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
+       show_verbose_cursor_time (adjusted_current_frame (event));
 }
 
 void
@@ -3116,7 +3187,7 @@ TimeFXDrag::motion (GdkEvent* event, bool)
                rv->get_time_axis_view().show_timestretch (rv->region()->position(), pf);
        }
 
-       _editor->show_verbose_time_cursor (pf, 10);
+       show_verbose_cursor_time (pf);
 }
 
 void
@@ -3144,8 +3215,6 @@ TimeFXDrag::finished (GdkEvent* /*event*/, bool movement_occurred)
        }
 #endif
 
-       _editor->begin_reversible_command (_("timestretch"));
-
        // XXX how do timeFX on multiple regions ?
 
        RegionSelection rs;
@@ -3245,9 +3314,9 @@ SelectionDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
        }
 
        if (_operation == SelectionMove) {
-               _editor->show_verbose_time_cursor (_editor->selection->time[_editor->clicked_selection].start, 10);
+               show_verbose_cursor_time (_editor->selection->time[_editor->clicked_selection].start);
        } else {
-               _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
+               show_verbose_cursor_time (adjusted_current_frame (event));
        }
 
        _original_pointer_time_axis = _editor->trackview_by_y_position (_drags->current_pointer_y ()).first->order ();
@@ -3283,7 +3352,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
        if (pending_time_axis.first == 0) {
                return;
        }
-       
+
        framepos_t const pending_position = adjusted_current_frame (event);
 
        /* only alter selection if things have changed */
@@ -3328,7 +3397,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
                                        //_editor->selection->set (_editor->clicked_axisview);
                                        _editor->set_selected_track_as_side_effect (Selection::Set);
                                }
-                               
+
                                _editor->clicked_selection = _editor->selection->set (start, end);
                        }
                }
@@ -3343,7 +3412,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
                /* deselect any tracks that this drag no longer includes, being careful to only deselect
                   tracks that we selected in the first place.
                */
-               
+
                int min_order = min (_original_pointer_time_axis, pending_time_axis.first->order());
                int max_order = max (_original_pointer_time_axis, pending_time_axis.first->order());
 
@@ -3352,7 +3421,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
 
                        list<TimeAxisView*>::iterator tmp = i;
                        ++tmp;
-                       
+
                        if ((*i)->order() < min_order || (*i)->order() > max_order) {
                                _editor->selection->remove (*i);
                                _added_time_axes.remove (*i);
@@ -3413,9 +3482,9 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
        }
 
        if (_operation == SelectionMove) {
-               _editor->show_verbose_time_cursor(start, 10);
+               show_verbose_cursor_time(start);
        } else {
-               _editor->show_verbose_time_cursor(pending_position, 10);
+               show_verbose_cursor_time(pending_position);
        }
 }
 
@@ -3447,7 +3516,7 @@ SelectionDrag::finished (GdkEvent* event, bool movement_occurred)
                if (_editor->clicked_axisview && !_editor->selection->selected (_editor->clicked_axisview)) {
                        _editor->selection->set (_editor->clicked_axisview);
                }
-               
+
                if (s && s->get_play_range () && s->transport_rolling()) {
                        s->request_stop (false, false);
                }
@@ -3469,8 +3538,8 @@ RangeMarkerBarDrag::RangeMarkerBarDrag (Editor* e, ArdourCanvas::Item* i, Operat
          _copy (false)
 {
        DEBUG_TRACE (DEBUG::Drags, "New RangeMarkerBarDrag\n");
-       
-       _drag_rect = new ArdourCanvas::SimpleRect (*_editor->time_line_group, 0.0, 0.0, 0.0, 
+
+       _drag_rect = new ArdourCanvas::SimpleRect (*_editor->time_line_group, 0.0, 0.0, 0.0,
                                                   physical_screen_height (_editor->get_window()));
        _drag_rect->hide ();
 
@@ -3507,7 +3576,7 @@ RangeMarkerBarDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
 
        Drag::start_grab (event, cursor);
 
-       _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
+       show_verbose_cursor_time (adjusted_current_frame (event));
 }
 
 void
@@ -3538,7 +3607,7 @@ RangeMarkerBarDrag::motion (GdkEvent* event, bool first_move)
        if (_operation == CreateRangeMarker || _operation == CreateTransportMarker || _operation == CreateCDMarker) {
                framepos_t grab = grab_frame ();
                _editor->snap_to (grab);
-               
+
                if (pf < grab_frame()) {
                        start = pf;
                        end = grab;
@@ -3579,7 +3648,7 @@ RangeMarkerBarDrag::motion (GdkEvent* event, bool first_move)
                update_item (_editor->temp_location);
        }
 
-       _editor->show_verbose_time_cursor (pf, 10);
+       show_verbose_cursor_time (pf);
 
 }
 
@@ -3612,7 +3681,7 @@ RangeMarkerBarDrag::finished (GdkEvent* event, bool movement_occurred)
                        newloc = new Location (
                                *_editor->session(), _editor->temp_location->start(), _editor->temp_location->end(), rangename, (Location::Flags) flags
                                );
-                       
+
                        _editor->session()->locations()->add (newloc, true);
                        XMLNode &after = _editor->session()->locations()->get_state();
                        _editor->session()->add_command(new MementoCommand<Locations>(*(_editor->session()->locations()), &before, &after));
@@ -3696,8 +3765,8 @@ MouseZoomDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
                Drag::start_grab (event, _editor->cursors()->zoom_in);
                _zoom_out = false;
        }
-               
-       _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
+
+       show_verbose_cursor_time (adjusted_current_frame (event));
 }
 
 void
@@ -3729,7 +3798,7 @@ MouseZoomDrag::motion (GdkEvent* event, bool first_move)
 
                _editor->reposition_zoom_rect(start, end);
 
-               _editor->show_verbose_time_cursor (pf, 10);
+               show_verbose_cursor_time (pf);
        }
 }
 
@@ -3808,9 +3877,14 @@ NoteDrag::total_dx () const
 
        /* primary note time */
        frameoffset_t const n = _region->beats_to_frames (_primary->note()->time ());
-       
+
        /* new time of the primary note relative to the region position */
-       frameoffset_t const st = n + dx;
+       frameoffset_t st = n + dx;
+
+       /* prevent the note being dragged earlier than the region's position */
+       if (st < 0) {
+               st = 0;
+       }
 
        /* snap and return corresponding delta */
        return _region->snap_frame_to_frame (st) - n;
@@ -3835,11 +3909,11 @@ NoteDrag::total_dy () const
        }
 
        /* more positive value = higher pitch and higher y-axis position on track,
-          which is the inverse of the X-centric geometric universe 
+          which is the inverse of the X-centric geometric universe
        */
 
-       return -ndy; 
-}      
+       return -ndy;
+}
 
 void
 NoteDrag::motion (GdkEvent *, bool)
@@ -3863,8 +3937,8 @@ NoteDrag::motion (GdkEvent *, bool)
                char buf[12];
                snprintf (buf, sizeof (buf), "%s (%d)", Evoral::midi_note_name (_primary->note()->note() + note_delta).c_str(),
                          (int) floor (_primary->note()->note() + note_delta));
-                
-               _editor->show_verbose_canvas_cursor_with (buf);
+
+               show_verbose_cursor_text (buf);
        }
 }
 
@@ -3909,7 +3983,7 @@ AutomationRangeDrag::AutomationRangeDrag (Editor* editor, ArdourCanvas::Item* it
        , _nothing_to_drag (false)
 {
        DEBUG_TRACE (DEBUG::Drags, "New AutomationRangeDrag\n");
-       
+
        _atav = reinterpret_cast<AutomationTimeAxisView*> (_item->get_data ("trackview"));
        assert (_atav);
 
@@ -3967,13 +4041,13 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
                                i->points.push_back (i->line->nth (j));
                        }
                }
-               
+
        } else {
 
                for (list<AudioRange>::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i) {
 
                        framecnt_t const half = (i->start + i->end) / 2;
-                       
+
                        /* find the line that this audio range starts in */
                        list<Line>::iterator j = _lines.begin();
                        while (j != _lines.end() && (j->range.first > i->start || j->range.second < i->start)) {
@@ -3982,7 +4056,7 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
 
                        if (j != _lines.end()) {
                                boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
-                               
+
                                /* j is the line that this audio range starts in; fade into it;
                                   64 samples length plucked out of thin air.
                                */
@@ -4002,7 +4076,7 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
                        }
 
                        /* same thing for the end */
-                       
+
                        j = _lines.begin();
                        while (j != _lines.end() && (j->range.first > i->end || j->range.second < i->end)) {
                                ++j;
@@ -4010,11 +4084,11 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
 
                        if (j != _lines.end()) {
                                boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
-                               
+
                                /* j is the line that this audio range starts in; fade out of it;
                                   64 samples length plucked out of thin air.
                                */
-                               
+
                                framepos_t b = i->end - 64;
                                if (b < half) {
                                        b = half;
@@ -4022,7 +4096,7 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
 
                                double const p = j->line->time_converter().from (b - j->line->time_converter().origin_b ());
                                double const q = j->line->time_converter().from (i->end - j->line->time_converter().origin_b ());
-                               
+
                                the_list->add (p, the_list->eval (p));
                                j->line->add_always_in_view (p);
                                the_list->add (q, the_list->eval (q));
@@ -4090,7 +4164,7 @@ AutomationRangeDrag::finished (GdkEvent* event, bool)
        if (_nothing_to_drag) {
                return;
        }
-       
+
        motion (event, false);
        for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
                i->line->end_drag ();
@@ -4136,7 +4210,7 @@ PatchChangeDrag::motion (GdkEvent* ev, bool)
        boost::shared_ptr<Region> r = _region_view->region ();
        f = max (f, r->position ());
        f = min (f, r->last_frame ());
-       
+
        framecnt_t const dxf = f - grab_frame();
        double const dxu = _editor->frame_to_unit (dxf);
        _patch_change->move (dxu - _cumulative_dx, 0);
@@ -4151,11 +4225,11 @@ PatchChangeDrag::finished (GdkEvent* ev, bool movement_occurred)
        }
 
        boost::shared_ptr<Region> r (_region_view->region ());
-       
+
        framepos_t f = adjusted_current_frame (ev);
        f = max (f, r->position ());
        f = min (f, r->last_frame ());
-       
+
        _region_view->move_patch_change (
                *_patch_change,
                _region_view->frames_to_beats (f - r->position() - r->start())