make MIDI rubber band selects use the correct canvas item so that event processing...
[ardour.git] / gtk2_ardour / editor_drag.cc
index 5d8a4cc6728b5a38c1672e8dd002f3307e69cf2c..2419169c7fb23f7d301ece441c762e7aaced59fc 100644 (file)
@@ -22,6 +22,7 @@
 #endif
 
 #include <stdint.h>
+#include <algorithm>
 
 #include "pbd/memento_command.h"
 #include "pbd/basename.h"
 #include "editor_drag.h"
 #include "audio_time_axis.h"
 #include "midi_time_axis.h"
-#include "canvas-note.h"
 #include "selection.h"
 #include "midi_selection.h"
 #include "automation_time_axis.h"
 #include "debug.h"
 #include "editor_cursors.h"
 #include "mouse_cursors.h"
+#include "note_base.h"
+#include "patch_change.h"
 #include "verbose_cursor.h"
 
 using namespace std;
@@ -125,7 +127,7 @@ DragManager::start_grab (GdkEvent* e, Gdk::Cursor* c)
        _old_follow_playhead = _editor->follow_playhead ();
        _editor->set_follow_playhead (false);
 
-       _current_pointer_frame = _editor->event_frame (e, &_current_pointer_x, &_current_pointer_y);
+       _current_pointer_frame = _editor->canvas_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);
@@ -163,7 +165,25 @@ 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_frame = _editor->canvas_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;
+}
+
+bool
+DragManager::window_motion_handler (GdkEvent* e, bool from_autoscroll)
+{
+       bool r = false;
+
+       _current_pointer_frame = _editor->window_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);
@@ -200,15 +220,15 @@ Drag::Drag (Editor* e, ArdourCanvas::Item* i)
 }
 
 void
-Drag::swap_grab (ArdourCanvas::Item* new_item, Gdk::Cursor* cursor, uint32_t time)
+Drag::swap_grab (ArdourCanvas::Item* new_item, Gdk::Cursor* cursor, uint32_t /*time*/)
 {
-       _item->ungrab (0);
+       _item->ungrab ();
        _item = new_item;
 
        if (cursor == 0) {
-               _item->grab (Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK, time);
+               _item->grab ();
        } else {
-               _item->grab (Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK, *cursor, time);
+               _item->grab ();
        }
 }
 
@@ -230,7 +250,7 @@ Drag::start_grab (GdkEvent* event, Gdk::Cursor *cursor)
                _y_constrained = false;
        }
 
-       _raw_grab_frame = _editor->event_frame (event, &_grab_x, &_grab_y);
+       _raw_grab_frame = _editor->canvas_event_frame (event, &_grab_x, &_grab_y);
        setup_pointer_frame_offset ();
        _grab_frame = adjusted_frame (_raw_grab_frame, event);
        _last_pointer_frame = _grab_frame;
@@ -238,12 +258,12 @@ Drag::start_grab (GdkEvent* event, Gdk::Cursor *cursor)
        _last_pointer_y = _grab_y;
 
        if (cursor == 0) {
-               _item->grab (Gdk::POINTER_MOTION_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK,
-                            event->button.time);
+               _item->grab ();
+                            
        } else {
-               _item->grab (Gdk::POINTER_MOTION_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK,
-                            *cursor,
-                            event->button.time);
+               /* CAIROCANVAS need a variant here that passes *cursor */
+               _item->grab ();
+
        }
 
        if (_editor->session() && _editor->session()->transport_rolling()) {
@@ -275,7 +295,7 @@ Drag::end_grab (GdkEvent* event)
 {
        _editor->stop_canvas_autoscroll ();
 
-       _item->ungrab (event ? event->button.time : 0);
+       _item->ungrab ();
 
        finished (event, _move_threshold_passed);
 
@@ -354,7 +374,7 @@ void
 Drag::abort ()
 {
        if (_item) {
-               _item->ungrab (0);
+               _item->ungrab ();
        }
 
        aborted (_move_threshold_passed);
@@ -369,7 +389,7 @@ 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
+               _drags->current_pointer_y() + 10 - _editor->vertical_adjustment.get_value()
                );
 
        _editor->verbose_cursor()->show ();
@@ -383,7 +403,7 @@ Drag::show_verbose_cursor_duration (framepos_t start, framepos_t end, double xof
        _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
+               _drags->current_pointer_y() + 10 - _editor->vertical_adjustment.get_value()
                );
 }
 
@@ -395,7 +415,7 @@ Drag::show_verbose_cursor_text (string const & text)
        _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
+               _drags->current_pointer_y() + 10 - _editor->vertical_adjustment.get_value()
                );
 }
 
