son't try to select non-existent notes after editing (and thus crash).
[ardour.git] / gtk2_ardour / midi_region_view.cc
index c3aa04ce40f89176793cfa502495e8494fb5a904..fdd5f1b744e6ed9b8c3c6f8c5555d632bdf4eafd 100644 (file)
@@ -497,13 +497,20 @@ MidiRegionView::button_press (GdkEventButton* ev)
        if (_mouse_state != SelectTouchDragging) {
 
                _pressed_button = ev->button;
-               _mouse_state = Pressed;
 
                if (m == MouseDraw || (m == MouseContent && Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier()))) {
-                       editor->drags()->set (new NoteCreateDrag (dynamic_cast<Editor *> (editor), group, this), (GdkEvent *) ev);
+
+                       if (midi_view()->note_mode() == Percussive) {
+                               editor->drags()->set (new HitCreateDrag (dynamic_cast<Editor *> (editor), group, this), (GdkEvent *) ev);
+                       } else {
+                               editor->drags()->set (new NoteCreateDrag (dynamic_cast<Editor *> (editor), group, this), (GdkEvent *) ev);
+                       }
+
                        _mouse_state = AddDragging;
                        remove_ghost_note ();
                        hide_verbose_cursor ();
+               } else {
+                       _mouse_state = Pressed;
                }
 
                return true;
@@ -713,11 +720,14 @@ MidiRegionView::key_press (GdkEventKey* ev)
           detectable auto-repeat is the name of the game and only sends
           repeated presses, carry out key actions at key press, not release.
        */
-
        bool unmodified = Keyboard::no_modifier_keys_pressed (ev);
 
        if (unmodified && (ev->keyval == GDK_Alt_L || ev->keyval == GDK_Alt_R)) {
-               _mouse_state = SelectTouchDragging;
+
+               if (_mouse_state != AddDragging) {
+                       _mouse_state = SelectTouchDragging;
+               }
+
                return true;
 
        } else if (ev->keyval == GDK_Escape && unmodified) {
@@ -1665,7 +1675,7 @@ MidiRegionView::note_in_region_range (const boost::shared_ptr<NoteType> note, bo
 
        /* must compare double explicitly as Beats::operator< rounds to ppqn */
        const bool outside = (note->time().to_double() < midi_reg->start_beats() ||
-                             note->time().to_double() > midi_reg->start_beats() + midi_reg->length_beats());
+                             note->time().to_double() >= midi_reg->start_beats() + midi_reg->length_beats());
 
        visible = (note->note() >= midi_stream_view()->lowest_note()) &&
                (note->note() <= midi_stream_view()->highest_note());
@@ -1705,7 +1715,7 @@ MidiRegionView::update_sustained (Note* ev, bool update_ghost_regions)
        double y1;
 
        /* trim note display to not overlap the end of its region */
-       if (note->length() > 0) {
+       if (note->length().to_double() > 0.0) {
                double note_end_time = note->end_time().to_double();
 
                if (note_end_time > mr->start_beats() + mr->length_beats()) {
@@ -3742,7 +3752,15 @@ MidiRegionView::update_ghost_note (double x, double y, uint32_t state)
        framepos_t const unsnapped_frame = editor.pixel_to_sample (x);
 
        const int32_t divisions = editor.get_grid_music_divisions (state);
-       const Evoral::Beats snapped_beats = snap_frame_to_grid_underneath (unsnapped_frame, divisions, true);
+       const bool shift_snap = midi_view()->note_mode() != Percussive;
+       const Evoral::Beats snapped_beats = snap_frame_to_grid_underneath (unsnapped_frame, divisions, shift_snap);
+
+       /* prevent Percussive mode from displaying a ghost hit at region end */
+       if (!shift_snap && snapped_beats >= midi_region()->start_beats() + midi_region()->length_beats()) {
+               _ghost_note->hide();
+               hide_verbose_cursor ();
+               return;
+       }
 
        /* ghost note may have been snapped before region */
        if (_ghost_note && snapped_beats.to_double() < 0.0) {