display active peak-builds
[ardour.git] / gtk2_ardour / editor_drag.cc
index 00811f6eea72bedaa88648e5e2e9fcd8a931b816..726a279a7e26fe2bfd95a57f1c1de8bb7a46590f 100644 (file)
@@ -96,8 +96,6 @@ DragManager::abort ()
 {
        _ending = true;
 
-       cerr << "Aborting drag\n";
-
        for (list<Drag*>::const_iterator i = _drags.begin(); i != _drags.end(); ++i) {
                (*i)->abort ();
                delete *i;
@@ -339,10 +337,10 @@ frameoffset_t
 Drag::snap_delta (guint state) const
 {
        if (ArdourKeyboard::indicates_snap_delta (state)) {
-               return 0;
+               return _snap_delta;
        }
 
-       return _snap_delta;
+       return 0;
 }
 
 double
@@ -595,6 +593,7 @@ RegionDrag::find_time_axis_view (TimeAxisView* t) const
 RegionMotionDrag::RegionMotionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool b)
        : RegionDrag (e, i, p, v)
        , _brushing (b)
+       , _ignore_video_lock (false)
        , _total_x_delta (0)
        , _last_pointer_time_axis_view (0)
        , _last_pointer_layer (0)
@@ -619,6 +618,15 @@ RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
                assert(_last_pointer_time_axis_view >= 0);
                _last_pointer_layer = tv.first->layer_display() == Overlaid ? 0 : tv.second;
        }
+
+       if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask (Keyboard::TertiaryModifier))) {
+               _ignore_video_lock = true;
+       }
+
+       if (_brushing) {
+               /* cross track dragging seems broken here. disabled for now. */
+               _y_constrained = true;
+       }
 }
 
 double
@@ -1005,7 +1013,7 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
 
                y_delta = 0;
 