@@ -494,10 +514,9 @@ RegionMotionDrag::RegionMotionDrag (Editor* e, ArdourCanvas::Item* i, RegionView
          _brushing (b),
          _total_x_delta (0)
 {
-
+       DEBUG_TRACE (DEBUG::Drags, "New RegionMotionDrag\n");
 }
 
-
 void
 RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
 {
@@ -550,7 +569,7 @@ 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 (in pixels) */
-               dx = (static_cast<double> (*pending_region_position) - _last_frame_position) / _editor->frames_per_unit;
+               dx = (static_cast<double> (*pending_region_position) - _last_frame_position) / _editor->samples_per_pixel;
 
                /* total x movement */
                framecnt_t total_dx = *pending_region_position;
@@ -636,6 +655,7 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
        double const x_delta = compute_x_delta (event, &pending_region_position);
 
        /* Work out the change in y */
+
        int delta_time_axis_view = current_pointer_time_axis_view - _last_pointer_time_axis_view;
        double delta_layer = current_pointer_layer - _last_pointer_layer;
 
@@ -658,7 +678,7 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
 
                RegionView* rv = i->view;
 
-               if (rv->region()->locked()) {
+               if (rv->region()->locked() || rv->region()->video_locked()) {
                        continue;
                }
 
@@ -666,20 +686,19 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
 
                        rv->drag_start (); 
 
-                       /* Absolutely no idea why this is necessary, but it is; without
-                          it, the region view disappears after the reparent.
-                       */
-                       _editor->update_canvas_now ();
-                       
                        /* Reparent to a non scrolling group so that we can keep the
                           region selection above all time axis views.
                           Reparenting means that we will have to move the region view
-                          later, as the two parent groups have different coordinates.
+                          within its new parent, as the two parent groups have different coordinates.
                        */
 
-                       rv->get_canvas_group()->reparent (*(_editor->_region_motion_group));
-                       
+                       ArdourCanvas::Group* rvg = rv->get_canvas_group();
+                       Duple rv_canvas_offset = rvg->item_to_canvas (Duple (0,0));
+
+                       rv->get_canvas_group()->reparent (_editor->_region_motion_group);
+
                        rv->fake_set_opaque (true);
+                       rvg->set_position (rv_canvas_offset);
                }
 
                /* If we have moved tracks, we'll fudge the layer delta so that the
@@ -728,9 +747,8 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
                        double y = 0;
 
                        /* Get the y coordinate of the top of the track that this region is now on */
-                       tv->canvas_display()->i2w (x, y);
-                       y += _editor->get_trackview_group_vertical_offset();
-                       
+                       tv->canvas_display()->item_to_canvas (x, y);
+
                        /* And adjust for the layer that it should be on */
                        StreamView* cv = tv->view ();
                        switch (cv->layer_display ()) {
@@ -745,17 +763,13 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
                        }
 
                        /* Now move the region view */
-                       rv->move (x_delta, y - rv->get_canvas_group()->property_y());
+                       rv->move (x_delta, y - rv->get_canvas_group()->position().y);
                }
 
        } /* foreach region */
 
        _total_x_delta += x_delta;
 
-       if (first_move) {
-               _editor->cursor_group->raise_to_top();
-       }
-
        if (x_delta != 0 && !_brushing) {
                show_verbose_cursor_time (_last_frame_position);
        }
@@ -818,15 +832,6 @@ RegionMoveDrag::motion (GdkEvent* event, bool first_move)
                        _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
-                         "forget" to update properly after the upcoming reparent()
-                         ..only if the mouse is in rapid motion at the time of the grab.
-                         something to do with regionview creation taking so long?
-                       */
-                       _editor->update_canvas_now();
                }
        }
 
@@ -879,8 +884,6 @@ RegionMoveDrag::finished (GdkEvent* ev, bool movement_occurred)
        bool const changed_tracks = (_time_axis_views[_views.front().time_axis_view] != &_views.front().view->get_time_axis_view());
        framecnt_t const drag_delta = _primary->region()->position() - _last_frame_position;
        
-       _editor->update_canvas_now ();
-
        if (_copy) {
 
                finished_copy (
@@ -929,7 +932,7 @@ RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed
        /* insert the regions into their new playlists */
        for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
 
-               if (i->view->region()->locked()) {
+               if (i->view->region()->locked() || i->view->region()->video_locked()) {
                        continue;
                }
 
@@ -1008,7 +1011,7 @@ RegionMoveDrag::finished_no_copy (
                RouteTimeAxisView* const dest_rtv = dynamic_cast<RouteTimeAxisView*> (_time_axis_views[i->time_axis_view]);
                double const dest_layer = i->layer;
 
-               if (rv->region()->locked()) {
+               if (rv->region()->locked() || rv->region()->video_locked()) {
                        ++i;
                        continue;
                }
@@ -1060,8 +1063,8 @@ RegionMoveDrag::finished_no_copy (
                           No need to do anything for copies as they are fake regions which will be deleted.
                        */
 
-                       rv->get_canvas_group()->reparent (*dest_rtv->view()->canvas_item());
-                       rv->get_canvas_group()->property_y() = i->initial_y;
+                       rv->get_canvas_group()->reparent (dest_rtv->view()->canvas_item());
+                       rv->get_canvas_group()->set_y_position (i->initial_y);
                        rv->drag_end ();
 
                        /* just change the model */
@@ -1274,15 +1277,13 @@ RegionMotionDrag::aborted (bool)
                TimeAxisView* tv = &(rv->get_time_axis_view ());
                RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
                assert (rtv);
-               rv->get_canvas_group()->reparent (*rtv->view()->canvas_item());
-               rv->get_canvas_group()->property_y() = 0;
+               rv->get_canvas_group()->reparent (rtv->view()->canvas_item());
+               rv->get_canvas_group()->set_y_position (0);
                rv->drag_end ();
                rv->fake_set_opaque (false);
                rv->move (-_total_x_delta, 0);
                rv->set_height (rtv->view()->child_height ());
        }
-
-       _editor->update_canvas_now ();
 }
 
 /** @param b true to brush, otherwise false.
@@ -1331,12 +1332,10 @@ RegionInsertDrag::RegionInsertDrag (Editor* e, boost::shared_ptr<Region> r, Rout
 void
 RegionInsertDrag::finished (GdkEvent *, bool)
 {
-       _editor->update_canvas_now ();
-
        RouteTimeAxisView* dest_rtv = dynamic_cast<RouteTimeAxisView*> (_time_axis_views[_views.front().time_axis_view]);
 
-       _primary->get_canvas_group()->reparent (*dest_rtv->view()->canvas_item());
-       _primary->get_canvas_group()->property_y() = 0;
+       _primary->get_canvas_group()->reparent (dest_rtv->view()->canvas_item());
+       _primary->get_canvas_group()->set_y_position (0);
 
        boost::shared_ptr<Playlist> playlist = dest_rtv->playlist();
 
@@ -1517,7 +1516,8 @@ void
 NoteResizeDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*ignored*/)
 {
        Gdk::Cursor* cursor;
-       ArdourCanvas::CanvasNoteEvent* cnote = dynamic_cast<ArdourCanvas::CanvasNoteEvent*>(_item);
+       NoteBase* cnote = reinterpret_cast<NoteBase*> (_item->get_data ("notebase"));
+       assert (cnote);
        float x_fraction = cnote->mouse_x_fraction ();
 
        if (x_fraction > 0.0 && x_fraction < 0.25) {
@@ -1531,7 +1531,7 @@ NoteResizeDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*ignored*/)
        region = &cnote->region_view();
 
        double const region_start = region->get_position_pixels();
-       double const middle_point = region_start + cnote->x1() + (cnote->x2() - cnote->x1()) / 2.0L;
+       double const middle_point = region_start + cnote->x0() + (cnote->x1() - cnote->x0()) / 2.0L;
 
        if (grab_x() <= middle_point) {
                cursor = _editor->cursors()->left_side_trim;
@@ -1541,7 +1541,7 @@ NoteResizeDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*ignored*/)
                at_front = false;
        }
 
-       _item->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, *cursor, event->motion.time);
+       _item->grab ();
 
        if (event->motion.state & Keyboard::PrimaryModifier) {
                relative = false;
@@ -1575,7 +1575,9 @@ NoteResizeDrag::motion (GdkEvent* /*event*/, bool /*first_move*/)
 {
        MidiRegionSelection& ms (_editor->get_selection().midi_regions);
        for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) {
-               (*r)->update_resizing (dynamic_cast<ArdourCanvas::CanvasNoteEvent*>(_item), at_front, _drags->current_pointer_x() - grab_x(), relative);
+               NoteBase* nb = reinterpret_cast<NoteBase*> (_item->get_data ("notebase"));
+               assert (nb);
+               (*r)->update_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative);
        }
 }
 
@@ -1584,7 +1586,9 @@ NoteResizeDrag::finished (GdkEvent*, bool /*movement_occurred*/)
 {
        MidiRegionSelection& ms (_editor->get_selection().midi_regions);
        for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) {
-               (*r)->commit_resizing (dynamic_cast<ArdourCanvas::CanvasNoteEvent*>(_item), at_front, _drags->current_pointer_x() - grab_x(), relative);
+               NoteBase* nb = reinterpret_cast<NoteBase*> (_item->get_data ("notebase"));
+               assert (nb);
+               (*r)->commit_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative);
        }
 }
 
