From 81d172493145ea2960f3fee698cd62991c97e7f1 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 2 May 2024 15:25:34 -0600 Subject: [PATCH 1/9] NO-OP: add clarifying comment --- libs/gtkmm2ext/utils.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/gtkmm2ext/utils.cc b/libs/gtkmm2ext/utils.cc index 9f24f928e3..144114251a 100644 --- a/libs/gtkmm2ext/utils.cc +++ b/libs/gtkmm2ext/utils.cc @@ -194,10 +194,10 @@ Gtkmm2ext::pixbuf_from_string(const string& name, const Pango::FontDescription& int width, height; pixel_size (name, font, width, height); if (clip_width <= 0) { - clip_width = width - clip_width; + clip_width = width - clip_width; /* this is an addition because clip_width is negative */ } if (clip_height <= 0) { - clip_height = height - clip_height; + clip_height = height - clip_height; /* this is an addition because clip_height is negative */ } } From 89d7d85239ab6b5e9040519a23b31f43a5a91489 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 2 May 2024 18:20:34 -0600 Subject: [PATCH 2/9] remove weird unused member of ARDOUR_UI --- gtk2_ardour/ardour_ui.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 331d776b4f..9b8529b726 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -275,8 +275,6 @@ public: void reset_focus (Gtk::Widget*); - static PublicEditor* _instance; - /** Emitted frequently with the audible sample, false, and the edit point as * parameters respectively. * From e170b34bf07d17d4c15ed13fc0c840ea19973018 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 2 May 2024 18:22:07 -0600 Subject: [PATCH 3/9] add pure virtual API for track DnD to PublicEditor --- gtk2_ardour/public_editor.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index e474b95dfb..b29c94a9a4 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -588,6 +588,12 @@ public: virtual void set_tempo_curve_range (double& max, double& min) const = 0; + virtual void start_track_drag (TimeAxisView&, int y, Gtk::Widget&) = 0; + virtual void mid_track_drag (GdkEventMotion*, Gtk::Widget&) = 0; + virtual void end_track_drag () = 0; + virtual void get_layout_relative_coordinates (Gtk::Widget&, int x, int y, int &xo, int &yo) = 0; + virtual bool track_dragging() const = 0; + /// Singleton instance, set up by Editor::Editor() static PublicEditor* _instance; From e71fcaa92d803a83d00171706bc070d9c6e8ae35 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 2 May 2024 18:22:50 -0600 Subject: [PATCH 4/9] add private object to Editor for use with track drag-n-drop --- gtk2_ardour/editor.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index bbc9300f97..7c6842f6df 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -2598,6 +2598,37 @@ private: friend class Drag; friend class RegionCutDrag; friend class RegionDrag; + + struct TrackDrag { + RouteTimeAxisView* track; + Gtk::EventBox* spacer; + GdkCursor* drag_cursor; + GdkCursor* predrag_cursor; + TimeAxisView* bump_track; + int spacer_order; + double start; + double current; + double previous; + bool have_predrag_cursor; + int direction; + + TrackDrag (RouteTimeAxisView* rtav) + : track (rtav) + , spacer (nullptr) + , drag_cursor (nullptr) + , predrag_cursor (nullptr) + , bump_track (nullptr) + , spacer_order (-1) + , start (-1.) + , current (0.) + , previous (0.) + , have_predrag_cursor (false) + , direction (0) + {} + + }; + TrackDrag* track_drag; + friend class RegionMoveDrag; friend class TrimDrag; friend class MappingTwistDrag; From b515174e6a0b62fc0c95ca9b3ba615b6314c751a Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 2 May 2024 18:24:48 -0600 Subject: [PATCH 5/9] initialize track_drag member of Editor --- gtk2_ardour/editor.cc | 1 + gtk2_ardour/editor.h | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 0100322d85..09b3f99723 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -474,6 +474,7 @@ Editor::Editor () , quantize_dialog (0) , _main_menu_disabler (0) , domain_bounce_info (nullptr) + , track_drag (nullptr) { /* we are a singleton */ diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 7c6842f6df..e9a6153b0b 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -1413,6 +1413,12 @@ private: void insert_patch_change (bool from_context); void fork_selected_regions (); void fork_regions_from_unselected (); + void start_track_drag (TimeAxisView&, int y, Gtk::Widget& w); + void mid_track_drag (GdkEventMotion*, Gtk::Widget& e); + void end_track_drag (); + void maybe_place_drag_spacer (); + void get_layout_relative_coordinates (Gtk::Widget&, int x, int y, int &xo, int &yo); + bool track_dragging() const; void do_insert_time (); void insert_time (Temporal::timepos_t const &, Temporal::timecnt_t const &, Editing::InsertTimeOption, bool, bool, bool, bool); From c3fb69c38595e34a06efcce7af69ddb6eddc47f4 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 2 May 2024 20:19:41 -0600 Subject: [PATCH 6/9] catch button release after track drag --- gtk2_ardour/editor.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 09b3f99723..64c5f67fd7 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -4291,6 +4291,11 @@ Editor::override_visible_track_count () bool Editor::edit_controls_button_event (GdkEventButton* ev) { + if (ev->type == GDK_BUTTON_RELEASE && track_dragging()) { + end_track_drag (); + return true; + } + if ((ev->type == GDK_2BUTTON_PRESS && ev->button == 1) || (ev->type == GDK_BUTTON_RELEASE && Keyboard::is_context_menu_event (ev))) { ARDOUR_UI::instance()->add_route (); } else if (ev->button == 1 && ev->type == GDK_BUTTON_PRESS) { From 51d2b3329c39fb23ec3cdaed09abb5dd601c422a Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 2 May 2024 20:23:29 -0600 Subject: [PATCH 7/9] more work catching button release after track drag --- gtk2_ardour/time_axis_view.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc index 2f3432c46d..2d80131689 100644 --- a/gtk2_ardour/time_axis_view.cc +++ b/gtk2_ardour/time_axis_view.cc @@ -518,6 +518,10 @@ TimeAxisView::maybe_set_cursor (int y) bool TimeAxisView::controls_ebox_button_release (GdkEventButton* ev) { + if (_editor.track_dragging()) { + return false; + } + if (_resize_drag_start >= 0) { if (_have_preresize_cursor) { gdk_window_set_cursor (controls_ebox.get_window()->gobj(), _preresize_cursor); From fdd91cc32555866b4588c2214511714cc5293d3e Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Sun, 5 May 2024 12:09:32 -0600 Subject: [PATCH 8/9] remove debug output --- libs/ardour/session_state.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 9f0bcd9ddf..f387871671 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -3941,8 +3941,6 @@ Session::cleanup_sources (CleanupReport& rep) } } - cerr << "Actually unused: " << unused.size() << endl; - if (unused.empty()) { /* Nothing to do */ ret = 0; From f92d821a722e404978ba8c5f106a3c520676448b Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Sun, 5 May 2024 15:09:34 -0600 Subject: [PATCH 9/9] working track drag-n-drop, re-picked from a 2nd implementation on a branch --- gtk2_ardour/editor.cc | 132 ++++++++++++++++++++++++++++++++-- gtk2_ardour/editor.h | 9 +-- gtk2_ardour/public_editor.h | 1 - gtk2_ardour/time_axis_view.cc | 50 ++++++++----- 4 files changed, 162 insertions(+), 30 deletions(-) diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 64c5f67fd7..1833d10008 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -6184,6 +6184,54 @@ struct TrackViewStripableSorter } }; +static const int track_drag_spacer_height = 25; + +void +Editor::maybe_move_tracks () +{ + for (auto & tv : track_views) { + + if (!tv->marked_for_display () || (tv == track_drag->track)) { + continue; + } + + /* find the track the mouse pointer is within, and if + * we're in the upper or lower half of it (depending on + * drag direction, move the spacer. + */ + + if (track_drag->current >= tv->y_position() && track_drag->current < (tv->y_position() + tv->effective_height())) { + + if (track_drag->bump_track == tv) { + /* already bumped for this track */ + break; + } + + if (track_drag->direction < 0) { + + /* dragging up */ + + if (track_drag->current < (tv->y_position() + (tv->effective_height() / 2))) { + /* in top half of this track, move spacer */ + track_drag->bump_track = tv; + move_selected_tracks (true); + } + + } else if (track_drag->direction > 0) { + + /* dragging down */ + + if (track_drag->current > (tv->y_position() + (tv->effective_height() / 2))) { + track_drag->bump_track = tv; + move_selected_tracks (false); + } + } + + break; + } + } +} + bool Editor::redisplay_track_views () { @@ -6200,21 +6248,24 @@ Editor::redisplay_track_views () track_views.sort (TrackViewStripableSorter ()); - uint32_t position; - TrackViewList::const_iterator i; + if (track_drag) { // && track_drag->spacer) { + maybe_move_tracks (); + } /* n will be the count of tracks plus children (updated by TimeAxisView::show_at), * so we will use that to know where to put things. */ - int n; - for (n = 0, position = 0, i = track_views.begin(); i != track_views.end(); ++i) { - TimeAxisView *tv = (*i); + int n = 0; + uint32_t position = 0; + + for (auto & tv : track_views) { if (tv->marked_for_display ()) { position += tv->show_at (position, n, &edit_controls_vbox); } else { tv->hide (); } + n++; } @@ -7016,3 +7067,74 @@ Editor::default_time_domain () const } return BeatTime; } + +void +Editor::start_track_drag (TimeAxisView& tav, int y, Gtk::Widget& w) +{ + track_drag = new TrackDrag (dynamic_cast (&tav)); + + track_drag->drag_cursor = _cursors->move->gobj(); + track_drag->predrag_cursor = gdk_window_get_cursor (edit_controls_vbox.get_window()->gobj()); + + gdk_window_set_cursor (edit_controls_vbox.get_toplevel()->get_window()->gobj(), track_drag->drag_cursor); + + int xo, yo; + w.translate_coordinates (edit_controls_vbox, 0, y, xo, yo); + + track_drag->have_predrag_cursor = true; + track_drag->bump_track = nullptr; + track_drag->previous = yo; + track_drag->start = yo; +} + +void +Editor::mid_track_drag (GdkEventMotion* ev, Gtk::Widget& w) +{ + int xo, yo; + w.translate_coordinates (edit_controls_vbox, ev->x, ev->y, xo, yo); + + if (track_drag->first_move) { + if (!track_drag->track->selected()) { + set_selected_track (*track_drag->track, Selection::Set, false); + } + track_drag->first_move = false; + } + + track_drag->current = yo; + + if (track_drag->current > track_drag->previous) { + if (track_drag->direction != 1) { + track_drag->bump_track = nullptr; + track_drag->direction = 1; + } + } else if (track_drag->current < track_drag->previous) { + if (track_drag->direction != -1) { + track_drag->bump_track = nullptr; + track_drag->direction = -1; + } + } + + if (track_drag->current == track_drag->previous) { + return; + } + + redisplay_track_views (); + track_drag->previous = yo; +} + +void +Editor::end_track_drag () +{ + if (track_drag->have_predrag_cursor) { + gdk_window_set_cursor (edit_controls_vbox.get_toplevel()->get_window()->gobj(), track_drag->predrag_cursor); + } + + delete track_drag; + track_drag = nullptr; +} + +bool +Editor::track_dragging() const +{ + return (bool) track_drag; +} diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index e9a6153b0b..cb3cda62ad 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -1416,8 +1416,7 @@ private: void start_track_drag (TimeAxisView&, int y, Gtk::Widget& w); void mid_track_drag (GdkEventMotion*, Gtk::Widget& e); void end_track_drag (); - void maybe_place_drag_spacer (); - void get_layout_relative_coordinates (Gtk::Widget&, int x, int y, int &xo, int &yo); + void maybe_move_tracks (); bool track_dragging() const; void do_insert_time (); @@ -2607,29 +2606,27 @@ private: struct TrackDrag { RouteTimeAxisView* track; - Gtk::EventBox* spacer; GdkCursor* drag_cursor; GdkCursor* predrag_cursor; TimeAxisView* bump_track; - int spacer_order; double start; double current; double previous; bool have_predrag_cursor; int direction; + bool first_move; TrackDrag (RouteTimeAxisView* rtav) : track (rtav) - , spacer (nullptr) , drag_cursor (nullptr) , predrag_cursor (nullptr) , bump_track (nullptr) - , spacer_order (-1) , start (-1.) , current (0.) , previous (0.) , have_predrag_cursor (false) , direction (0) + , first_move (true) {} }; diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index b29c94a9a4..c7647aceb0 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -591,7 +591,6 @@ public: virtual void start_track_drag (TimeAxisView&, int y, Gtk::Widget&) = 0; virtual void mid_track_drag (GdkEventMotion*, Gtk::Widget&) = 0; virtual void end_track_drag () = 0; - virtual void get_layout_relative_coordinates (Gtk::Widget&, int x, int y, int &xo, int &yo) = 0; virtual bool track_dragging() const = 0; /// Singleton instance, set up by Editor::Editor() diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc index 2d80131689..ccb7fbedd8 100644 --- a/gtk2_ardour/time_axis_view.cc +++ b/gtk2_ardour/time_axis_view.cc @@ -438,7 +438,13 @@ TimeAxisView::controls_ebox_button_press (GdkEventButton* event) _ebox_release_can_act = true; if (maybe_set_cursor (event->y) > 0) { + _resize_drag_start = event->y_root; + + } else { + if (event->button == 1) { + _editor.start_track_drag (*this, event->y, controls_ebox); + } } return true; @@ -453,6 +459,12 @@ TimeAxisView::idle_resize (int32_t h) bool TimeAxisView::controls_ebox_motion (GdkEventMotion* ev) { + if (_editor.track_dragging()) { + _editor.mid_track_drag (ev, controls_ebox); + gdk_event_request_motions (ev); + return true; + } + if (_resize_drag_start >= 0) { /* (ab)use the DragManager to do autoscrolling - basically we @@ -468,13 +480,15 @@ TimeAxisView::controls_ebox_motion (GdkEventMotion* ev) _editor.add_to_idle_resize (this, delta); _resize_drag_start = ev->y_root; _did_resize = true; + gdk_event_request_motions (ev); + return true; } else { /* not dragging but ... */ maybe_set_cursor (ev->y); } - gdk_event_request_motions(ev); - return true; + gdk_event_request_motions (ev); + return false; } bool @@ -519,28 +533,28 @@ bool TimeAxisView::controls_ebox_button_release (GdkEventButton* ev) { if (_editor.track_dragging()) { - return false; + _editor.end_track_drag (); + } else { + if (_resize_drag_start >= 0) { + if (_have_preresize_cursor) { + gdk_window_set_cursor (controls_ebox.get_window()->gobj(), _preresize_cursor); + _preresize_cursor = 0; + _have_preresize_cursor = false; + } + _editor.stop_canvas_autoscroll (); + _resize_drag_start = -1; + if (_did_resize) { + _did_resize = false; + // don't change selection + return true; + } } - if (_resize_drag_start >= 0) { - if (_have_preresize_cursor) { - gdk_window_set_cursor (controls_ebox.get_window()->gobj(), _preresize_cursor); - _preresize_cursor = 0; - _have_preresize_cursor = false; - } - _editor.stop_canvas_autoscroll (); - _resize_drag_start = -1; - if (_did_resize) { - _did_resize = false; - // don't change selection + if (!_ebox_release_can_act) { return true; } } - if (!_ebox_release_can_act) { - return true; - } - switch (ev->button) { case 1: if (selectable()) {