-               if (rv->region()->locked() || rv->region()->video_locked()) {
+               if (rv->region()->locked() || (rv->region()->video_locked() && !_ignore_video_lock)) {
                        continue;
                }
 
@@ -1223,13 +1231,13 @@ void
 RegionMoveDrag::motion (GdkEvent* event, bool first_move)
 {
        if (_copy && first_move) {
-
-               if (_x_constrained) {
+               if (_x_constrained && !_brushing) {
                        _editor->begin_reversible_command (Operations::fixed_time_region_copy);
-               } else {
+               } else if (!_brushing) {
                        _editor->begin_reversible_command (Operations::region_copy);
+               } else if (_brushing) {
+                       _editor->begin_reversible_command (Operations::drag_region_brush);
                }
-
                /* duplicate the regionview(s) and region(s) */
 
                list<DraggingView> new_regionviews;
@@ -1287,14 +1295,14 @@ RegionMoveDrag::motion (GdkEvent* event, bool first_move)
                }
 
        } else if (!_copy && first_move) {
-
-               if (_x_constrained) {
+               if (_x_constrained && !_brushing) {
                        _editor->begin_reversible_command (_("fixed time region drag"));
-               } else {
+               } else if (!_brushing) {
                        _editor->begin_reversible_command (Operations::region_drag);
+               } else if (_brushing) {
+                       _editor->begin_reversible_command (Operations::drag_region_brush);
                }
        }
-
        RegionMotionDrag::motion (event, first_move);
 }
 
@@ -1427,7 +1435,7 @@ RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed
 
                RouteTimeAxisView* dest_rtv = 0;
 
-               if (i->view->region()->locked() || i->view->region()->video_locked()) {
+               if (i->view->region()->locked() || (i->view->region()->video_locked() && !_ignore_video_lock)) {
                        continue;
                }
 
@@ -1502,12 +1510,6 @@ RegionMoveDrag::finished_no_copy (
        set<RouteTimeAxisView*> views_to_update;
        RouteTimeAxisView* new_time_axis_view = 0;
 
-       if (_brushing) {
-               /* all changes were made during motion event handlers */
-               _editor->commit_reversible_command ();
-               return;
-       }
-
        typedef map<boost::shared_ptr<Playlist>, RouteTimeAxisView*> PlaylistMapping;
        PlaylistMapping playlist_mapping;
 
@@ -1516,7 +1518,7 @@ RegionMoveDrag::finished_no_copy (
                RegionView* rv = i->view;
                RouteTimeAxisView* dest_rtv = 0;
 
-               if (rv->region()->locked() || rv->region()->video_locked()) {
+               if (rv->region()->locked() || (rv->region()->video_locked() && !_ignore_video_lock)) {
                        ++i;
                        continue;
                }
@@ -1621,7 +1623,6 @@ RegionMoveDrag::finished_no_copy (
                        }
 
                        rv->region()->set_position (where);
-
                        _editor->session()->add_command (new StatefulDiffCommand (rv->region()));
                }
 
@@ -1670,7 +1671,7 @@ RegionMoveDrag::finished_no_copy (
 
        /* write commands for the accumulated diffs for all our modified playlists */
        add_stateful_diff_commands_for_playlists (modified_playlists);
-
+       /* applies to _brushing */
        _editor->commit_reversible_command ();
 
        /* We have futzed with the layering of canvas items on our streamviews.
@@ -2336,6 +2337,8 @@ RegionCreateDrag::aborted (bool)
 NoteResizeDrag::NoteResizeDrag (Editor* e, ArdourCanvas::Item* i)
        : Drag (e, i)
        , region (0)
+       , relative (false)
+       , at_front (true)
        , _snap_delta (0)
 {
        DEBUG_TRACE (DEBUG::Drags, "New NoteResizeDrag\n");
@@ -2372,37 +2375,36 @@ NoteResizeDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*ignored*/)
        } else {
                relative = true;
        }
-
        MidiRegionSelection& ms (_editor->get_selection().midi_regions);
-
        if (ms.size() > 1) {
                /* has to be relative, may make no sense otherwise */
                relative = true;
        }
-
        /* select this note; if it is already selected, preserve the existing selection,
           otherwise make this note the only one selected.
        */
        region->note_selected (cnote, cnote->selected ());
-
-       _editor->begin_reversible_command (_("resize notes"));
-
-       for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ) {
-               MidiRegionSelection::iterator next;
-               next = r;
-               ++next;
-               MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(*r);
-               if (mrv) {
-                       mrv->begin_resizing (at_front);
-               }
-               r = next;
-       }
 }
 
 void
-NoteResizeDrag::motion (GdkEvent* event, bool /*first_move*/)
+NoteResizeDrag::motion (GdkEvent* event, bool first_move)
 {
        MidiRegionSelection& ms (_editor->get_selection().midi_regions);
+       if (first_move) {
+               _editor->begin_reversible_command (_("resize notes"));
+
+               for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ) {
+                       MidiRegionSelection::iterator next;
+                       next = r;
+                       ++next;
+                       MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(*r);
+                       if (mrv) {
+                               mrv->begin_resizing (at_front);
+                       }
+                       r = next;
+               }
+       }
+
        for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) {
                NoteBase* nb = reinterpret_cast<NoteBase*> (_item->get_data ("notebase"));
                assert (nb);
@@ -2410,7 +2412,7 @@ NoteResizeDrag::motion (GdkEvent* event, bool /*first_move*/)
                if (mrv) {
                        double sd = 0.0;
                        bool snap = true;
-                       bool apply_snap_delta = !ArdourKeyboard::indicates_snap_delta (event->button.state);
+                       bool apply_snap_delta = ArdourKeyboard::indicates_snap_delta (event->button.state);
 
                        if (ArdourKeyboard::indicates_snap (event->button.state)) {
                                if (_editor->snap_mode () != SnapOff) {
@@ -2420,7 +2422,7 @@ NoteResizeDrag::motion (GdkEvent* event, bool /*first_move*/)
                                if (_editor->snap_mode () == SnapOff) {
                                        snap = false;
                                        /* inverted logic here - we;re in snapoff but we've pressed the snap delta modifier */
-                                       if (!apply_snap_delta) {
+                                       if (apply_snap_delta) {
                                                snap = true;
                                        }
                                }
@@ -2436,8 +2438,12 @@ NoteResizeDrag::motion (GdkEvent* event, bool /*first_move*/)
 }
 
 void
-NoteResizeDrag::finished (GdkEvent* event, bool /*movement_occurred*/)
+NoteResizeDrag::finished (GdkEvent* event, bool movement_occurred)
 {
+       if (!movement_occurred) {
+               return;
+       }
+
        MidiRegionSelection& ms (_editor->get_selection().midi_regions);
        for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) {
                NoteBase* nb = reinterpret_cast<NoteBase*> (_item->get_data ("notebase"));
@@ -2445,7 +2451,7 @@ NoteResizeDrag::finished (GdkEvent* event, bool /*movement_occurred*/)
                MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(*r);
                double sd = 0.0;
                bool snap = true;
-               bool apply_snap_delta = !ArdourKeyboard::indicates_snap_delta (event->button.state);
+               bool apply_snap_delta = ArdourKeyboard::indicates_snap_delta (event->button.state);
                if (mrv) {
                        if (ArdourKeyboard::indicates_snap (event->button.state)) {
                                if (_editor->snap_mode () != SnapOff) {
@@ -2455,14 +2461,16 @@ NoteResizeDrag::finished (GdkEvent* event, bool /*movement_occurred*/)
                                if (_editor->snap_mode () == SnapOff) {
                                        snap = false;
                                        /* inverted logic here - we;re in snapoff but we've pressed the snap delta modifier */
-                                       if (!apply_snap_delta) {
+                                       if (apply_snap_delta) {
                                                snap = true;
                                        }
                                }
                        }
+
                        if (apply_snap_delta) {
                                sd = _snap_delta;
                        }
+
                        mrv->commit_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative, sd, snap);
                }
        }
@@ -2499,11 +2507,15 @@ VideoTimeLineDrag::VideoTimeLineDrag (Editor* e, ArdourCanvas::Item* i)
        _editor->get_regions_after(rs, (framepos_t) 0, empty);
        std::list<RegionView*> views = rs.by_layer();
 
+       _stuck = false;
        for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
                RegionView* rv = (*i);
                if (!rv->region()->video_locked()) {
                        continue;
                }
+               if (rv->region()->locked()) {
+                       _stuck = true;
+               }
                _views.push_back (AVDraggingView (rv));
        }
 }
@@ -2516,6 +2528,16 @@ VideoTimeLineDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
                return;
        }
 
+       if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask (Keyboard::TertiaryModifier))) {
+               _stuck = false;
+               _views.clear();
+       }
+
+       if (_stuck) {
+               show_verbose_cursor_text (_("One or more Audio Regions\nare both Locked and\nLocked to Video.\nThe video cannot me moved."));
+               return;
+       }
+
        _startdrag_video_offset=ARDOUR_UI::instance()->video_timeline->get_offset();
        _max_backwards_drag = (
                          ARDOUR_UI::instance()->video_timeline->get_duration()
@@ -2546,6 +2568,10 @@ VideoTimeLineDrag::motion (GdkEvent* event, bool first_move)
        if (ARDOUR_UI::instance()->video_timeline->is_offset_locked()) {
                return;
        }
+       if (_stuck) {
+               show_verbose_cursor_text (_("One or more Audio Regions\nare both Locked and\nLocked to Video.\nThe video cannot me moved."));
+               return;
+       }
 
        framecnt_t dt = adjusted_current_frame (event) - raw_grab_frame() + _pointer_frame_offset;
        dt = ARDOUR_UI::instance()->video_timeline->quantify_frames_to_apv(_startdrag_video_offset+dt) - _startdrag_video_offset;
@@ -2592,6 +2618,9 @@ VideoTimeLineDrag::finished (GdkEvent * /*event*/, bool movement_occurred)
        if (ARDOUR_UI::instance()->video_timeline->is_offset_locked()) {
                return;
        }
+       if (_stuck) {
+               return;
+       }
 
        if (!movement_occurred || ! _editor->session()) {
                return;
@@ -3288,6 +3317,10 @@ CursorDrag::CursorDrag (Editor* e, EditorCursor& c, bool s)
 void
 CursorDrag::fake_locate (framepos_t t)
 {
+       if (_editor->session () == 0) {
+               return;
+       }
+
        _editor->playhead_cursor->set_position (t);
 
        Session* s = _editor->session ();
@@ -3481,7 +3514,7 @@ FadeInDrag::finished (GdkEvent* event, bool movement_occurred)
                fade_length = pos - region->position();
        }
 
-       _editor->begin_reversible_command (_("change fade in length"));
+       bool in_command = false;
 
        for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
 
@@ -3497,11 +3530,17 @@ FadeInDrag::finished (GdkEvent* event, bool movement_occurred)
                tmp->audio_region()->set_fade_in_length (fade_length);
                tmp->audio_region()->set_fade_in_active (true);
 
+               if (!in_command) {
+                       _editor->begin_reversible_command (_("change fade in length"));
+                       in_command = true;
+               }
                XMLNode &after = alist->get_state();
                _editor->session()->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &after));
        }
 