@@ -1597,6 +1601,165 @@ NoteResizeDrag::aborted (bool)
        }
 }
 
+AVDraggingView::AVDraggingView (RegionView* v)
+       : view (v)
+{
+       initial_position = v->region()->position ();
+}
+
+VideoTimeLineDrag::VideoTimeLineDrag (Editor* e, ArdourCanvas::Item* i)
+       : Drag (e, i)
+{
+       DEBUG_TRACE (DEBUG::Drags, "New VideoTimeLineDrag\n");
+
+       RegionSelection rs;
+       TrackViewList empty;
+       empty.clear();
+       _editor->get_regions_after(rs, (framepos_t) 0, empty);
+       std::list<RegionView*> views = rs.by_layer();
+
+       for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
+               RegionView* rv = (*i);
+               if (!rv->region()->video_locked()) {
+                       continue;
+               }
+               _views.push_back (AVDraggingView (rv));
+       }
+}
+
+void
+VideoTimeLineDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
+{
+       Drag::start_grab (event);
+       if (_editor->session() == 0) {
+               return;
+       }
+
+       _startdrag_video_offset=ARDOUR_UI::instance()->video_timeline->get_offset();
+       _max_backwards_drag = (
+                         ARDOUR_UI::instance()->video_timeline->get_duration()
+                       + ARDOUR_UI::instance()->video_timeline->get_offset()
+                       - ceil(ARDOUR_UI::instance()->video_timeline->get_apv())
+                       );
+
+       for (list<AVDraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
+               if (i->initial_position < _max_backwards_drag || _max_backwards_drag < 0) {
+                       _max_backwards_drag = ARDOUR_UI::instance()->video_timeline->quantify_frames_to_apv (i->initial_position);
+               }
+       }
+       DEBUG_TRACE (DEBUG::Drags, string_compose("VideoTimeLineDrag: max backwards-drag: %1\n", _max_backwards_drag));
+
+       char buf[128];
+       Timecode::Time timecode;
+       _editor->session()->sample_to_timecode(abs(_startdrag_video_offset), timecode, true /* use_offset */, false /* use_subframes */ );
+       snprintf (buf, sizeof (buf), "Video Start:\n%c%02" PRId32 ":%02" PRId32 ":%02" PRId32 ":%02" PRId32, (_startdrag_video_offset<0?'-':' '), timecode.hours, timecode.minutes, timecode.seconds, timecode.frames);
+       _editor->verbose_cursor()->set(buf, event->button.x + 10, event->button.y + 10);
+       _editor->verbose_cursor()->show ();
+}
+
+void
+VideoTimeLineDrag::motion (GdkEvent* event, bool first_move)
+{
+       if (_editor->session() == 0) {
+               return;
+       }
+       if (ARDOUR_UI::instance()->video_timeline->is_offset_locked()) {
+               return;
+       }
+
+       framecnt_t dt = adjusted_current_frame (event) - raw_grab_frame() + _pointer_frame_offset;
+       dt = ARDOUR_UI::instance()->video_timeline->quantify_frames_to_apv(dt);
+
+       if (_max_backwards_drag >= 0 && dt <= - _max_backwards_drag) {
+               dt = - _max_backwards_drag;
+       }
+
+       ARDOUR_UI::instance()->video_timeline->set_offset(_startdrag_video_offset+dt);
+       ARDOUR_UI::instance()->flush_videotimeline_cache(true);
+
+       for (list<AVDraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
+               RegionView* rv = i->view;
+               DEBUG_TRACE (DEBUG::Drags, string_compose("SHIFT REGION at %1 by %2\n", i->initial_position, dt));
+               if (first_move) {
+                       rv->drag_start ();
+                       rv->fake_set_opaque (true);
+                       rv->region()->clear_changes ();
+                       rv->region()->suspend_property_changes();
+               }
+               rv->region()->set_position(i->initial_position + dt);
+               rv->region_changed(ARDOUR::Properties::position);
+       }
+
+       const framepos_t offset = ARDOUR_UI::instance()->video_timeline->get_offset();
+       Timecode::Time timecode;
+       Timecode::Time timediff;
+       char buf[128];
+       _editor->session()->sample_to_timecode(abs(offset), timecode, true /* use_offset */, false /* use_subframes */ );
+       _editor->session()->sample_to_timecode(abs(dt), timediff, false /* use_offset */, false /* use_subframes */ );
+       snprintf (buf, sizeof (buf),
+                       "%s\n%c%02" PRId32 ":%02" PRId32 ":%02" PRId32 ":%02" PRId32
+                       "\n%s\n%c%02" PRId32 ":%02" PRId32 ":%02" PRId32 ":%02" PRId32
+                       , _("Video Start:"),
+                               (offset<0?'-':' '), timecode.hours, timecode.minutes, timecode.seconds, timecode.frames
+                       , _("Diff:"),
+                               (dt<0?'-':' '), timediff.hours, timediff.minutes, timediff.seconds, timediff.frames
+                               );
+       _editor->verbose_cursor()->set(buf, event->button.x + 10, event->button.y + 10);
+       _editor->verbose_cursor()->show ();
+}
+
+void
+VideoTimeLineDrag::finished (GdkEvent * /*event*/, bool movement_occurred)
+{
+       if (ARDOUR_UI::instance()->video_timeline->is_offset_locked()) {
+               return;
+       }
+
+       if (!movement_occurred || ! _editor->session()) {
+               return;
+       }
+
+       ARDOUR_UI::instance()->flush_videotimeline_cache(true);
+
+       _editor->begin_reversible_command (_("Move Video"));
+
+       XMLNode &before = ARDOUR_UI::instance()->video_timeline->get_state();
+       ARDOUR_UI::instance()->video_timeline->save_undo();
+       XMLNode &after = ARDOUR_UI::instance()->video_timeline->get_state();
+       _editor->session()->add_command(new MementoCommand<VideoTimeLine>(*(ARDOUR_UI::instance()->video_timeline), &before, &after));
+
+       for (list<AVDraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
+               i->view->drag_end();
+               i->view->fake_set_opaque (false);
+               i->view->region()->resume_property_changes ();
+
+               _editor->session()->add_command (new StatefulDiffCommand (i->view->region()));
+       }
+
+       _editor->session()->maybe_update_session_range(
+                       std::max(ARDOUR_UI::instance()->video_timeline->get_offset(), (ARDOUR::frameoffset_t) 0),
+                       std::max(ARDOUR_UI::instance()->video_timeline->get_offset() + ARDOUR_UI::instance()->video_timeline->get_duration(), (ARDOUR::frameoffset_t) 0)
+                       );
+
+
+       _editor->commit_reversible_command ();
+}
+
+void
+VideoTimeLineDrag::aborted (bool)
+{
+       if (ARDOUR_UI::instance()->video_timeline->is_offset_locked()) {
+               return;
+       }
+       ARDOUR_UI::instance()->video_timeline->set_offset(_startdrag_video_offset);
+       ARDOUR_UI::instance()->flush_videotimeline_cache(true);
+
+       for (list<AVDraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
+               i->view->region()->resume_property_changes ();
+               i->view->region()->set_position(i->initial_position);
+       }
+}
+
 TrimDrag::TrimDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool preserve_fade_anchor)
        : RegionDrag (e, i, p, v)
 {
@@ -1667,6 +1830,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
        TimeAxisView* tvp = &_primary->get_time_axis_view ();
        RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
        pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
+       frameoffset_t frame_delta = 0;
 
        if (tv && tv->is_track()) {
                speed = tv->track()->speed();
@@ -1733,7 +1897,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
                                        boost::shared_ptr<AudioRegion> ar (arv->audio_region());
                                        distance = _drags->current_pointer_x() - grab_x();
                                        len = ar->fade_in()->back()->when;
-                                       new_length = len - _editor->unit_to_frame (distance);
+                                       new_length = len - _editor->pixel_to_sample (distance);
                                        new_length = ar->verify_xfade_bounds (new_length, true  /*START*/ );
                                        arv->reset_fade_in_shape_width (ar, new_length);  //the grey shape
                                }
@@ -1753,7 +1917,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
                                        boost::shared_ptr<AudioRegion> ar (arv->audio_region());
                                        distance = grab_x() - _drags->current_pointer_x();
                                        len = ar->fade_out()->back()->when;
-                                       new_length = len - _editor->unit_to_frame (distance);
+                                       new_length = len - _editor->pixel_to_sample (distance);
                                        new_length = ar->verify_xfade_bounds (new_length, false  /*END*/ );
                                        arv->reset_fade_out_shape_width (ar, new_length);  //the grey shape
                                }
