2 * Copyright (C) 2005-2018 Paul Davis <paul@linuxaudiosystems.com>
3 * Copyright (C) 2005 Taybin Rutkin <taybin@taybin.com>
4 * Copyright (C) 2006-2012 David Robillard <d@drobilla.net>
5 * Copyright (C) 2008 Hans Baier <hansfbaier@googlemail.com>
6 * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
7 * Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org>
8 * Copyright (C) 2015-2016 Tim Mayberry <mojofunk@gmail.com>
9 * Copyright (C) 2015-2017 Nick Mainsbridge <mainsbridge@gmail.com>
10 * Copyright (C) 2015-2019 Ben Loftis <ben@harrisonconsoles.com>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include "pbd/stacktrace.h"
34 #include "ardour/audio_track.h"
35 #include "ardour/midi_track.h"
36 #include "ardour/midi_region.h"
37 #include "ardour/profile.h"
38 #include "ardour/region_factory.h"
40 #include "canvas/canvas.h"
41 #include "canvas/text.h"
42 #include "canvas/scroll_group.h"
46 #include "public_editor.h"
47 #include "audio_region_view.h"
48 #include "audio_streamview.h"
49 #include "audio_time_axis.h"
50 #include "region_gain_line.h"
51 #include "automation_line.h"
52 #include "automation_time_axis.h"
53 #include "automation_line.h"
54 #include "control_point.h"
55 #include "editor_drag.h"
56 #include "midi_time_axis.h"
57 #include "editor_regions.h"
58 #include "editor_sources.h"
59 #include "ui_config.h"
60 #include "verbose_cursor.h"
65 using namespace ARDOUR;
68 using namespace ArdourCanvas;
70 using Gtkmm2ext::Keyboard;
73 Editor::track_canvas_scroll (GdkEventScroll* ev)
75 int direction = ev->direction;
77 /* this event arrives without transformation by the canvas, so we have
78 * to transform the coordinates to be able to look things up.
81 Duple event_coords = _track_canvas->window_to_canvas (Duple (ev->x, ev->y));
85 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) {
86 if (UIConfiguration::instance().get_use_mouse_position_as_zoom_focus_on_scroll()) {
87 temporal_zoom_step_mouse_focus (false);
89 temporal_zoom_step (false);
92 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) {
95 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) {
96 if (!current_stepping_trackview) {
97 step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
98 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (event_coords.y, false);
99 current_stepping_trackview = p.first;
100 if (!current_stepping_trackview) {
104 last_track_height_step_timestamp = get_microseconds();
105 current_stepping_trackview->step_height (false);
108 scroll_up_one_track ();
113 case GDK_SCROLL_DOWN:
114 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) {
115 if (UIConfiguration::instance().get_use_mouse_position_as_zoom_focus_on_scroll()) {
116 temporal_zoom_step_mouse_focus (true);
118 temporal_zoom_step (true);
121 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) {
122 scroll_right_step ();
124 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) {
125 if (!current_stepping_trackview) {
126 step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
127 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (event_coords.y, false);
128 current_stepping_trackview = p.first;
129 if (!current_stepping_trackview) {
133 last_track_height_step_timestamp = get_microseconds();
134 current_stepping_trackview->step_height (true);
137 scroll_down_one_track ();
142 case GDK_SCROLL_LEFT:
147 case GDK_SCROLL_RIGHT:
148 scroll_right_step ();
161 Editor::canvas_scroll_event (GdkEventScroll *event, bool from_canvas)
164 boost::optional<ArdourCanvas::Rect> rulers = _time_markers_group->bounding_box();
165 if (rulers && rulers->contains (Duple (event->x, event->y))) {
166 return canvas_ruler_event ((GdkEvent*) event, timecode_ruler, TimecodeRulerItem);
170 _track_canvas->grab_focus();
171 return track_canvas_scroll (event);
175 Editor::track_canvas_button_press_event (GdkEventButton *event)
177 _track_canvas->grab_focus();
178 if (!Keyboard::is_context_menu_event (event)) {
179 begin_reversible_selection_op (X_("Clear Selection Click (track canvas)"));
181 commit_reversible_selection_op();
187 Editor::track_canvas_button_release_event (GdkEventButton *event)
189 if (!Keyboard::is_context_menu_event (event)) {
190 if (_drags->active ()) {
191 _drags->end_grab ((GdkEvent*) event);
198 Editor::track_canvas_motion_notify_event (GdkEventMotion */*event*/)
201 /* keep those motion events coming */
202 _track_canvas->get_pointer (x, y);
207 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
209 if (!session () || session()->loading () || session()->deletion_in_progress ()) {
215 switch (event->type) {
216 case GDK_BUTTON_PRESS:
217 case GDK_2BUTTON_PRESS:
218 case GDK_3BUTTON_PRESS:
219 ret = button_press_handler (item, event, type);
221 case GDK_BUTTON_RELEASE:
222 ret = button_release_handler (item, event, type);
224 case GDK_MOTION_NOTIFY:
225 ret = motion_handler (item, event);
228 case GDK_ENTER_NOTIFY:
229 ret = enter_handler (item, event, type);
232 case GDK_LEAVE_NOTIFY:
233 ret = leave_handler (item, event, type);
237 ret = key_press_handler (item, event, type);
240 case GDK_KEY_RELEASE:
241 ret = key_release_handler (item, event, type);
251 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
255 if (!rv->sensitive ()) {
259 switch (event->type) {
260 case GDK_BUTTON_PRESS:
261 case GDK_2BUTTON_PRESS:
262 case GDK_3BUTTON_PRESS:
263 clicked_regionview = rv;
264 clicked_control_point = 0;
265 clicked_axisview = &rv->get_time_axis_view();
266 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
267 ret = button_press_handler (item, event, RegionItem);
270 case GDK_BUTTON_RELEASE:
271 ret = button_release_handler (item, event, RegionItem);
274 case GDK_MOTION_NOTIFY:
275 ret = motion_handler (item, event);
278 case GDK_ENTER_NOTIFY:
279 set_entered_regionview (rv);
280 ret = enter_handler (item, event, RegionItem);
283 case GDK_LEAVE_NOTIFY:
284 if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
285 set_entered_regionview (0);
286 ret = leave_handler (item, event, RegionItem);
298 Editor::canvas_wave_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
300 /* we only care about enter events here, required for mouse/cursor
301 * tracking. there is a non-linear (non-child/non-parent) relationship
302 * between various components of a regionview and so when we leave one
303 * of them (e.g. a trim handle) and enter another (e.g. the waveview)
304 * no other items get notified. enter/leave handling does not propagate
305 * in the same way as other events, so we need to catch this because
306 * entering (and leaving) the waveview is equivalent to
307 * entering/leaving the regionview (which is why it is passed in as a
310 * And in fact, we really only care about enter events.
315 if (!rv->sensitive ()) {
319 switch (event->type) {
320 case GDK_ENTER_NOTIFY:
321 set_entered_regionview (rv);
322 ret = enter_handler (item, event, WaveItem);
334 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
338 switch (event->type) {
339 case GDK_BUTTON_PRESS:
340 case GDK_2BUTTON_PRESS:
341 case GDK_3BUTTON_PRESS:
342 clicked_regionview = 0;
343 clicked_control_point = 0;
344 clicked_axisview = tv;
345 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
346 ret = button_press_handler (item, event, StreamItem);
349 case GDK_BUTTON_RELEASE:
350 ret = button_release_handler (item, event, StreamItem);
353 case GDK_MOTION_NOTIFY:
354 ret = motion_handler (item, event);
357 case GDK_ENTER_NOTIFY:
358 set_entered_track (tv);
359 ret = enter_handler (item, event, StreamItem);
362 case GDK_LEAVE_NOTIFY:
363 if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
364 set_entered_track (0);
366 ret = leave_handler (item, event, StreamItem);
377 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
381 switch (event->type) {
382 case GDK_BUTTON_PRESS:
383 case GDK_2BUTTON_PRESS:
384 case GDK_3BUTTON_PRESS:
385 clicked_regionview = 0;
386 clicked_control_point = 0;
387 clicked_axisview = atv;
388 clicked_routeview = 0;
389 ret = button_press_handler (item, event, AutomationTrackItem);
392 case GDK_BUTTON_RELEASE:
393 ret = button_release_handler (item, event, AutomationTrackItem);
396 case GDK_MOTION_NOTIFY:
397 ret = motion_handler (item, event);
400 case GDK_ENTER_NOTIFY:
401 ret = enter_handler (item, event, AutomationTrackItem);
404 case GDK_LEAVE_NOTIFY:
405 ret = leave_handler (item, event, AutomationTrackItem);
416 Editor::canvas_start_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
418 if (!rv->sensitive()) {
422 switch (event->type) {
423 case GDK_BUTTON_PRESS:
424 clicked_regionview = rv;
425 clicked_control_point = 0;
426 clicked_axisview = &rv->get_time_axis_view();
427 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
428 if (event->button.button == 3) {
429 return button_press_handler (item, event, StartCrossFadeItem);
433 case GDK_BUTTON_RELEASE:
434 if (event->button.button == 3) {
435 return button_release_handler (item, event, StartCrossFadeItem);
444 /* In Mixbus, the crossfade area is used to trim the region while leaving the fade anchor intact (see preserve_fade_anchor)*/
445 /* however in A3 this feature is unfinished, and it might be better to do it with a modifier-trim instead, anyway */
446 /* if we return RegionItem here then we avoid the issue until it is resolved later */
447 return typed_event (item, event, RegionItem); // StartCrossFadeItem);
451 Editor::canvas_end_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
453 if (!rv->sensitive()) {
457 switch (event->type) {
458 case GDK_BUTTON_PRESS:
459 clicked_regionview = rv;
460 clicked_control_point = 0;
461 clicked_axisview = &rv->get_time_axis_view();
462 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
463 if (event->button.button == 3) {
464 return button_press_handler (item, event, EndCrossFadeItem);
468 case GDK_BUTTON_RELEASE:
469 if (event->button.button == 3) {
470 return button_release_handler (item, event, EndCrossFadeItem);
479 /* In Mixbus, the crossfade area is used to trim the region while leaving the fade anchor intact (see preserve_fade_anchor)*/
480 /* however in A3 this feature is unfinished, and it might be better to do it with a modifier-trim instead, anyway */
481 /* if we return RegionItem here then we avoid the issue until it is resolved later */
482 return typed_event (item, event, RegionItem); // EndCrossFadeItem);
486 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
488 /* we handle only button 3 press/release events */
490 if (!rv->sensitive()) {
494 switch (event->type) {
495 case GDK_BUTTON_PRESS:
496 clicked_regionview = rv;
497 clicked_control_point = 0;
498 clicked_axisview = &rv->get_time_axis_view();
499 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
500 if (event->button.button == 3) {
501 return button_press_handler (item, event, FadeInItem);
505 case GDK_BUTTON_RELEASE:
506 if (event->button.button == 3) {
507 return button_release_handler (item, event, FadeInItem);
516 /* proxy for the regionview, except enter/leave events */
518 if (event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) {
521 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
526 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv, bool trim)
530 if (!rv->sensitive()) {
534 switch (event->type) {
535 case GDK_BUTTON_PRESS:
536 case GDK_2BUTTON_PRESS:
537 case GDK_3BUTTON_PRESS:
538 clicked_regionview = rv;
539 clicked_control_point = 0;
540 clicked_axisview = &rv->get_time_axis_view();
541 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
542 ret = button_press_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
545 case GDK_BUTTON_RELEASE:
546 ret = button_release_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
549 case GDK_MOTION_NOTIFY:
550 ret = motion_handler (item, event);
553 case GDK_ENTER_NOTIFY:
554 ret = enter_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
557 case GDK_LEAVE_NOTIFY:
558 ret = leave_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
569 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
571 /* we handle only button 3 press/release events */
573 if (!rv->sensitive()) {
577 switch (event->type) {
578 case GDK_BUTTON_PRESS:
579 clicked_regionview = rv;
580 clicked_control_point = 0;
581 clicked_axisview = &rv->get_time_axis_view();
582 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
583 if (event->button.button == 3) {
584 return button_press_handler (item, event, FadeOutItem);
588 case GDK_BUTTON_RELEASE:
589 if (event->button.button == 3) {
590 return button_release_handler (item, event, FadeOutItem);
599 /* proxy for the regionview, except enter/leave events */
601 if (event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) {
604 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
609 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv, bool trim)
613 if (!rv->sensitive()) {
617 switch (event->type) {
618 case GDK_BUTTON_PRESS:
619 case GDK_2BUTTON_PRESS:
620 case GDK_3BUTTON_PRESS:
621 clicked_regionview = rv;
622 clicked_control_point = 0;
623 clicked_axisview = &rv->get_time_axis_view();
624 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
625 ret = button_press_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
628 case GDK_BUTTON_RELEASE:
629 ret = button_release_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
632 case GDK_MOTION_NOTIFY:
633 ret = motion_handler (item, event);
636 case GDK_ENTER_NOTIFY:
637 ret = enter_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
640 case GDK_LEAVE_NOTIFY:
641 ret = leave_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
651 struct DescendingRegionLayerSorter {
652 bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
653 return a->layer() > b->layer();
658 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
660 switch (event->type) {
661 case GDK_BUTTON_PRESS:
662 case GDK_2BUTTON_PRESS:
663 case GDK_3BUTTON_PRESS:
664 clicked_control_point = cp;
665 clicked_axisview = &cp->line().trackview;
666 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
667 clicked_regionview = 0;
673 case GDK_SCROLL_DOWN:
680 return typed_event (item, event, ControlPointItem);
684 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
687 AudioRegionGainLine* gl;
688 if ((gl = dynamic_cast<AudioRegionGainLine*> (al)) != 0) {
690 if (event->type == GDK_BUTTON_PRESS) {
691 clicked_regionview = &gl->region_view ();
694 type = AutomationLineItem;
695 if (event->type == GDK_BUTTON_PRESS) {
696 clicked_regionview = 0;
700 clicked_control_point = 0;
701 clicked_axisview = &al->trackview;
702 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
704 return typed_event (item, event, type);
708 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
712 switch (event->type) {
713 case GDK_BUTTON_PRESS:
714 case GDK_2BUTTON_PRESS:
715 case GDK_3BUTTON_PRESS:
716 clicked_selection = rect->id;
717 ret = button_press_handler (item, event, SelectionItem);
719 case GDK_BUTTON_RELEASE:
720 ret = button_release_handler (item, event, SelectionItem);
722 case GDK_MOTION_NOTIFY:
723 ret = motion_handler (item, event);
725 /* Don't need these at the moment. */
726 case GDK_ENTER_NOTIFY:
727 ret = enter_handler (item, event, SelectionItem);
730 case GDK_LEAVE_NOTIFY:
731 ret = leave_handler (item, event, SelectionItem);
742 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
746 switch (event->type) {
747 case GDK_BUTTON_PRESS:
748 case GDK_2BUTTON_PRESS:
749 case GDK_3BUTTON_PRESS:
750 clicked_selection = rect->id;
751 ret = button_press_handler (item, event, StartSelectionTrimItem);
753 case GDK_BUTTON_RELEASE:
754 ret = button_release_handler (item, event, StartSelectionTrimItem);
756 case GDK_MOTION_NOTIFY:
757 ret = motion_handler (item, event);
759 case GDK_ENTER_NOTIFY:
760 ret = enter_handler (item, event, StartSelectionTrimItem);
763 case GDK_LEAVE_NOTIFY:
764 ret = leave_handler (item, event, StartSelectionTrimItem);
775 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
779 switch (event->type) {
780 case GDK_BUTTON_PRESS:
781 case GDK_2BUTTON_PRESS:
782 case GDK_3BUTTON_PRESS:
783 clicked_selection = rect->id;
784 ret = button_press_handler (item, event, EndSelectionTrimItem);
786 case GDK_BUTTON_RELEASE:
787 ret = button_release_handler (item, event, EndSelectionTrimItem);
789 case GDK_MOTION_NOTIFY:
790 ret = motion_handler (item, event);
792 case GDK_ENTER_NOTIFY:
793 ret = enter_handler (item, event, EndSelectionTrimItem);
796 case GDK_LEAVE_NOTIFY:
797 ret = leave_handler (item, event, EndSelectionTrimItem);
808 Editor::canvas_frame_handle_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
812 /* frame handles are not active when in internal edit mode, because actual notes
813 might be in the area occupied by the handle - we want them to be editable as normal.
816 if (internal_editing() || !rv->sensitive()) {
820 /* NOTE: frame handles pretend to be the colored trim bar from an event handling
821 perspective. XXX change this ??
826 if (item->get_data ("isleft")) {
827 type = LeftFrameHandle;
829 type = RightFrameHandle;
832 switch (event->type) {
833 case GDK_BUTTON_PRESS:
834 case GDK_2BUTTON_PRESS:
835 case GDK_3BUTTON_PRESS:
836 clicked_regionview = rv;
837 clicked_control_point = 0;
838 clicked_axisview = &clicked_regionview->get_time_axis_view();
839 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
840 ret = button_press_handler (item, event, type);
842 case GDK_BUTTON_RELEASE:
843 ret = button_release_handler (item, event, type);
845 case GDK_MOTION_NOTIFY:
846 ret = motion_handler (item, event);
848 case GDK_ENTER_NOTIFY:
849 ret = enter_handler (item, event, type);
852 case GDK_LEAVE_NOTIFY:
853 ret = leave_handler (item, event, type);
865 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
869 if (!rv->sensitive()) {
873 switch (event->type) {
874 case GDK_BUTTON_PRESS:
875 case GDK_2BUTTON_PRESS:
876 case GDK_3BUTTON_PRESS:
877 clicked_regionview = rv;
878 clicked_control_point = 0;
879 clicked_axisview = &clicked_regionview->get_time_axis_view();
880 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
881 ret = button_press_handler (item, event, RegionViewNameHighlight);
883 case GDK_BUTTON_RELEASE:
884 ret = button_release_handler (item, event, RegionViewNameHighlight);
886 case GDK_MOTION_NOTIFY:
887 motion_handler (item, event);
888 ret = true; // force this to avoid progagating the event into the regionview
890 case GDK_ENTER_NOTIFY:
891 ret = enter_handler (item, event, RegionViewNameHighlight);
894 case GDK_LEAVE_NOTIFY:
895 ret = leave_handler (item, event, RegionViewNameHighlight);
906 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
910 if (!rv->sensitive()) {
914 switch (event->type) {
915 case GDK_BUTTON_PRESS:
916 case GDK_2BUTTON_PRESS:
917 case GDK_3BUTTON_PRESS:
918 clicked_regionview = rv;
919 clicked_control_point = 0;
920 clicked_axisview = &clicked_regionview->get_time_axis_view();
921 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
922 ret = button_press_handler (item, event, RegionViewName);
924 case GDK_BUTTON_RELEASE:
925 ret = button_release_handler (item, event, RegionViewName);
927 case GDK_MOTION_NOTIFY:
928 ret = motion_handler (item, event);
930 case GDK_ENTER_NOTIFY:
931 ret = enter_handler (item, event, RegionViewName);
934 case GDK_LEAVE_NOTIFY:
935 ret = leave_handler (item, event, RegionViewName);
946 Editor::canvas_feature_line_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView*)
950 switch (event->type) {
951 case GDK_BUTTON_PRESS:
952 case GDK_2BUTTON_PRESS:
953 case GDK_3BUTTON_PRESS:
954 clicked_regionview = 0;
955 clicked_control_point = 0;
956 clicked_axisview = 0;
957 clicked_routeview = 0; //dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
958 ret = button_press_handler (item, event, FeatureLineItem);
961 case GDK_BUTTON_RELEASE:
962 ret = button_release_handler (item, event, FeatureLineItem);
965 case GDK_MOTION_NOTIFY:
966 ret = motion_handler (item, event);
969 case GDK_ENTER_NOTIFY:
970 ret = enter_handler (item, event, FeatureLineItem);
973 case GDK_LEAVE_NOTIFY:
974 ret = leave_handler (item, event, FeatureLineItem);
985 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, ArdourMarker* /*marker*/)
987 return typed_event (item, event, MarkerItem);
991 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
993 return typed_event (item, event, MarkerBarItem);
997 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
999 return typed_event (item, event, RangeMarkerBarItem);
1003 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1005 return typed_event (item, event, TransportMarkerBarItem);
1009 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1011 return typed_event (item, event, CdMarkerBarItem);
1015 Editor::canvas_videotl_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1017 return typed_event (item, event, VideoBarItem);
1021 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* marker)
1023 return typed_event (item, event, TempoMarkerItem);
1027 Editor::canvas_tempo_curve_event (GdkEvent *event, ArdourCanvas::Item* item, TempoCurve* /*marker*/)
1029 return typed_event (item, event, TempoCurveItem);
1033 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* /*marker*/)
1035 return typed_event (item, event, MeterMarkerItem);
1039 Editor::canvas_ruler_event (GdkEvent *event, ArdourCanvas::Item* item, ItemType type)
1041 bool handled = false;
1043 if (event->type == GDK_SCROLL) {
1045 /* scroll events in the rulers are handled a little differently from
1046 scrolling elsewhere in the canvas.
1049 switch (event->scroll.direction) {
1051 if (Keyboard::modifier_state_equals(event->scroll.state,
1052 Keyboard::ScrollHorizontalModifier)) {
1053 scroll_left_step ();
1054 } else if (UIConfiguration::instance().get_use_mouse_position_as_zoom_focus_on_scroll()) {
1055 temporal_zoom_step_mouse_focus (false);
1057 temporal_zoom_step (false);
1062 case GDK_SCROLL_DOWN:
1063 if (Keyboard::modifier_state_equals(event->scroll.state,
1064 Keyboard::ScrollHorizontalModifier)) {
1065 scroll_right_step ();
1066 } else if (UIConfiguration::instance().get_use_mouse_position_as_zoom_focus_on_scroll()) {
1067 temporal_zoom_step_mouse_focus (true);
1069 temporal_zoom_step (true);
1074 case GDK_SCROLL_LEFT:
1075 scroll_left_half_page ();
1079 case GDK_SCROLL_RIGHT:
1080 scroll_right_half_page ();
1091 return typed_event (item, event, type);
1095 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1097 return typed_event (item, event, TempoBarItem);
1101 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1103 return typed_event (item, event, MeterBarItem);
1107 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
1109 return typed_event (item, event, PlayheadCursorItem);
1113 Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
1115 if (!internal_editing()) {
1119 return typed_event (item, event, NoteItem);
1123 Editor::canvas_drop_zone_event (GdkEvent* event)
1125 GdkEventScroll scroll;
1126 ArdourCanvas::Duple winpos;
1128 switch (event->type) {
1129 case GDK_BUTTON_RELEASE:
1130 if (event->button.button == 1) {
1131 begin_reversible_selection_op (X_("Nowhere Click"));
1132 selection->clear_objects ();
1133 selection->clear_tracks ();
1134 commit_reversible_selection_op ();
1139 /* convert coordinates back into window space so that
1140 we can just call canvas_scroll_event().
1142 winpos = _track_canvas->canvas_to_window (Duple (event->scroll.x, event->scroll.y));
1143 scroll = event->scroll;
1144 scroll.x = winpos.x;
1145 scroll.y = winpos.y;
1146 return canvas_scroll_event (&scroll, true);
1149 case GDK_ENTER_NOTIFY:
1150 return typed_event (_canvas_drop_zone, event, DropZoneItem);
1152 case GDK_LEAVE_NOTIFY:
1153 return typed_event (_canvas_drop_zone, event, DropZoneItem);
1163 Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const& context, int x, int y, guint time)
1165 boost::shared_ptr<Region> region;
1166 boost::shared_ptr<Region> region_copy;
1167 RouteTimeAxisView* rtav;
1172 string target = _track_canvas->drag_dest_find_target (context, _track_canvas->drag_dest_get_target_list());
1174 if (target.empty()) {
1178 event.type = GDK_MOTION_NOTIFY;
1181 /* assume we're dragging with button 1 */
1182 event.motion.state = Gdk::BUTTON1_MASK;
1184 (void) window_event_sample (&event, &px, &py);
1186 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py, false);
1187 bool can_drop = false;
1189 if (tv.first != 0) {
1191 /* over a time axis view of some kind */
1193 rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1195 if (rtav != 0 && rtav->is_track ()) {
1196 /* over a track, not a bus */
1202 /* not over a time axis view, so drop is possible */
1208 if (target == X_("regions")) {
1209 region = _regions->get_dragged_region ();
1216 boost::dynamic_pointer_cast<AudioRegion> (region) != 0 ||
1217 boost::dynamic_pointer_cast<MidiRegion> (region) != 0
1221 /* drop to drop-zone */
1222 context->drag_status (context->get_suggested_action(), time);
1226 if ((boost::dynamic_pointer_cast<AudioRegion> (region) != 0 &&
1227 dynamic_cast<AudioTimeAxisView*> (tv.first) != 0) ||
1228 (boost::dynamic_pointer_cast<MidiRegion> (region) != 0 &&
1229 dynamic_cast<MidiTimeAxisView*> (tv.first) != 0)) {
1236 context->drag_status (context->get_suggested_action(), time);
1240 /* DND originating from outside ardour
1242 * TODO: check if file is audio/midi, allow drops on same track-type only,
1243 * currently: if audio is dropped on a midi-track, it is only added to the region-list
1245 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1246 context->drag_status(Gdk::ACTION_COPY, time);
1248 if ((context->get_actions() & (Gdk::ACTION_COPY | Gdk::ACTION_LINK | Gdk::ACTION_MOVE)) == Gdk::ACTION_COPY) {
1249 context->drag_status(Gdk::ACTION_COPY, time);
1251 context->drag_status(Gdk::ACTION_LINK, time);
1259 context->drag_status (Gdk::DragAction (0), time);
1264 Editor::drop_regions (const Glib::RefPtr<Gdk::DragContext>& /*context*/,
1266 const SelectionData& /*data*/,
1267 guint /*info*/, guint /*time*/,
1268 bool from_region_list)
1274 event.type = GDK_MOTION_NOTIFY;
1277 /* assume we're dragging with button 1 */
1278 event.motion.state = Gdk::BUTTON1_MASK;
1279 samplepos_t const pos = window_event_sample (&event, &px, &py);
1281 boost::shared_ptr<Region> region;
1283 if (from_region_list) {
1284 region = _regions->get_dragged_region ();
1286 region = _sources->get_dragged_region ();
1289 if (!region) { return; }
1291 RouteTimeAxisView* rtav = 0;
1292 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py, false);
1294 if (tv.first != 0) {
1295 rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1298 if (boost::dynamic_pointer_cast<AudioRegion> (region)) {
1299 uint32_t output_chan = region->n_channels();
1300 if ((Config->get_output_auto_connect() & AutoConnectMaster) && session()->master_out()) {
1301 output_chan = session()->master_out()->n_inputs().n_audio();
1303 list<boost::shared_ptr<AudioTrack> > audio_tracks;
1304 audio_tracks = session()->new_audio_track (region->n_channels(), output_chan, 0, 1, region->name(), PresentationInfo::max_order);
1305 rtav = dynamic_cast<RouteTimeAxisView*> (time_axis_view_from_stripable (audio_tracks.front()));
1306 } else if (boost::dynamic_pointer_cast<MidiRegion> (region)) {
1307 ChanCount one_midi_port (DataType::MIDI, 1);
1308 list<boost::shared_ptr<MidiTrack> > midi_tracks;
1309 midi_tracks = session()->new_midi_track (one_midi_port, one_midi_port,
1310 Config->get_strict_io () || Profile->get_mixbus (),
1311 boost::shared_ptr<ARDOUR::PluginInfo>(),
1312 (ARDOUR::Plugin::PresetRecord*) 0,
1313 (ARDOUR::RouteGroup*) 0, 1, region->name(), PresentationInfo::max_order);
1314 rtav = dynamic_cast<RouteTimeAxisView*> (time_axis_view_from_stripable (midi_tracks.front()));
1319 error << _("Could not create new track after region placed in the drop zone") << endmsg;
1324 if (rtav != 0 && rtav->is_track ()) {
1325 boost::shared_ptr<Region> region_copy = RegionFactory::create (region, true);
1327 if ((boost::dynamic_pointer_cast<AudioRegion> (region_copy) != 0 && dynamic_cast<AudioTimeAxisView*> (rtav) != 0) ||
1328 (boost::dynamic_pointer_cast<MidiRegion> (region_copy) != 0 && dynamic_cast<MidiTimeAxisView*> (rtav) != 0)) {
1329 _drags->set (new RegionInsertDrag (this, region_copy, rtav, pos), &event);
1330 _drags->end_grab (&event);
1336 Editor::key_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType)
1342 Editor::key_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType type)
1345 bool handled = false;
1348 case TempoMarkerItem:
1349 switch (event->key.keyval) {
1351 remove_tempo_marker (item);
1359 case MeterMarkerItem:
1360 switch (event->key.keyval) {
1362 remove_meter_marker (item);