-       _editor->commit_reversible_command ();
+       if (in_command) {
+               _editor->commit_reversible_command ();
+       }
 }
 
 void
@@ -3600,7 +3639,7 @@ FadeOutDrag::finished (GdkEvent* event, bool movement_occurred)
                fade_length = region->last_frame() - pos;
        }
 
-       _editor->begin_reversible_command (_("change fade out length"));
+       bool in_command = false;
 
        for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
 
@@ -3616,11 +3655,17 @@ FadeOutDrag::finished (GdkEvent* event, bool movement_occurred)
                tmp->audio_region()->set_fade_out_length (fade_length);
                tmp->audio_region()->set_fade_out_active (true);
 
+               if (!in_command) {
+                       _editor->begin_reversible_command (_("change fade out length"));
+                       in_command = true;
+               }
                XMLNode &after = alist->get_state();
                _editor->session()->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &after));
        }
 
-       _editor->commit_reversible_command ();
+       if (in_command) {
+               _editor->commit_reversible_command ();
+       }
 }
 
 void
@@ -3642,7 +3687,7 @@ MarkerDrag::MarkerDrag (Editor* e, ArdourCanvas::Item* i)
 {
        DEBUG_TRACE (DEBUG::Drags, "New MarkerDrag\n");
 
-       _marker = reinterpret_cast<Marker*> (_item->get_data ("marker"));
+       _marker = reinterpret_cast<ArdourMarker*> (_item->get_data ("marker"));
        assert (_marker);
 
        _points.push_back (ArdourCanvas::Duple (0, 0));
@@ -3656,7 +3701,7 @@ MarkerDrag::~MarkerDrag ()
        }
 }
 