@@ -1763,27 +1927,11 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
 
        case ContentsTrim:
                {
-                       bool swap_direction = false;
-
-                       if (event && Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
-                               swap_direction = true;
-                       }
-
-                       framecnt_t frame_delta = 0;
-
-                       bool left_direction = false;
-                       if (last_pointer_frame() > adjusted_current_frame(event)) {
-                               left_direction = true;
-                       }
-
-                       if (left_direction) {
-                               frame_delta = (last_pointer_frame() - adjusted_current_frame(event));
-                       } else {
-                               frame_delta = (adjusted_current_frame(event) - last_pointer_frame());
-                       }
+                       frame_delta = (adjusted_current_frame(event) - last_pointer_frame());
+                       // frame_delta = (last_pointer_frame() - adjusted_current_frame(event));
 
                        for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
-                               i->view->trim_contents (frame_delta, left_direction, swap_direction);
+                               i->view->move_contents (frame_delta);
                        }
                }
                break;
@@ -1797,7 +1945,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
                show_verbose_cursor_time ((framepos_t) (rv->region()->last_frame() / speed));
                break;
        case ContentsTrim:
-               show_verbose_cursor_time (adjusted_current_frame (event));
+               // show_verbose_cursor_time (frame_delta);
                break;
        }
 }
@@ -1827,7 +1975,7 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred)
                                                boost::shared_ptr<AudioRegion> ar (arv->audio_region());
                                                distance = _drags->current_pointer_x() - grab_x();
                                                len = ar->fade_in()->back()->when;
