2 Copyright (C) 2000 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "pbd/stacktrace.h"
27 #include "ardour/audio_track.h"
28 #include "ardour/midi_track.h"
29 #include "ardour/midi_region.h"
30 #include "ardour/region_factory.h"
31 #include "ardour/profile.h"
33 #include "canvas/canvas.h"
34 #include "canvas/text.h"
35 #include "canvas/scroll_group.h"
39 #include "public_editor.h"
40 #include "audio_region_view.h"
41 #include "audio_streamview.h"
42 #include "audio_time_axis.h"
43 #include "region_gain_line.h"
44 #include "automation_line.h"
45 #include "automation_time_axis.h"
46 #include "automation_line.h"
47 #include "control_point.h"
48 #include "editor_drag.h"
49 #include "midi_time_axis.h"
50 #include "editor_regions.h"
51 #include "ui_config.h"
52 #include "verbose_cursor.h"
57 using namespace ARDOUR;
60 using namespace ArdourCanvas;
62 using Gtkmm2ext::Keyboard;
65 Editor::track_canvas_scroll (GdkEventScroll* ev)
67 int direction = ev->direction;
69 /* this event arrives without transformation by the canvas, so we have
70 * to transform the coordinates to be able to look things up.
73 Duple event_coords = _track_canvas->window_to_canvas (Duple (ev->x, ev->y));
77 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) {
78 if (UIConfiguration::instance().get_use_mouse_position_as_zoom_focus_on_scroll()) {
79 temporal_zoom_step_mouse_focus (false);
81 temporal_zoom_step (false);
84 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) {
87 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) {
88 if (!current_stepping_trackview) {
89 step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
90 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (event_coords.y, false);
91 current_stepping_trackview = p.first;
92 if (!current_stepping_trackview) {
96 last_track_height_step_timestamp = get_microseconds();
97 current_stepping_trackview->step_height (false);
100 scroll_up_one_track ();
105 case GDK_SCROLL_DOWN:
106 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) {
107 if (UIConfiguration::instance().get_use_mouse_position_as_zoom_focus_on_scroll()) {
108 temporal_zoom_step_mouse_focus (true);
110 temporal_zoom_step (true);
113 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) {
114 scroll_right_step ();
116 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) {
117 if (!current_stepping_trackview) {
118 step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
119 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (event_coords.y, false);
120 current_stepping_trackview = p.first;
121 if (!current_stepping_trackview) {
125 last_track_height_step_timestamp = get_microseconds();
126 current_stepping_trackview->step_height (true);
129 scroll_down_one_track ();
134 case GDK_SCROLL_LEFT:
139 case GDK_SCROLL_RIGHT:
140 scroll_right_step ();
153 Editor::canvas_scroll_event (GdkEventScroll *event, bool from_canvas)
156 boost::optional<ArdourCanvas::Rect> rulers = _time_markers_group->bounding_box();
157 if (rulers && rulers->contains (Duple (event->x, event->y))) {
158 return canvas_ruler_event ((GdkEvent*) event, timecode_ruler, TimecodeRulerItem);
162 _track_canvas->grab_focus();
163 return track_canvas_scroll (event);
167 Editor::track_canvas_button_press_event (GdkEventButton *event)
169 _track_canvas->grab_focus();
170 if (!Keyboard::is_context_menu_event (event)) {
171 begin_reversible_selection_op (X_("Clear Selection Click (track canvas)"));
173 commit_reversible_selection_op();
179 Editor::track_canvas_button_release_event (GdkEventButton *event)
181 if (!Keyboard::is_context_menu_event (event)) {
182 if (_drags->active ()) {
183 _drags->end_grab ((GdkEvent*) event);
190 Editor::track_canvas_motion_notify_event (GdkEventMotion */*event*/)
193 /* keep those motion events coming */
194 _track_canvas->get_pointer (x, y);
199 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
203 switch (event->type) {
204 case GDK_BUTTON_PRESS:
205 case GDK_2BUTTON_PRESS:
206 case GDK_3BUTTON_PRESS:
207 ret = button_press_handler (item, event, type);
209 case GDK_BUTTON_RELEASE:
210 ret = button_release_handler (item, event, type);
212 case GDK_MOTION_NOTIFY:
213 ret = motion_handler (item, event);
216 case GDK_ENTER_NOTIFY:
217 ret = enter_handler (item, event, type);
220 case GDK_LEAVE_NOTIFY:
221 ret = leave_handler (item, event, type);
225 ret = key_press_handler (item, event, type);
228 case GDK_KEY_RELEASE:
229 ret = key_release_handler (item, event, type);
239 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
243 if (!rv->sensitive ()) {
247 switch (event->type) {
248 case GDK_BUTTON_PRESS:
249 case GDK_2BUTTON_PRESS:
250 case GDK_3BUTTON_PRESS:
251 clicked_regionview = rv;
252 clicked_control_point = 0;
253 clicked_axisview = &rv->get_time_axis_view();
254 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
255 ret = button_press_handler (item, event, RegionItem);
258 case GDK_BUTTON_RELEASE:
259 ret = button_release_handler (item, event, RegionItem);
262 case GDK_MOTION_NOTIFY:
263 ret = motion_handler (item, event);
266 case GDK_ENTER_NOTIFY:
267 set_entered_regionview (rv);
268 ret = enter_handler (item, event, RegionItem);
271 case GDK_LEAVE_NOTIFY:
272 if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
273 set_entered_regionview (0);
274 ret = leave_handler (item, event, RegionItem);
286 Editor::canvas_wave_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
288 /* we only care about enter events here, required for mouse/cursor
289 * tracking. there is a non-linear (non-child/non-parent) relationship
290 * between various components of a regionview and so when we leave one
291 * of them (e.g. a trim handle) and enter another (e.g. the waveview)
292 * no other items get notified. enter/leave handling does not propagate
293 * in the same way as other events, so we need to catch this because
294 * entering (and leaving) the waveview is equivalent to
295 * entering/leaving the regionview (which is why it is passed in as a
298 * And in fact, we really only care about enter events.
303 if (!rv->sensitive ()) {
307 switch (event->type) {
308 case GDK_ENTER_NOTIFY:
309 set_entered_regionview (rv);
310 ret = enter_handler (item, event, WaveItem);
322 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
326 switch (event->type) {
327 case GDK_BUTTON_PRESS:
328 case GDK_2BUTTON_PRESS:
329 case GDK_3BUTTON_PRESS:
330 clicked_regionview = 0;
331 clicked_control_point = 0;
332 clicked_axisview = tv;
333 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
334 ret = button_press_handler (item, event, StreamItem);
337 case GDK_BUTTON_RELEASE:
338 ret = button_release_handler (item, event, StreamItem);
341 case GDK_MOTION_NOTIFY:
342 ret = motion_handler (item, event);
345 case GDK_ENTER_NOTIFY:
346 set_entered_track (tv);
347 ret = enter_handler (item, event, StreamItem);
350 case GDK_LEAVE_NOTIFY:
351 if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
352 set_entered_track (0);
354 ret = leave_handler (item, event, StreamItem);
365 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
369 switch (event->type) {
370 case GDK_BUTTON_PRESS:
371 case GDK_2BUTTON_PRESS:
372 case GDK_3BUTTON_PRESS:
373 clicked_regionview = 0;
374 clicked_control_point = 0;
375 clicked_axisview = atv;
376 clicked_routeview = 0;
377 ret = button_press_handler (item, event, AutomationTrackItem);
380 case GDK_BUTTON_RELEASE:
381 ret = button_release_handler (item, event, AutomationTrackItem);
384 case GDK_MOTION_NOTIFY:
385 ret = motion_handler (item, event);
388 case GDK_ENTER_NOTIFY:
389 ret = enter_handler (item, event, AutomationTrackItem);
392 case GDK_LEAVE_NOTIFY:
393 ret = leave_handler (item, event, AutomationTrackItem);
404 Editor::canvas_start_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
406 if (!rv->sensitive()) {
410 switch (event->type) {
411 case GDK_BUTTON_PRESS:
412 clicked_regionview = rv;
413 clicked_control_point = 0;
414 clicked_axisview = &rv->get_time_axis_view();
415 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
416 if (event->button.button == 3) {
417 return button_press_handler (item, event, StartCrossFadeItem);
421 case GDK_BUTTON_RELEASE:
422 if (event->button.button == 3) {
423 return button_release_handler (item, event, StartCrossFadeItem);
432 /* In Mixbus, the crossfade area is used to trim the region while leaving the fade anchor intact (see preserve_fade_anchor)*/
433 /* however in A3 this feature is unfinished, and it might be better to do it with a modifier-trim instead, anyway */
434 /* if we return RegionItem here then we avoid the issue until it is resolved later */
435 return typed_event (item, event, RegionItem); // StartCrossFadeItem);
439 Editor::canvas_end_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
441 if (!rv->sensitive()) {
445 switch (event->type) {
446 case GDK_BUTTON_PRESS:
447 clicked_regionview = rv;
448 clicked_control_point = 0;
449 clicked_axisview = &rv->get_time_axis_view();
450 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
451 if (event->button.button == 3) {
452 return button_press_handler (item, event, EndCrossFadeItem);
456 case GDK_BUTTON_RELEASE:
457 if (event->button.button == 3) {
458 return button_release_handler (item, event, EndCrossFadeItem);
467 /* In Mixbus, the crossfade area is used to trim the region while leaving the fade anchor intact (see preserve_fade_anchor)*/
468 /* however in A3 this feature is unfinished, and it might be better to do it with a modifier-trim instead, anyway */
469 /* if we return RegionItem here then we avoid the issue until it is resolved later */
470 return typed_event (item, event, RegionItem); // EndCrossFadeItem);
474 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
476 /* we handle only button 3 press/release events */
478 if (!rv->sensitive()) {
482 switch (event->type) {
483 case GDK_BUTTON_PRESS:
484 clicked_regionview = rv;
485 clicked_control_point = 0;
486 clicked_axisview = &rv->get_time_axis_view();
487 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
488 if (event->button.button == 3) {
489 return button_press_handler (item, event, FadeInItem);
493 case GDK_BUTTON_RELEASE:
494 if (event->button.button == 3) {
495 return button_release_handler (item, event, FadeInItem);
504 /* proxy for the regionview, except enter/leave events */
506 if (event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) {
509 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
514 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv, bool trim)
518 if (!rv->sensitive()) {
522 switch (event->type) {
523 case GDK_BUTTON_PRESS:
524 case GDK_2BUTTON_PRESS:
525 case GDK_3BUTTON_PRESS:
526 clicked_regionview = rv;
527 clicked_control_point = 0;
528 clicked_axisview = &rv->get_time_axis_view();
529 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
530 ret = button_press_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
533 case GDK_BUTTON_RELEASE:
534 ret = button_release_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
535 maybe_locate_with_edit_preroll ( rv->region()->position() );
538 case GDK_MOTION_NOTIFY:
539 ret = motion_handler (item, event);
542 case GDK_ENTER_NOTIFY:
543 ret = enter_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
546 case GDK_LEAVE_NOTIFY:
547 ret = leave_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
558 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
560 /* we handle only button 3 press/release events */
562 if (!rv->sensitive()) {
566 switch (event->type) {
567 case GDK_BUTTON_PRESS:
568 clicked_regionview = rv;
569 clicked_control_point = 0;
570 clicked_axisview = &rv->get_time_axis_view();
571 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
572 if (event->button.button == 3) {
573 return button_press_handler (item, event, FadeOutItem);
577 case GDK_BUTTON_RELEASE:
578 if (event->button.button == 3) {
579 return button_release_handler (item, event, FadeOutItem);
588 /* proxy for the regionview, except enter/leave events */
590 if (event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) {
593 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
598 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv, bool trim)
602 if (!rv->sensitive()) {
606 switch (event->type) {
607 case GDK_BUTTON_PRESS:
608 case GDK_2BUTTON_PRESS:
609 case GDK_3BUTTON_PRESS:
610 clicked_regionview = rv;
611 clicked_control_point = 0;
612 clicked_axisview = &rv->get_time_axis_view();
613 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
614 ret = button_press_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
617 case GDK_BUTTON_RELEASE:
618 ret = button_release_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
619 maybe_locate_with_edit_preroll ( rv->region()->last_frame() - rv->get_fade_out_shape_width() );
622 case GDK_MOTION_NOTIFY:
623 ret = motion_handler (item, event);
626 case GDK_ENTER_NOTIFY:
627 ret = enter_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
630 case GDK_LEAVE_NOTIFY:
631 ret = leave_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
641 struct DescendingRegionLayerSorter {
642 bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
643 return a->layer() > b->layer();
648 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
650 switch (event->type) {
651 case GDK_BUTTON_PRESS:
652 case GDK_2BUTTON_PRESS:
653 case GDK_3BUTTON_PRESS:
654 clicked_control_point = cp;
655 clicked_axisview = &cp->line().trackview;
656 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
657 clicked_regionview = 0;
663 case GDK_SCROLL_DOWN:
670 return typed_event (item, event, ControlPointItem);
674 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
677 AudioRegionGainLine* gl;
678 if ((gl = dynamic_cast<AudioRegionGainLine*> (al)) != 0) {
680 if (event->type == GDK_BUTTON_PRESS) {
681 clicked_regionview = &gl->region_view ();
684 type = AutomationLineItem;
685 if (event->type == GDK_BUTTON_PRESS) {
686 clicked_regionview = 0;
690 clicked_control_point = 0;
691 clicked_axisview = &al->trackview;
692 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
694 return typed_event (item, event, type);
698 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
702 switch (event->type) {
703 case GDK_BUTTON_PRESS:
704 case GDK_2BUTTON_PRESS:
705 case GDK_3BUTTON_PRESS:
706 clicked_selection = rect->id;
707 ret = button_press_handler (item, event, SelectionItem);
709 case GDK_BUTTON_RELEASE:
710 ret = button_release_handler (item, event, SelectionItem);
712 case GDK_MOTION_NOTIFY:
713 ret = motion_handler (item, event);
715 /* Don't need these at the moment. */
716 case GDK_ENTER_NOTIFY:
717 ret = enter_handler (item, event, SelectionItem);
720 case GDK_LEAVE_NOTIFY:
721 ret = leave_handler (item, event, SelectionItem);
732 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
736 switch (event->type) {
737 case GDK_BUTTON_PRESS:
738 case GDK_2BUTTON_PRESS:
739 case GDK_3BUTTON_PRESS:
740 clicked_selection = rect->id;
741 ret = button_press_handler (item, event, StartSelectionTrimItem);
743 case GDK_BUTTON_RELEASE:
744 ret = button_release_handler (item, event, StartSelectionTrimItem);
746 case GDK_MOTION_NOTIFY:
747 ret = motion_handler (item, event);
749 case GDK_ENTER_NOTIFY:
750 ret = enter_handler (item, event, StartSelectionTrimItem);
753 case GDK_LEAVE_NOTIFY:
754 ret = leave_handler (item, event, StartSelectionTrimItem);
765 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
769 switch (event->type) {
770 case GDK_BUTTON_PRESS:
771 case GDK_2BUTTON_PRESS:
772 case GDK_3BUTTON_PRESS:
773 clicked_selection = rect->id;
774 ret = button_press_handler (item, event, EndSelectionTrimItem);
776 case GDK_BUTTON_RELEASE:
777 ret = button_release_handler (item, event, EndSelectionTrimItem);
779 case GDK_MOTION_NOTIFY:
780 ret = motion_handler (item, event);
782 case GDK_ENTER_NOTIFY:
783 ret = enter_handler (item, event, EndSelectionTrimItem);
786 case GDK_LEAVE_NOTIFY:
787 ret = leave_handler (item, event, EndSelectionTrimItem);
798 Editor::canvas_frame_handle_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
802 /* frame handles are not active when in internal edit mode, because actual notes
803 might be in the area occupied by the handle - we want them to be editable as normal.
806 if (internal_editing() || !rv->sensitive()) {
810 /* NOTE: frame handles pretend to be the colored trim bar from an event handling
811 perspective. XXX change this ??
816 if (item->get_data ("isleft")) {
817 type = LeftFrameHandle;
819 type = RightFrameHandle;
822 switch (event->type) {
823 case GDK_BUTTON_PRESS:
824 case GDK_2BUTTON_PRESS:
825 case GDK_3BUTTON_PRESS:
826 clicked_regionview = rv;
827 clicked_control_point = 0;
828 clicked_axisview = &clicked_regionview->get_time_axis_view();
829 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
830 ret = button_press_handler (item, event, type);
832 case GDK_BUTTON_RELEASE:
833 ret = button_release_handler (item, event, type);
835 case GDK_MOTION_NOTIFY:
836 ret = motion_handler (item, event);
838 case GDK_ENTER_NOTIFY:
839 ret = enter_handler (item, event, type);
842 case GDK_LEAVE_NOTIFY:
843 ret = leave_handler (item, event, type);
855 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
859 if (!rv->sensitive()) {
863 switch (event->type) {
864 case GDK_BUTTON_PRESS:
865 case GDK_2BUTTON_PRESS:
866 case GDK_3BUTTON_PRESS:
867 clicked_regionview = rv;
868 clicked_control_point = 0;
869 clicked_axisview = &clicked_regionview->get_time_axis_view();
870 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
871 ret = button_press_handler (item, event, RegionViewNameHighlight);
873 case GDK_BUTTON_RELEASE:
874 ret = button_release_handler (item, event, RegionViewNameHighlight);
876 case GDK_MOTION_NOTIFY:
877 motion_handler (item, event);
878 ret = true; // force this to avoid progagating the event into the regionview
880 case GDK_ENTER_NOTIFY:
881 ret = enter_handler (item, event, RegionViewNameHighlight);
884 case GDK_LEAVE_NOTIFY:
885 ret = leave_handler (item, event, RegionViewNameHighlight);
896 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
900 if (!rv->sensitive()) {
904 switch (event->type) {
905 case GDK_BUTTON_PRESS:
906 case GDK_2BUTTON_PRESS:
907 case GDK_3BUTTON_PRESS:
908 clicked_regionview = rv;
909 clicked_control_point = 0;
910 clicked_axisview = &clicked_regionview->get_time_axis_view();
911 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
912 ret = button_press_handler (item, event, RegionViewName);
914 case GDK_BUTTON_RELEASE:
915 ret = button_release_handler (item, event, RegionViewName);
917 case GDK_MOTION_NOTIFY:
918 ret = motion_handler (item, event);
920 case GDK_ENTER_NOTIFY:
921 ret = enter_handler (item, event, RegionViewName);
924 case GDK_LEAVE_NOTIFY:
925 ret = leave_handler (item, event, RegionViewName);
936 Editor::canvas_feature_line_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView*)
940 switch (event->type) {
941 case GDK_BUTTON_PRESS:
942 case GDK_2BUTTON_PRESS:
943 case GDK_3BUTTON_PRESS:
944 clicked_regionview = 0;
945 clicked_control_point = 0;
946 clicked_axisview = 0;
947 clicked_routeview = 0; //dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
948 ret = button_press_handler (item, event, FeatureLineItem);
951 case GDK_BUTTON_RELEASE:
952 ret = button_release_handler (item, event, FeatureLineItem);
955 case GDK_MOTION_NOTIFY:
956 ret = motion_handler (item, event);
959 case GDK_ENTER_NOTIFY:
960 ret = enter_handler (item, event, FeatureLineItem);
963 case GDK_LEAVE_NOTIFY:
964 ret = leave_handler (item, event, FeatureLineItem);
975 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, ArdourMarker* /*marker*/)
977 return typed_event (item, event, MarkerItem);
981 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
983 return typed_event (item, event, MarkerBarItem);
987 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
989 return typed_event (item, event, RangeMarkerBarItem);
993 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
995 return typed_event (item, event, TransportMarkerBarItem);
999 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1001 return typed_event (item, event, CdMarkerBarItem);
1005 Editor::canvas_videotl_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1007 return typed_event (item, event, VideoBarItem);
1011 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* /*marker*/)
1013 return typed_event (item, event, TempoMarkerItem);
1017 Editor::canvas_tempo_curve_event (GdkEvent *event, ArdourCanvas::Item* item, TempoCurve* /*marker*/)
1019 return typed_event (item, event, TempoCurveItem);
1023 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* /*marker*/)
1025 return typed_event (item, event, MeterMarkerItem);
1029 Editor::canvas_ruler_event (GdkEvent *event, ArdourCanvas::Item* item, ItemType type)
1031 bool handled = false;
1033 if (event->type == GDK_SCROLL) {
1035 /* scroll events in the rulers are handled a little differently from
1036 scrolling elsewhere in the canvas.
1039 switch (event->scroll.direction) {
1041 if (Keyboard::modifier_state_equals(event->scroll.state,
1042 Keyboard::ScrollHorizontalModifier)) {
1043 scroll_left_step ();
1044 } else if (UIConfiguration::instance().get_use_mouse_position_as_zoom_focus_on_scroll()) {
1045 temporal_zoom_step_mouse_focus (false);
1047 temporal_zoom_step (false);
1052 case GDK_SCROLL_DOWN:
1053 if (Keyboard::modifier_state_equals(event->scroll.state,
1054 Keyboard::ScrollHorizontalModifier)) {
1055 scroll_right_step ();
1056 } else if (UIConfiguration::instance().get_use_mouse_position_as_zoom_focus_on_scroll()) {
1057 temporal_zoom_step_mouse_focus (true);
1059 temporal_zoom_step (true);
1064 case GDK_SCROLL_LEFT:
1065 scroll_left_half_page ();
1069 case GDK_SCROLL_RIGHT:
1070 scroll_right_half_page ();
1081 return typed_event (item, event, type);
1085 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1087 return typed_event (item, event, TempoBarItem);
1091 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1093 return typed_event (item, event, MeterBarItem);
1097 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
1099 return typed_event (item, event, PlayheadCursorItem);
1103 Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
1105 if (!internal_editing()) {
1109 return typed_event (item, event, NoteItem);
1113 Editor::canvas_drop_zone_event (GdkEvent* event)
1115 GdkEventScroll scroll;
1116 ArdourCanvas::Duple winpos;
1118 switch (event->type) {
1119 case GDK_BUTTON_RELEASE:
1120 if (event->button.button == 1) {
1121 begin_reversible_selection_op (X_("Nowhere Click"));
1122 selection->clear_objects ();
1123 selection->clear_tracks ();
1124 commit_reversible_selection_op ();
1129 /* convert coordinates back into window space so that
1130 we can just call canvas_scroll_event().
1132 winpos = _track_canvas->canvas_to_window (Duple (event->scroll.x, event->scroll.y));
1133 scroll = event->scroll;
1134 scroll.x = winpos.x;
1135 scroll.y = winpos.y;
1136 return canvas_scroll_event (&scroll, true);
1139 case GDK_ENTER_NOTIFY:
1140 return typed_event (_canvas_drop_zone, event, DropZoneItem);
1142 case GDK_LEAVE_NOTIFY:
1143 return typed_event (_canvas_drop_zone, event, DropZoneItem);
1153 Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const& context, int x, int y, guint time)
1155 boost::shared_ptr<Region> region;
1156 boost::shared_ptr<Region> region_copy;
1157 RouteTimeAxisView* rtav;
1162 string target = _track_canvas->drag_dest_find_target (context, _track_canvas->drag_dest_get_target_list());
1164 if (target.empty()) {
1168 event.type = GDK_MOTION_NOTIFY;
1171 /* assume we're dragging with button 1 */
1172 event.motion.state = Gdk::BUTTON1_MASK;
1174 (void) window_event_sample (&event, &px, &py);
1176 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py, false);
1177 bool can_drop = false;
1179 if (tv.first != 0) {
1181 /* over a time axis view of some kind */
1183 rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1185 if (rtav != 0 && rtav->is_track ()) {
1186 /* over a track, not a bus */
1192 /* not over a time axis view, so drop is possible */
1197 region = _regions->get_dragged_region ();
1203 boost::dynamic_pointer_cast<AudioRegion> (region) != 0 ||
1204 boost::dynamic_pointer_cast<MidiRegion> (region) != 0
1208 /* drop to drop-zone */
1209 context->drag_status (context->get_suggested_action(), time);
1213 if ((boost::dynamic_pointer_cast<AudioRegion> (region) != 0 &&
1214 dynamic_cast<AudioTimeAxisView*> (tv.first) != 0) ||
1215 (boost::dynamic_pointer_cast<MidiRegion> (region) != 0 &&
1216 dynamic_cast<MidiTimeAxisView*> (tv.first) != 0)) {
1223 context->drag_status (context->get_suggested_action(), time);
1227 /* DND originating from outside ardour
1229 * TODO: check if file is audio/midi, allow drops on same track-type only,
1230 * currently: if audio is dropped on a midi-track, it is only added to the region-list
1232 if (UIConfiguration::instance().get_only_copy_imported_files()) {
1233 context->drag_status(Gdk::ACTION_COPY, time);
1235 if ((context->get_actions() & (Gdk::ACTION_COPY | Gdk::ACTION_LINK | Gdk::ACTION_MOVE)) == Gdk::ACTION_COPY) {
1236 context->drag_status(Gdk::ACTION_COPY, time);
1238 context->drag_status(Gdk::ACTION_LINK, time);
1246 context->drag_status (Gdk::DragAction (0), time);
1251 Editor::drop_regions (const Glib::RefPtr<Gdk::DragContext>& /*context*/,
1253 const SelectionData& /*data*/,
1254 guint /*info*/, guint /*time*/)
1260 event.type = GDK_MOTION_NOTIFY;
1263 /* assume we're dragging with button 1 */
1264 event.motion.state = Gdk::BUTTON1_MASK;
1265 framepos_t const pos = window_event_sample (&event, &px, &py);
1267 boost::shared_ptr<Region> region = _regions->get_dragged_region ();
1268 if (!region) { return; }
1270 RouteTimeAxisView* rtav = 0;
1271 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py, false);
1273 if (tv.first != 0) {
1274 rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1277 if (boost::dynamic_pointer_cast<AudioRegion> (region)) {
1278 uint32_t output_chan = region->n_channels();
1279 if ((Config->get_output_auto_connect() & AutoConnectMaster) && session()->master_out()) {
1280 output_chan = session()->master_out()->n_inputs().n_audio();
1282 list<boost::shared_ptr<AudioTrack> > audio_tracks;
1283 audio_tracks = session()->new_audio_track (region->n_channels(), output_chan, 0, 1, region->name(), PresentationInfo::max_order);
1284 rtav = dynamic_cast<RouteTimeAxisView*> (axis_view_from_stripable (audio_tracks.front()));
1285 } else if (boost::dynamic_pointer_cast<MidiRegion> (region)) {
1286 ChanCount one_midi_port (DataType::MIDI, 1);
1287 list<boost::shared_ptr<MidiTrack> > midi_tracks;
1288 midi_tracks = session()->new_midi_track (one_midi_port, one_midi_port, boost::shared_ptr<ARDOUR::PluginInfo>(),
1289 (ARDOUR::Plugin::PresetRecord*) 0,
1290 (ARDOUR::RouteGroup*) 0, 1, region->name(), PresentationInfo::max_order);
1291 rtav = dynamic_cast<RouteTimeAxisView*> (axis_view_from_stripable (midi_tracks.front()));
1296 error << _("Could not create new track after region placed in the drop zone") << endmsg;
1301 if (rtav != 0 && rtav->is_track ()) {
1302 boost::shared_ptr<Region> region_copy = RegionFactory::create (region, true);
1304 if ((boost::dynamic_pointer_cast<AudioRegion> (region_copy) != 0 && dynamic_cast<AudioTimeAxisView*> (rtav) != 0) ||
1305 (boost::dynamic_pointer_cast<MidiRegion> (region_copy) != 0 && dynamic_cast<MidiTimeAxisView*> (rtav) != 0)) {
1306 _drags->set (new RegionInsertDrag (this, region_copy, rtav, pos), &event);
1307 _drags->end_grab (0);
1313 Editor::key_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType)
1319 Editor::key_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType type)
1322 bool handled = false;
1325 case TempoMarkerItem:
1326 switch (event->key.keyval) {
1328 remove_tempo_marker (item);
1336 case MeterMarkerItem:
1337 switch (event->key.keyval) {
1339 remove_meter_marker (item);