-MarkerDrag::CopiedLocationMarkerInfo::CopiedLocationMarkerInfo (Location* l, Marker* m)
+MarkerDrag::CopiedLocationMarkerInfo::CopiedLocationMarkerInfo (Location* l, ArdourMarker* m)
 {
        location = new Location (*l);
        markers.push_back (m);
@@ -3698,7 +3743,7 @@ MarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
        case Selection::Extend:
        {
                Locations::LocationList ll;
-               list<Marker*> to_add;
+               list<ArdourMarker*> to_add;
                framepos_t s, e;
                _editor->selection->markers.range (s, e);
                s = min (_marker->position(), s);
@@ -3813,17 +3858,17 @@ MarkerDrag::motion (GdkEvent* event, bool)
 
 
                                switch (_marker->type()) {
-                               case Marker::SessionStart:
-                               case Marker::RangeStart:
-                               case Marker::LoopStart:
-                               case Marker::PunchIn:
+                               case ArdourMarker::SessionStart:
+                               case ArdourMarker::RangeStart:
+                               case ArdourMarker::LoopStart:
+                               case ArdourMarker::PunchIn:
                                        f_delta = newframe - copy_location->start();
                                        break;
 
-                               case Marker::SessionEnd:
-                               case Marker::RangeEnd:
-                               case Marker::LoopEnd:
-                               case Marker::PunchOut:
+                               case ArdourMarker::SessionEnd:
+                               case ArdourMarker::RangeEnd:
+                               case ArdourMarker::LoopEnd:
+                               case ArdourMarker::PunchOut:
                                        f_delta = newframe - copy_location->end();
                                        break;
                                default:
@@ -3954,8 +3999,8 @@ MarkerDrag::finished (GdkEvent* event, bool movement_occurred)
 
        _editor->_dragging_edit_point = false;
 
-       _editor->begin_reversible_command ( _("move marker") );
        XMLNode &before = _editor->session()->locations()->get_state();
+       bool in_command = false;
 
        MarkerSelection::iterator i;
        CopiedLocationInfo::iterator x;
@@ -3970,9 +4015,12 @@ MarkerDrag::finished (GdkEvent* event, bool movement_occurred)
                if (location) {
 
                        if (location->locked()) {
-                               return;
+                               continue;
+                       }
+                       if (!in_command) {
+                               _editor->begin_reversible_command ( _("move marker") );
+                               in_command = true;
                        }
-
                        if (location->is_mark()) {
                                location->set_start (((*x).location)->start());
                        } else {
@@ -3981,9 +4029,11 @@ MarkerDrag::finished (GdkEvent* event, bool movement_occurred)
                }
        }
 
-       XMLNode &after = _editor->session()->locations()->get_state();
-       _editor->session()->add_command(new MementoCommand<Locations>(*(_editor->session()->locations()), &before, &after));
-       _editor->commit_reversible_command ();
+       if (in_command) {
+               XMLNode &after = _editor->session()->locations()->get_state();
+               _editor->session()->add_command(new MementoCommand<Locations>(*(_editor->session()->locations()), &before, &after));
+               _editor->commit_reversible_command ();
+       }
 }
 
 void
@@ -3998,7 +4048,7 @@ MarkerDrag::aborted (bool movement_occured)
                /* move all markers to their original location */
 
 
-               for (vector<Marker*>::iterator m = x->markers.begin(); m != x->markers.end(); ++m) {
+               for (vector<ArdourMarker*>::iterator m = x->markers.begin(); m != x->markers.end(); ++m) {
 
                        bool is_start;
                        Location * location = _editor->find_location_from_marker (*m, is_start);
@@ -4018,8 +4068,9 @@ MarkerDrag::update_item (Location*)
 
 ControlPointDrag::ControlPointDrag (Editor* e, ArdourCanvas::Item* i)
        : Drag (e, i),
-         _cumulative_x_drag (0),
-         _cumulative_y_drag (0)
+         _cumulative_x_drag (0)
+       , _cumulative_y_drag (0)
+       , _pushing (false)
 {
        if (_zero_gain_fraction < 0.0) {
                _zero_gain_fraction = gain_to_slider_position_with_max (dB_to_coefficient (0.0), Config->get_max_gain());
@@ -4046,9 +4097,6 @@ ControlPointDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
        setup_snap_delta (pos);
 
        float const fraction = 1 - (_point->get_y() / _point->line().height());
-
-       _point->line().start_drag_single (_point, _fixed_grab_x, fraction);
-
        show_verbose_cursor_text (_point->line().get_verbose_cursor_string (fraction));
 
        _pushing = Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::push_points_modifier ());
@@ -4059,7 +4107,7 @@ ControlPointDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
 }
 
 void
-ControlPointDrag::motion (GdkEvent* event, bool)
+ControlPointDrag::motion (GdkEvent* event, bool first_motion)
 {
        double dx = _drags->current_pointer_x() - last_pointer_x();
        double dy = current_pointer_y() - last_pointer_y();
@@ -4078,11 +4126,6 @@ ControlPointDrag::motion (GdkEvent* event, bool)
        // positive side of zero
        double const zero_gain_y = (1.0 - _zero_gain_fraction) * _point->line().height() - .01;
 
-       // make sure we hit zero when passing through
-       if ((cy < zero_gain_y && (cy - dy) > zero_gain_y) || (cy > zero_gain_y && (cy - dy) < zero_gain_y)) {
-               cy = zero_gain_y;
-       }
-
        if (_x_constrained) {
                cx = _fixed_grab_x;
        }
@@ -4093,6 +4136,11 @@ ControlPointDrag::motion (GdkEvent* event, bool)
        _cumulative_x_drag = cx - _fixed_grab_x;
        _cumulative_y_drag = cy - _fixed_grab_y;
 
+       // make sure we hit zero when passing through
+       if ((cy < zero_gain_y && (cy - dy) > zero_gain_y) || (cy > zero_gain_y && (cy - dy) < zero_gain_y)) {
+               cy = zero_gain_y;
+       }
+
        cx = max (0.0, cx);
        cy = max (0.0, cy);
        cy = min ((double) _point->line().height(), cy);
@@ -4108,6 +4156,11 @@ ControlPointDrag::motion (GdkEvent* event, bool)
 
        float const fraction = 1.0 - (cy / _point->line().height());
 
+       if (first_motion) {
+               _editor->begin_reversible_command (_("automation event move"));
+               _point->line().start_drag_single (_point, _fixed_grab_x, fraction);
+       }
+
        _point->line().drag_motion (_editor->sample_to_pixel_unrounded (cx_frames), fraction, false, _pushing, _final_index);
 
        show_verbose_cursor_text (_point->line().get_verbose_cursor_string (fraction));
@@ -4125,10 +4178,9 @@ ControlPointDrag::finished (GdkEvent* event, bool movement_occurred)
 
        } else {
                motion (event, false);
+               _point->line().end_drag (_pushing, _final_index);
+               _editor->commit_reversible_command ();
        }
-
-       _point->line().end_drag (_pushing, _final_index);
-       _editor->commit_reversible_command ();
 }
 
 void
@@ -4153,6 +4205,8 @@ LineDrag::LineDrag (Editor* e, ArdourCanvas::Item* i)
        : Drag (e, i)
        , _line (0)
        , _cumulative_y_drag (0)
+       , _before (0)
+       , _after (0)
 {
        DEBUG_TRACE (DEBUG::Drags, "New LineDrag\n");
 }
@@ -4176,10 +4230,7 @@ LineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
 
        framecnt_t const frame_within_region = (framecnt_t) floor (cx * _editor->samples_per_pixel);
 
-       uint32_t before;
-       uint32_t after;
-
-       if (!_line->control_points_adjacent (frame_within_region, before, after)) {
+       if (!_line->control_points_adjacent (frame_within_region, _before, _after)) {
                /* no adjacent points */
                return;
        }
@@ -4193,13 +4244,11 @@ LineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
 
        double fraction = 1.0 - (cy / _line->height());
 
-       _line->start_drag_line (before, after, fraction);
-
        show_verbose_cursor_text (_line->get_verbose_cursor_string (fraction));
 }
 
 void
-LineDrag::motion (GdkEvent* event, bool)
+LineDrag::motion (GdkEvent* event, bool first_move)
 {
        double dy = current_pointer_y() - last_pointer_y();
 
@@ -4217,6 +4266,11 @@ LineDrag::motion (GdkEvent* event, bool)
        double const fraction = 1.0 - (cy / _line->height());
        uint32_t ignored;
 
+       if (first_move) {
+               _editor->begin_reversible_command (_("automation range move"));
+               _line->start_drag_line (_before, _after, fraction);
+       }
+
        /* we are ignoring x position for this drag, so we can just pass in anything */
        _line->drag_motion (0, fraction, true, false, ignored);
 
@@ -4229,20 +4283,24 @@ LineDrag::finished (GdkEvent* event, bool movement_occured)
        if (movement_occured) {
                motion (event, false);
                _line->end_drag (false, 0);
+               _editor->commit_reversible_command ();
        } else {
                /* add a new control point on the line */
 
                AutomationTimeAxisView* atv;
 
-               _line->end_drag (false, 0);
-
                if ((atv = dynamic_cast<AutomationTimeAxisView*>(_editor->clicked_axisview)) != 0) {
-                       framepos_t where = _editor->window_event_sample (event, 0, 0);
+                       framepos_t where = _editor->canvas_event_sample (event, 0, 0);
+
                        atv->add_automation_event (event, where, event->button.y, false);
+               } else if (dynamic_cast<AudioTimeAxisView*>(_editor->clicked_axisview) != 0) {
+                       AudioRegionView* arv;
+
+                       if ((arv = dynamic_cast<AudioRegionView*>(_editor->clicked_regionview)) != 0) {
+                               arv->add_gain_point_event (arv->get_canvas_group (), event, false);
+                       }
                }
        }
-
-       _editor->commit_reversible_command ();
 }
 
 void
@@ -4820,7 +4878,6 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
 
        case SelectionStartTrim:
 
-               start = _editor->selection->time[_editor->clicked_selection].start;
                end = _editor->selection->time[_editor->clicked_selection].end;
 
                if (pending_position > end) {
@@ -4833,7 +4890,6 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
        case SelectionEndTrim:
 
                start = _editor->selection->time[_editor->clicked_selection].start;
-               end = _editor->selection->time[_editor->clicked_selection].end;
 
                if (pending_position < start) {
                        end = start;
@@ -4895,7 +4951,7 @@ SelectionDrag::finished (GdkEvent* event, bool movement_occurred)
 
                /* XXX what if its a music time selection? */
                if (s) {
-                       if ( s->get_play_range() && s->transport_rolling() ) {
+                       if (s->get_play_range() && s->transport_rolling()) {
                                s->request_play_range (&_editor->selection->time, true);
                        } else {
                                if (ARDOUR_UI::config()->get_follow_edits() && !s->transport_rolling()) {
@@ -4905,8 +4961,14 @@ SelectionDrag::finished (GdkEvent* event, bool movement_occurred)
                                                s->request_locate (_editor->get_selection().time.start());
                                }
                        }
-               }
 
+                       if (_editor->get_selection().time.length() != 0) {
+                               s->set_range_selection (_editor->get_selection().time.start(), _editor->get_selection().time.end_frame());
+                       } else {
+                               s->clear_range_selection ();
+                       }
+               }
+               
        } else {
                /* just a click, no pointer movement.
                 */
@@ -5278,7 +5340,13 @@ NoteDrag::total_dx (const guint state) const
                }
        }
 
-       return _region->snap_frame_to_frame (st - rp, snap) + rp - n - snap_delta (state);
+       frameoffset_t ret;
+       if (snap) {
+               ret =  _region->snap_frame_to_frame (st - rp) + rp - n - snap_delta (state);
+       } else {
+               ret = st - n - snap_delta (state);
+       }
+       return ret;
 }
 
 /** @return Current total drag y change in note number */
@@ -5337,7 +5405,7 @@ NoteDrag::finished (GdkEvent* ev, bool moved)
        if (!moved) {
                /* no motion - select note */
 
-               if (_editor->current_mouse_mode() == Editing::MouseObject ||
+               if (_editor->current_mouse_mode() == Editing::MouseContent ||
                    _editor->current_mouse_mode() == Editing::MouseDraw) {
 
                        bool changed = false;
@@ -5515,8 +5583,8 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
                                double const p = j->line->time_converter().from (i->start - j->line->time_converter().origin_b ());
                                double const q = j->line->time_converter().from (a - j->line->time_converter().origin_b ());
 
-                               the_list->editor_add (p, value (the_list, p));
-                               the_list->editor_add (q, value (the_list, q));
+                               the_list->editor_add (p, value (the_list, p), false);
+                               the_list->editor_add (q, value (the_list, q), false);
                        }
 
                        /* same thing for the end */
@@ -5541,8 +5609,8 @@ 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->editor_add (p, value (the_list, p));
-                               the_list->editor_add (q, value (the_list, q));
+                               the_list->editor_add (p, value (the_list, p), false);
+                               the_list->editor_add (q, value (the_list, q), false);
                        }
                }
 
@@ -5579,19 +5647,22 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
        if (_nothing_to_drag) {
                return;
        }
-
-       for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
-               i->line->start_drag_multiple (i->points, y_fraction (i->line, current_pointer_y()), i->state);
-       }
 }
 
 void
-AutomationRangeDrag::motion (GdkEvent*, bool /*first_move*/)
+AutomationRangeDrag::motion (GdkEvent*, bool first_move)
 {
        if (_nothing_to_drag) {
                return;
        }
 
+       if (first_move) {
+               _editor->begin_reversible_command (_("automation range move"));
+               for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
+                       i->line->start_drag_multiple (i->points, y_fraction (i->line, current_pointer_y()), i->state);
+               }
+       }
+
        for (list<Line>::iterator l = _lines.begin(); l != _lines.end(); ++l) {
                float const f = y_fraction (l->line, current_pointer_y());
                /* we are ignoring x position for this drag, so we can just pass in anything */
@@ -5602,9 +5673,9 @@ AutomationRangeDrag::motion (GdkEvent*, bool /*first_move*/)
 }
 
 void
-AutomationRangeDrag::finished (GdkEvent* event, bool)
+AutomationRangeDrag::finished (GdkEvent* event, bool motion_occurred)
 {
-       if (_nothing_to_drag) {
+       if (_nothing_to_drag || !motion_occurred) {
                return;
        }