-                                               new_length = len - _editor->unit_to_frame (distance);
+                                               new_length = len - _editor->pixel_to_sample (distance);
                                                new_length = ar->verify_xfade_bounds (new_length, true  /*START*/ );
                                                ar->set_fade_in_length(new_length);
                                        }
@@ -1844,7 +1992,7 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred)
                                                boost::shared_ptr<AudioRegion> ar (arv->audio_region());
                                                distance = _drags->current_pointer_x() - grab_x();
                                                len = ar->fade_out()->back()->when;
-                                               new_length = len - _editor->unit_to_frame (distance);
+                                               new_length = len - _editor->pixel_to_sample (distance);
                                                new_length = ar->verify_xfade_bounds (new_length, false  /*END*/ );
                                                ar->set_fade_out_length(new_length);
                                        }
@@ -1998,7 +2146,7 @@ MeterMarkerDrag::motion (GdkEvent* event, bool first_move)
                _marker = new MeterMarker (
                        *_editor,
                        *_editor->meter_group,
-                       ARDOUR_UI::config()->canvasvar_MeterMarker.get(),
+                       ARDOUR_UI::config()->get_canvasvar_MeterMarker(),
                        name,
                        *new MeterSection (_marker->meter())
                );
@@ -2117,7 +2265,7 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move)
                _marker = new TempoMarker (
                        *_editor,
                        *_editor->tempo_group,
-                       ARDOUR_UI::config()->canvasvar_TempoMarker.get(),
+                       ARDOUR_UI::config()->get_canvasvar_TempoMarker(),
                        name,
                        *new TempoSection (_marker->tempo())
                        );
@@ -2190,9 +2338,10 @@ TempoMarkerDrag::aborted (bool moved)
        }
 }
 
-CursorDrag::CursorDrag (Editor* e, ArdourCanvas::Item* i, bool s)
-       : Drag (e, i),
-         _stop (s)
+CursorDrag::CursorDrag (Editor* e, EditorCursor& c, bool s)
+       : Drag (e, &c.time_bar_canvas_item())
+       , _cursor (c)
+       , _stop (s)
 {
        DEBUG_TRACE (DEBUG::Drags, "New CursorDrag\n");
 }
@@ -2208,7 +2357,7 @@ CursorDrag::fake_locate (framepos_t t)
 
        Session* s = _editor->session ();
        if (s->timecode_transmission_suspended ()) {
-               framepos_t const f = _editor->playhead_cursor->current_frame;
+               framepos_t const f = _editor->playhead_cursor->current_frame ();
                s->send_mmc_locate (f);
                s->send_full_time_code (f);
        }
