diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 2775e4ee40..e63d9ccf5b 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -6852,11 +6852,11 @@ NoteCreateDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) const timepos_t pos = _drags->current_pointer_time (); Temporal::Beats aligned_beats (round_to_grid (pos, event)); - const Temporal::Beats grid_beats (_midi_view->get_draw_length_beats (pos)); + const Temporal::Beats min_length (0, Temporal::Beats::PPQN/ 128); _note[0] = timepos_t (aligned_beats); /* minimum initial length is grid beats */ - _note[1] = _note[0] + timepos_t (grid_beats); + _note[1] = _note[0] + timepos_t (min_length); /* the note positions we've just computed are in absolute beats, but * the drag rect is a member of the region view group, so we need @@ -6882,7 +6882,7 @@ NoteCreateDrag::motion (GdkEvent* event, bool) const timepos_t pos = _drags->current_pointer_time (); /* when the user clicks and starts a drag to define the note's length, require notes to be at least |this| long */ - const Temporal::Beats min_length (_midi_view->get_draw_length_beats (pos)); + const Temporal::Beats min_length (0, Temporal::Beats::PPQN / 128); Temporal::Beats aligned_beats = round_to_grid (pos, event); _note[1] = std::max (aligned_beats, (_note[0].beats () + min_length)); @@ -6899,12 +6899,18 @@ NoteCreateDrag::motion (GdkEvent* event, bool) void NoteCreateDrag::finished (GdkEvent* ev, bool had_movement) { - /* we create a note even if there was no movement */ + Beats length; /* Compute start within region, rather than absolute time start */ Beats const start = _midi_view->midi_region ()->absolute_time_to_region_beats (min (_note[0], _note[1])); - Beats length = max (Beats (0, 1), (_note[0].distance (_note[1]).abs ().beats ())); + + if (!had_movement) { + /* we create a note even if there was no movement */ + length = _midi_view->get_draw_length_beats (_note[0]); + } else { + length = _note[0].distance (_note[1]).abs ().beats (); + } /* create_note_at() implements UNDO for us */ if (UIConfiguration::instance().get_select_last_drawn_note_only()) { diff --git a/gtk2_ardour/midi_cue_view.cc b/gtk2_ardour/midi_cue_view.cc index e2bc66a2b1..89011d35fa 100644 --- a/gtk2_ardour/midi_cue_view.cc +++ b/gtk2_ardour/midi_cue_view.cc @@ -53,6 +53,8 @@ MidiCueView::MidiCueView (std::shared_ptr mt, event_rect->set_outline (false); _note_group->raise_to_top (); + + set_extensible (true); } void diff --git a/gtk2_ardour/midi_cue_view.h b/gtk2_ardour/midi_cue_view.h index c27d39b791..c1e49a7135 100644 --- a/gtk2_ardour/midi_cue_view.h +++ b/gtk2_ardour/midi_cue_view.h @@ -41,6 +41,10 @@ class MidiCueView : public MidiView void set_height (double); ArdourCanvas::Item* drag_group() const; + bool note_in_region_range (const std::shared_ptr note, bool& visible) const { + visible = true; + return true; + } protected: bool scroll (GdkEventScroll* ev); diff --git a/gtk2_ardour/midi_view.cc b/gtk2_ardour/midi_view.cc index 0312a3a35a..1438a44313 100644 --- a/gtk2_ardour/midi_view.cc +++ b/gtk2_ardour/midi_view.cc @@ -135,6 +135,7 @@ MidiView::MidiView (std::shared_ptr mt, , _mouse_changed_selection (false) , split_tuple (0) , note_splitting (false) + , _extensible (false) { init (); } @@ -1095,7 +1096,7 @@ MidiView::model_changed() std::shared_ptr note (*n); bool visible; - if (note_in_region_range (note, visible)) { + if (_extensible || note_in_region_range (note, visible)) { if (!empty_when_starting && (cne = find_canvas_note (note)) != 0) { cne->validate (); if (visible) { @@ -1648,7 +1649,7 @@ MidiView::update_sustained (Note* ev, bool update_ghost_regions) const Temporal::Beats source_end ((_midi_region->start() + _midi_region->length()).beats()); - if (note->end_time() > source_end) { + if (!_extensible && note->end_time() > source_end) { note_end = timepos_t (source_end); } diff --git a/gtk2_ardour/midi_view.h b/gtk2_ardour/midi_view.h index 763467825a..dcbc22d0cd 100644 --- a/gtk2_ardour/midi_view.h +++ b/gtk2_ardour/midi_view.h @@ -229,7 +229,7 @@ class MidiView : public virtual sigc::trackable * @param visible will be set to true if the note is within the visible note range, false otherwise. * @return true iff the note is within the (time) extent of the region. */ - bool note_in_region_range(const std::shared_ptr note, bool& visible) const; + virtual bool note_in_region_range(const std::shared_ptr note, bool& visible) const; /* Test if a note is withing this region's time range. Return true if so */ bool note_in_region_time_range(const std::shared_ptr note) const; @@ -625,6 +625,10 @@ class MidiView : public virtual sigc::trackable uint32_t split_tuple; bool note_splitting; + bool _extensible; /* if true, we can add data beyond the current region/source end */ + + bool extensible() const { return _extensible; } + void set_extensible (bool yn) { _extensible = yn; } void start_note_splitting (); void end_note_splitting ();