@@ -2222,15 +2371,20 @@ CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
 {
        Drag::start_grab (event, c);
 
-       _grab_zoom = _editor->frames_per_unit;
+       _grab_zoom = _editor->samples_per_pixel;
+
+       framepos_t where = _editor->canvas_event_frame (event, 0, 0);
 
-       framepos_t where = _editor->event_frame (event, 0, 0);
        _editor->snap_to_with_modifier (where, event);
 
        _editor->_dragging_playhead = true;
 
        Session* s = _editor->session ();
 
+       /* grab the track canvas item as well */
+
+       _cursor.track_canvas_item().grab();
+
        if (s) {
                if (_was_rolling && _stop) {
                        s->request_stop ();
@@ -2266,9 +2420,6 @@ CursorDrag::motion (GdkEvent* event, bool)
        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 ();
-#endif
        }
 }
 
@@ -2277,6 +2428,8 @@ CursorDrag::finished (GdkEvent* event, bool movement_occurred)
 {
        _editor->_dragging_playhead = false;
 
+       _cursor.track_canvas_item().ungrab();
+
        if (!movement_occurred && _stop) {
                return;
        }
@@ -2285,7 +2438,7 @@ CursorDrag::finished (GdkEvent* event, bool movement_occurred)
 
        Session* s = _editor->session ();
        if (s) {
-               s->request_locate (_editor->playhead_cursor->current_frame, _was_rolling);
+               s->request_locate (_editor->playhead_cursor->current_frame (), _was_rolling);
                _editor->_pending_locate_request = true;
                s->request_resume_timecode_transmission ();
        }
@@ -2294,6 +2447,8 @@ CursorDrag::finished (GdkEvent* event, bool movement_occurred)
 void
 CursorDrag::aborted (bool)
 {
+       _cursor.track_canvas_item().ungrab();
+
        if (_editor->_dragging_playhead) {
                _editor->session()->request_resume_timecode_transmission ();
                _editor->_dragging_playhead = false;
@@ -2542,8 +2697,8 @@ MarkerDrag::MarkerDrag (Editor* e, ArdourCanvas::Item* i)
        _marker = reinterpret_cast<Marker*> (_item->get_data ("marker"));
        assert (_marker);
 
-       _points.push_back (Gnome::Art::Point (0, 0));
-       _points.push_back (Gnome::Art::Point (0, physical_screen_height (_editor->get_window())));
+       _points.push_back (ArdourCanvas::Duple (0, 0));
+       _points.push_back (ArdourCanvas::Duple (0, physical_screen_height (_editor->get_window())));
 }
 
 MarkerDrag::~MarkerDrag ()
@@ -2813,10 +2968,6 @@ MarkerDrag::motion (GdkEvent* event, bool)
        assert (!_copied_locations.empty());
 
        show_verbose_cursor_time (newframe);
-
-#ifdef GTKOSX
-       _editor->update_canvas_now ();
-#endif
 }
 
 void
@@ -2977,7 +3128,7 @@ ControlPointDrag::motion (GdkEvent* event, bool)
        cy = max (0.0, cy);
        cy = min ((double) _point->line().height(), cy);
 
-       framepos_t cx_frames = _editor->unit_to_frame (cx);
+       framepos_t cx_frames = _editor->pixel_to_sample (cx);
 
        if (!_x_constrained) {
                _editor->snap_to_with_modifier (cx_frames, event);
@@ -2987,7 +3138,7 @@ ControlPointDrag::motion (GdkEvent* event, bool)
 
        float const fraction = 1.0 - (cy / _point->line().height());
 
-       _point->line().drag_motion (_editor->frame_to_unit_unrounded (cx_frames), fraction, false, _pushing, _final_index);
+       _point->line().drag_motion (_editor->sample_to_pixel_unrounded (cx_frames), fraction, false, _pushing, _final_index);
 
        _editor->verbose_cursor()->set_text (_point->line().get_verbose_cursor_string (fraction));
 }
@@ -3052,9 +3203,9 @@ LineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
        double cx = event->button.x;
        double cy = event->button.y;
 
-       _line->parent_group().w2i (cx, cy);
+       _line->parent_group().canvas_to_item (cx, cy);
 
-       framecnt_t const frame_within_region = (framecnt_t) floor (cx * _editor->frames_per_unit);
+       framecnt_t const frame_within_region = (framecnt_t) floor (cx * _editor->samples_per_pixel);
 
        uint32_t before;
        uint32_t after;
@@ -3141,7 +3292,7 @@ FeatureLineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
        double cx = event->button.x;
        double cy = event->button.y;
 
-       _item->property_parent().get_value()->w2i(cx, cy);
+       _item->parent()->canvas_to_item (cx, cy);
 
        /* store grab start in parent frame */
        _region_view_grab_x = cx;
@@ -3150,7 +3301,7 @@ FeatureLineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
 
        _arv = reinterpret_cast<AudioRegionView*> (_item->get_data ("regionview"));
 
-       _max_x = _editor->frame_to_pixel(_arv->get_duration());
+       _max_x = _editor->sample_to_pixel(_arv->get_duration());
 }
 
 void
@@ -3171,16 +3322,9 @@ FeatureLineDrag::motion (GdkEvent*, bool)
                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;
+       boost::optional<ArdourCanvas::Rect> bbox = _line->bounding_box ();
+       assert (bbox);
+       _line->set (ArdourCanvas::Duple (cx, 2.0), ArdourCanvas::Duple (cx, bbox.get().height ()));
 
        float *pos = new float;
        *pos = cx;
@@ -3253,20 +3397,20 @@ RubberbandSelectDrag::motion (GdkEvent* event, bool)
 
        if (start != end || y1 != y2) {
 
-               double x1 = _editor->frame_to_pixel (start);
-               double x2 = _editor->frame_to_pixel (end);
+               double x1 = _editor->sample_to_pixel (start);
+               double x2 = _editor->sample_to_pixel (end);
 
-               _editor->rubberband_rect->property_x1() = x1;
+               _editor->rubberband_rect->set_x0 (x1);
                if (_vertical_only) {
                        /* fixed 10 pixel width */
-                       _editor->rubberband_rect->property_x2() = x1 + 10;
+                       _editor->rubberband_rect->set_x1 (x1 + 10);
                } else {
-                       _editor->rubberband_rect->property_x2() = x2;
+                       _editor->rubberband_rect->set_x1 (x2);
                } 
 
-               _editor->rubberband_rect->property_y1() = y1;
-               _editor->rubberband_rect->property_y2() = y2;
-
+               _editor->rubberband_rect->set_y0 (y1);
+               _editor->rubberband_rect->set_y1 (y2);
+               
                _editor->rubberband_rect->show();
                _editor->rubberband_rect->raise_to_top();
 
@@ -3691,7 +3835,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
                break;
        }
 
-       if (event->button.x >= _editor->horizontal_position() + _editor->_canvas_width) {
+       if (event->button.x >= _editor->horizontal_position() + _editor->_visible_canvas_width) {
                _editor->start_canvas_autoscroll (1, 0);
        }
 
@@ -3787,12 +3931,13 @@ RangeMarkerBarDrag::RangeMarkerBarDrag (Editor* e, ArdourCanvas::Item* i, Operat
 {
        DEBUG_TRACE (DEBUG::Drags, "New RangeMarkerBarDrag\n");
 
-       _drag_rect = new ArdourCanvas::SimpleRect (*_editor->time_line_group, 0.0, 0.0, 0.0,
-                                                  physical_screen_height (_editor->get_window()));
+       _drag_rect = new ArdourCanvas::Rectangle (_editor->time_line_group, 
+                                                 ArdourCanvas::Rect (0.0, 0.0, 0.0,
+                                                                     physical_screen_height (_editor->get_window())));
        _drag_rect->hide ();
 
-       _drag_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_RangeDragRect.get();
-       _drag_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_RangeDragRect.get();
+       _drag_rect->set_fill_color (ARDOUR_UI::config()->get_canvasvar_RangeDragRect());
+       _drag_rect->set_outline_color (ARDOUR_UI::config()->get_canvasvar_RangeDragRect());
 }
 
 void
@@ -3832,7 +3977,7 @@ RangeMarkerBarDrag::motion (GdkEvent* event, bool first_move)
 {
        framepos_t start = 0;
        framepos_t end = 0;
-       ArdourCanvas::SimpleRect *crect;
+       ArdourCanvas::Rectangle *crect;
 
        switch (_operation) {
        case CreateRangeMarker:
@@ -3881,17 +4026,17 @@ RangeMarkerBarDrag::motion (GdkEvent* event, bool first_move)
                }
        }
 
-       if (event->button.x >= _editor->horizontal_position() + _editor->_canvas_width) {
+       if (event->button.x >= _editor->horizontal_position() + _editor->_visible_canvas_width) {
                _editor->start_canvas_autoscroll (1, 0);
        }
 
        if (start != end) {
                _editor->temp_location->set (start, end);
 
-               double x1 = _editor->frame_to_pixel (start);
-               double x2 = _editor->frame_to_pixel (end);
-               crect->property_x1() = x1;
-               crect->property_x2() = x2;
+               double x1 = _editor->sample_to_pixel (start);
+               double x2 = _editor->sample_to_pixel (end);
+               crect->set_x0 (x1);
+               crect->set_x1 (x2);
 
                update_item (_editor->temp_location);
        }
@@ -3989,11 +4134,11 @@ RangeMarkerBarDrag::aborted (bool)
 void
 RangeMarkerBarDrag::update_item (Location* location)
 {
-       double const x1 = _editor->frame_to_pixel (location->start());
-       double const x2 = _editor->frame_to_pixel (location->end());
+       double const x1 = _editor->sample_to_pixel (location->start());
+       double const x2 = _editor->sample_to_pixel (location->end());
 
-       _drag_rect->property_x1() = x1;
-       _drag_rect->property_x2() = x2;
+       _drag_rect->set_x0 (x1);
+       _drag_rect->set_x1 (x2);
 }
 
 MouseZoomDrag::MouseZoomDrag (Editor* e, ArdourCanvas::Item* i)
@@ -4085,7 +4230,8 @@ NoteDrag::NoteDrag (Editor* e, ArdourCanvas::Item* i)
 {
        DEBUG_TRACE (DEBUG::Drags, "New NoteDrag\n");
 
-       _primary = dynamic_cast<CanvasNoteEvent*> (_item);
+       _primary = reinterpret_cast<NoteBase*> (_item->get_data ("notebase"));
+       assert (_primary);
        _region = &_primary->region_view ();
        _note_height = _region->midi_stream_view()->note_height ();
 }
@@ -4121,7 +4267,7 @@ frameoffset_t
 NoteDrag::total_dx () const
 {
        /* dx in frames */
-       frameoffset_t const dx = _editor->unit_to_frame (_drags->current_pointer_x() - grab_x());
+       frameoffset_t const dx = _editor->pixel_to_sample (_drags->current_pointer_x() - grab_x());
 
        /* primary note time */
        frameoffset_t const n = _region->source_beats_to_absolute_frames (_primary->note()->time ());
@@ -4161,7 +4307,7 @@ NoteDrag::motion (GdkEvent *, bool)
        int8_t const dy = total_dy ();
 
        /* Now work out what we have to do to the note canvas items to set this new drag delta */
-       double const tdx = _editor->frame_to_unit (dx) - _cumulative_dx;
+       double const tdx = _editor->sample_to_pixel (dx) - _cumulative_dx;
        double const tdy = -dy * _note_height - _cumulative_dy;
 
        if (tdx || tdy) {
@@ -4457,14 +4603,14 @@ DraggingView::DraggingView (RegionView* v, RegionDrag* parent)
 {
        time_axis_view = parent->find_time_axis_view (&v->get_time_axis_view ());
        layer = v->region()->layer ();
-       initial_y = v->get_canvas_group()->property_y ();
+       initial_y = v->get_canvas_group()->position().y;
        initial_playlist = v->region()->playlist ();
        initial_position = v->region()->position ();
        initial_end = v->region()->position () + v->region()->length ();
 }
 
-PatchChangeDrag::PatchChangeDrag (Editor* e, CanvasPatchChange* i, MidiRegionView* r)
-       : Drag (e, i)
+PatchChangeDrag::PatchChangeDrag (Editor* e, PatchChange* i, MidiRegionView* r)
+       : Drag (e, i->canvas_item ())
        , _region_view (r)
        , _patch_change (i)
        , _cumulative_dx (0)
@@ -4483,8 +4629,8 @@ PatchChangeDrag::motion (GdkEvent* ev, bool)
        f = min (f, r->last_frame ());
 
        framecnt_t const dxf = f - grab_frame(); // permitted dx in frames
-       double const dxu = _editor->frame_to_unit (dxf); // permitted fx in units
-       _patch_change->move (dxu - _cumulative_dx, 0);
+       double const dxu = _editor->sample_to_pixel (dxf); // permitted fx in units
+       _patch_change->move (ArdourCanvas::Duple (dxu - _cumulative_dx, 0));
        _cumulative_dx = dxu;
 }
 
@@ -4509,7 +4655,7 @@ PatchChangeDrag::finished (GdkEvent* ev, bool movement_occurred)
 void
 PatchChangeDrag::aborted (bool)
 {
-       _patch_change->move (-_cumulative_dx, 0);
+       _patch_change->move (ArdourCanvas::Duple (-_cumulative_dx, 0));
 }
 
 void
@@ -4520,7 +4666,7 @@ PatchChangeDrag::setup_pointer_frame_offset ()
 }
 
 MidiRubberbandSelectDrag::MidiRubberbandSelectDrag (Editor* e, MidiRegionView* rv)
-       : RubberbandSelectDrag (e, rv->get_canvas_frame ())
+       : RubberbandSelectDrag (e, rv->get_canvas_group ())
        , _region_view (rv)
 {
 
@@ -4538,8 +4684,8 @@ MidiRubberbandSelectDrag::select_things (int button_state, framepos_t x1, framep
        y2 = max (0.0, y2 - y);
        
        _region_view->update_drag_selection (
-               _editor->frame_to_pixel (x1),
-               _editor->frame_to_pixel (x2),
+               _editor->sample_to_pixel (x1),
+               _editor->sample_to_pixel (x2),
                y1,
                y2,
                Keyboard::modifier_state_contains (button_state, Keyboard::TertiaryModifier)
@@ -4553,7 +4699,7 @@ MidiRubberbandSelectDrag::deselect_things ()
 }
 
 MidiVerticalSelectDrag::MidiVerticalSelectDrag (Editor* e, MidiRegionView* rv)
-       : RubberbandSelectDrag (e, rv->get_canvas_frame ())
+       : RubberbandSelectDrag (e, rv->get_canvas_group ())
        , _region_view (rv)
 {
        _vertical_only = true;
@@ -4642,7 +4788,7 @@ NoteCreateDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
 {
        Drag::start_grab (event, cursor);
                                                 
-       _drag_rect = new ArdourCanvas::SimpleRect (*_region_view->get_canvas_group ());
+       _drag_rect = new ArdourCanvas::Rectangle (_region_view->get_canvas_group ());
 
        framepos_t pf = _drags->current_pointer_frame ();
        framecnt_t const g = grid_frames (pf);
@@ -4657,28 +4803,24 @@ NoteCreateDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
        _note[0] = adjusted_frame (pf, event) - _region_view->region()->position ();
 
        MidiStreamView* sv = _region_view->midi_stream_view ();
-       double const x = _editor->frame_to_pixel (_note[0]);
+       double const x = _editor->sample_to_pixel (_note[0]);
        double const y = sv->note_to_y (sv->y_to_note (y_to_region (event->button.y)));
 
-       _drag_rect->property_x1() = x;
-       _drag_rect->property_y1() = y;
-       _drag_rect->property_x2() = x;
-       _drag_rect->property_y2() = y + floor (_region_view->midi_stream_view()->note_height ());
-
-       _drag_rect->property_outline_what() = 0xff;
-       _drag_rect->property_outline_color_rgba() = 0xffffff99;
-       _drag_rect->property_fill_color_rgba()    = 0xffffff66;
+       _drag_rect->set (ArdourCanvas::Rect (x, y, x, y + floor (_region_view->midi_stream_view()->note_height ())));
+       _drag_rect->set_outline_what (0xff);
+       _drag_rect->set_outline_color (0xffffff99);
+       _drag_rect->set_fill_color (0xffffff66);
 }
 
 void
 NoteCreateDrag::motion (GdkEvent* event, bool)
 {
        _note[1] = max ((framepos_t)0, adjusted_current_frame (event) - _region_view->region()->position ());
-       double const x = _editor->frame_to_pixel (_note[1]);
+       double const x = _editor->sample_to_pixel (_note[1]);
        if (_note[1] > _note[0]) {
-               _drag_rect->property_x2() = x;
+               _drag_rect->set_x1 (x);
        } else {
-               _drag_rect->property_x1() = x;
+               _drag_rect->set_x0 (x);
        }
 }
 
@@ -4701,14 +4843,14 @@ NoteCreateDrag::finished (GdkEvent*, bool had_movement)
 
        double const length_beats = max (one_tick, _region_view->region_frames_to_region_beats (length));
 
-       _region_view->create_note_at (start, _drag_rect->property_y1(), length_beats, false);
+       _region_view->create_note_at (start, _drag_rect->y0(), length_beats, false);
 }
 
 double
 NoteCreateDrag::y_to_region (double y) const
 {
        double x = 0;
-       _region_view->get_canvas_group()->w2i (x, y);
+       _region_view->get_canvas_group()->canvas_to_item (x, y);
        return y;
 }
 
@@ -4751,16 +4893,16 @@ CrossfadeEdgeDrag::motion (GdkEvent*, bool)
 
        /* how long should it be ? */
 
-       new_length = len + _editor->unit_to_frame (distance);
+       new_length = len + _editor->pixel_to_sample (distance);
 
        /* now check with the region that this is legal */
 
        new_length = ar->verify_xfade_bounds (new_length, start);
 
        if (start) {
-               arv->redraw_start_xfade_to (ar, new_length);
+               arv->reset_fade_in_shape_width (ar, new_length);
        } else {
-               arv->redraw_end_xfade_to (ar, new_length);
+               arv->reset_fade_out_shape_width (ar, new_length);
        }
 }
 
@@ -4781,7 +4923,7 @@ CrossfadeEdgeDrag::finished (GdkEvent*, bool)
                len = ar->fade_out()->back()->when;
        }
 
-       new_length = ar->verify_xfade_bounds (len + _editor->unit_to_frame (distance), start);
+       new_length = ar->verify_xfade_bounds (len + _editor->pixel_to_sample (distance), start);
        
        _editor->begin_reversible_command ("xfade trim");
        ar->playlist()->clear_owned_changes ();