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/midi_region.h"
28 #include "ardour/region_factory.h"
29 #include "ardour/profile.h"
31 #include "canvas/canvas.h"
32 #include "canvas/text.h"
36 #include "public_editor.h"
37 #include "audio_region_view.h"
38 #include "audio_streamview.h"
39 #include "audio_time_axis.h"
40 #include "region_gain_line.h"
41 #include "automation_line.h"
42 #include "automation_time_axis.h"
43 #include "automation_line.h"
44 #include "control_point.h"
45 #include "editor_drag.h"
46 #include "midi_time_axis.h"
47 #include "editor_regions.h"
48 #include "verbose_cursor.h"
53 using namespace ARDOUR;
56 using namespace ArdourCanvas;
58 using Gtkmm2ext::Keyboard;
61 Editor::track_canvas_scroll (GdkEventScroll* ev)
63 if (Keyboard::some_magic_widget_has_focus()) {
68 int direction = ev->direction;
70 /* this event arrives without transformation by the canvas, so we have
71 * to transform the coordinates to be able to look things up.
74 Duple event_coords = _track_canvas->window_to_canvas (Duple (ev->x, ev->y));
79 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) {
80 //for mouse-wheel zoom, force zoom-focus to mouse
81 Editing::ZoomFocus temp_focus = zoom_focus;
82 zoom_focus = Editing::ZoomFocusMouse;
83 temporal_zoom_step (false);
84 zoom_focus = temp_focus;
86 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) {
87 direction = GDK_SCROLL_LEFT;
89 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) {
90 if (!current_stepping_trackview) {
91 step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
92 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (event_coords.y, false);
93 current_stepping_trackview = p.first;
94 if (!current_stepping_trackview) {
98 last_track_height_step_timestamp = get_microseconds();
99 current_stepping_trackview->step_height (false);
102 scroll_tracks_up_line ();
107 case GDK_SCROLL_DOWN:
108 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) {
109 //for mouse-wheel zoom, force zoom-focus to mouse
110 Editing::ZoomFocus temp_focus = zoom_focus;
111 zoom_focus = Editing::ZoomFocusMouse;
112 temporal_zoom_step (true);
113 zoom_focus = temp_focus;
115 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) {
116 direction = GDK_SCROLL_RIGHT;
118 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) {
119 if (!current_stepping_trackview) {
120 step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
121 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (event_coords.y, false);
122 current_stepping_trackview = p.first;
123 if (!current_stepping_trackview) {
127 last_track_height_step_timestamp = get_microseconds();
128 current_stepping_trackview->step_height (true);
131 scroll_tracks_down_line ();
136 case GDK_SCROLL_LEFT:
137 xdelta = (current_page_samples() / 8);
138 if (leftmost_frame > xdelta) {
139 reset_x_origin (leftmost_frame - xdelta);
145 case GDK_SCROLL_RIGHT:
146 xdelta = (current_page_samples() / 8);
147 if (max_framepos - xdelta > leftmost_frame) {
148 reset_x_origin (leftmost_frame + xdelta);
150 reset_x_origin (max_framepos - current_page_samples());
163 Editor::canvas_scroll_event (GdkEventScroll *event)
165 boost::optional<Rect> rulers = _time_markers_group->bounding_box();
166 if (rulers && rulers->contains (Duple (event->x, event->y))) {
167 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*/)
178 _track_canvas->grab_focus();
183 Editor::track_canvas_button_release_event (GdkEventButton *event)
185 if (_drags->active ()) {
186 _drags->end_grab ((GdkEvent*) event);
192 Editor::track_canvas_motion_notify_event (GdkEventMotion */*event*/)
195 /* keep those motion events coming */
196 _track_canvas->get_pointer (x, y);
201 Editor::track_canvas_motion (GdkEvent *ev)
203 if (_verbose_cursor->visible ()) {
204 _verbose_cursor->set_position (ev->motion.x + 10, ev->motion.y + 10);
211 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
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 if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
280 set_entered_regionview (rv);
285 case GDK_LEAVE_NOTIFY:
286 if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
287 set_entered_regionview (0);
300 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
304 switch (event->type) {
305 case GDK_BUTTON_PRESS:
306 case GDK_2BUTTON_PRESS:
307 case GDK_3BUTTON_PRESS:
308 clicked_regionview = 0;
309 clicked_control_point = 0;
310 clicked_axisview = tv;
311 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
312 ret = button_press_handler (item, event, StreamItem);
315 case GDK_BUTTON_RELEASE:
316 ret = button_release_handler (item, event, StreamItem);
319 case GDK_MOTION_NOTIFY:
320 ret = motion_handler (item, event);
323 case GDK_ENTER_NOTIFY:
324 set_entered_track (tv);
328 case GDK_LEAVE_NOTIFY:
329 set_entered_track (0);
340 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
344 switch (event->type) {
345 case GDK_BUTTON_PRESS:
346 case GDK_2BUTTON_PRESS:
347 case GDK_3BUTTON_PRESS:
348 clicked_regionview = 0;
349 clicked_control_point = 0;
350 clicked_axisview = atv;
351 clicked_routeview = 0;
352 ret = button_press_handler (item, event, AutomationTrackItem);
355 case GDK_BUTTON_RELEASE:
356 ret = button_release_handler (item, event, AutomationTrackItem);
359 case GDK_MOTION_NOTIFY:
360 ret = motion_handler (item, event);
363 case GDK_ENTER_NOTIFY:
364 ret = enter_handler (item, event, AutomationTrackItem);
367 case GDK_LEAVE_NOTIFY:
368 ret = leave_handler (item, event, AutomationTrackItem);
379 Editor::canvas_start_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
381 if (!rv->sensitive()) {
385 switch (event->type) {
386 case GDK_BUTTON_PRESS:
387 clicked_regionview = rv;
388 clicked_control_point = 0;
389 clicked_axisview = &rv->get_time_axis_view();
390 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
391 if (event->button.button == 3) {
392 return button_press_handler (item, event, StartCrossFadeItem);
396 case GDK_BUTTON_RELEASE:
397 if (event->button.button == 3) {
398 return button_release_handler (item, event, StartCrossFadeItem);
407 /* In Mixbus, the crossfade area is used to trim the region while leaving the fade anchor intact (see preserve_fade_anchor)*/
408 /* however in A3 this feature is unfinished, and it might be better to do it with a modifier-trim instead, anyway */
409 /* if we return RegionItem here then we avoid the issue until it is resolved later */
410 return typed_event (item, event, RegionItem); // StartCrossFadeItem);
414 Editor::canvas_end_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
416 if (!rv->sensitive()) {
420 switch (event->type) {
421 case GDK_BUTTON_PRESS:
422 clicked_regionview = rv;
423 clicked_control_point = 0;
424 clicked_axisview = &rv->get_time_axis_view();
425 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
426 if (event->button.button == 3) {
427 return button_press_handler (item, event, EndCrossFadeItem);
431 case GDK_BUTTON_RELEASE:
432 if (event->button.button == 3) {
433 return button_release_handler (item, event, EndCrossFadeItem);
442 /* In Mixbus, the crossfade area is used to trim the region while leaving the fade anchor intact (see preserve_fade_anchor)*/
443 /* however in A3 this feature is unfinished, and it might be better to do it with a modifier-trim instead, anyway */
444 /* if we return RegionItem here then we avoid the issue until it is resolved later */
445 return typed_event (item, event, RegionItem); // EndCrossFadeItem);
449 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
451 /* we handle only button 3 press/release events */
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, FadeInItem);
468 case GDK_BUTTON_RELEASE:
469 if (event->button.button == 3) {
470 return button_release_handler (item, event, FadeInItem);
479 /* proxy for the regionview, except enter/leave events */
481 if (event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) {
484 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
489 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv, bool trim)
493 if (!rv->sensitive()) {
497 switch (event->type) {
498 case GDK_BUTTON_PRESS:
499 case GDK_2BUTTON_PRESS:
500 case GDK_3BUTTON_PRESS:
501 clicked_regionview = rv;
502 clicked_control_point = 0;
503 clicked_axisview = &rv->get_time_axis_view();
504 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
505 ret = button_press_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
508 case GDK_BUTTON_RELEASE:
509 ret = button_release_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
510 maybe_locate_with_edit_preroll ( rv->region()->position() );
513 case GDK_MOTION_NOTIFY:
514 ret = motion_handler (item, event);
517 case GDK_ENTER_NOTIFY:
518 ret = enter_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
521 case GDK_LEAVE_NOTIFY:
522 ret = leave_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
533 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
535 /* we handle only button 3 press/release events */
537 if (!rv->sensitive()) {
541 switch (event->type) {
542 case GDK_BUTTON_PRESS:
543 clicked_regionview = rv;
544 clicked_control_point = 0;
545 clicked_axisview = &rv->get_time_axis_view();
546 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
547 if (event->button.button == 3) {
548 return button_press_handler (item, event, FadeOutItem);
552 case GDK_BUTTON_RELEASE:
553 if (event->button.button == 3) {
554 return button_release_handler (item, event, FadeOutItem);
563 /* proxy for the regionview, except enter/leave events */
565 if (event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) {
568 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
573 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv, bool trim)
577 if (!rv->sensitive()) {
581 switch (event->type) {
582 case GDK_BUTTON_PRESS:
583 case GDK_2BUTTON_PRESS:
584 case GDK_3BUTTON_PRESS:
585 clicked_regionview = rv;
586 clicked_control_point = 0;
587 clicked_axisview = &rv->get_time_axis_view();
588 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
589 ret = button_press_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
592 case GDK_BUTTON_RELEASE:
593 ret = button_release_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
594 maybe_locate_with_edit_preroll ( rv->region()->last_frame() - rv->get_fade_out_shape_width() );
597 case GDK_MOTION_NOTIFY:
598 ret = motion_handler (item, event);
601 case GDK_ENTER_NOTIFY:
602 ret = enter_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
605 case GDK_LEAVE_NOTIFY:
606 ret = leave_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
616 struct DescendingRegionLayerSorter {
617 bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
618 return a->layer() > b->layer();
623 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
625 switch (event->type) {
626 case GDK_BUTTON_PRESS:
627 case GDK_2BUTTON_PRESS:
628 case GDK_3BUTTON_PRESS:
629 clicked_control_point = cp;
630 clicked_axisview = &cp->line().trackview;
631 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
632 clicked_regionview = 0;
638 case GDK_SCROLL_DOWN:
645 return typed_event (item, event, ControlPointItem);
649 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
653 if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
656 type = AutomationLineItem;
659 return typed_event (item, event, type);
663 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
667 switch (event->type) {
668 case GDK_BUTTON_PRESS:
669 case GDK_2BUTTON_PRESS:
670 case GDK_3BUTTON_PRESS:
671 clicked_selection = rect->id;
672 ret = button_press_handler (item, event, SelectionItem);
674 case GDK_BUTTON_RELEASE:
675 ret = button_release_handler (item, event, SelectionItem);
677 case GDK_MOTION_NOTIFY:
678 ret = motion_handler (item, event);
680 /* Don't need these at the moment. */
681 case GDK_ENTER_NOTIFY:
682 ret = enter_handler (item, event, SelectionItem);
685 case GDK_LEAVE_NOTIFY:
686 ret = leave_handler (item, event, SelectionItem);
697 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
701 switch (event->type) {
702 case GDK_BUTTON_PRESS:
703 case GDK_2BUTTON_PRESS:
704 case GDK_3BUTTON_PRESS:
705 clicked_selection = rect->id;
706 ret = button_press_handler (item, event, StartSelectionTrimItem);
708 case GDK_BUTTON_RELEASE:
709 ret = button_release_handler (item, event, StartSelectionTrimItem);
711 case GDK_MOTION_NOTIFY:
712 ret = motion_handler (item, event);
714 case GDK_ENTER_NOTIFY:
715 ret = enter_handler (item, event, StartSelectionTrimItem);
718 case GDK_LEAVE_NOTIFY:
719 ret = leave_handler (item, event, StartSelectionTrimItem);
730 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
734 switch (event->type) {
735 case GDK_BUTTON_PRESS:
736 case GDK_2BUTTON_PRESS:
737 case GDK_3BUTTON_PRESS:
738 clicked_selection = rect->id;
739 ret = button_press_handler (item, event, EndSelectionTrimItem);
741 case GDK_BUTTON_RELEASE:
742 ret = button_release_handler (item, event, EndSelectionTrimItem);
744 case GDK_MOTION_NOTIFY:
745 ret = motion_handler (item, event);
747 case GDK_ENTER_NOTIFY:
748 ret = enter_handler (item, event, EndSelectionTrimItem);
751 case GDK_LEAVE_NOTIFY:
752 ret = leave_handler (item, event, EndSelectionTrimItem);
763 Editor::canvas_frame_handle_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
767 /* frame handles are not active when in internal edit mode, because actual notes
768 might be in the area occupied by the handle - we want them to be editable as normal.
771 if (internal_editing() || !rv->sensitive()) {
775 /* NOTE: frame handles pretend to be the colored trim bar from an event handling
776 perspective. XXX change this ??
781 if (item->get_data ("isleft")) {
782 type = LeftFrameHandle;
784 type = RightFrameHandle;
787 switch (event->type) {
788 case GDK_BUTTON_PRESS:
789 case GDK_2BUTTON_PRESS:
790 case GDK_3BUTTON_PRESS:
791 clicked_regionview = rv;
792 clicked_control_point = 0;
793 clicked_axisview = &clicked_regionview->get_time_axis_view();
794 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
795 ret = button_press_handler (item, event, type);
797 case GDK_BUTTON_RELEASE:
798 ret = button_release_handler (item, event, type);
800 case GDK_MOTION_NOTIFY:
801 ret = motion_handler (item, event);
803 case GDK_ENTER_NOTIFY:
804 ret = enter_handler (item, event, type);
807 case GDK_LEAVE_NOTIFY:
808 ret = leave_handler (item, event, type);
820 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
824 if (!rv->sensitive()) {
828 switch (event->type) {
829 case GDK_BUTTON_PRESS:
830 case GDK_2BUTTON_PRESS:
831 case GDK_3BUTTON_PRESS:
832 clicked_regionview = rv;
833 clicked_control_point = 0;
834 clicked_axisview = &clicked_regionview->get_time_axis_view();
835 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
836 ret = button_press_handler (item, event, RegionViewNameHighlight);
838 case GDK_BUTTON_RELEASE:
839 ret = button_release_handler (item, event, RegionViewNameHighlight);
841 case GDK_MOTION_NOTIFY:
842 motion_handler (item, event);
843 ret = true; // force this to avoid progagating the event into the regionview
845 case GDK_ENTER_NOTIFY:
846 ret = enter_handler (item, event, RegionViewNameHighlight);
849 case GDK_LEAVE_NOTIFY:
850 ret = leave_handler (item, event, RegionViewNameHighlight);
861 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
865 if (!rv->sensitive()) {
869 switch (event->type) {
870 case GDK_BUTTON_PRESS:
871 case GDK_2BUTTON_PRESS:
872 case GDK_3BUTTON_PRESS:
873 clicked_regionview = rv;
874 clicked_control_point = 0;
875 clicked_axisview = &clicked_regionview->get_time_axis_view();
876 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
877 ret = button_press_handler (item, event, RegionViewName);
879 case GDK_BUTTON_RELEASE:
880 ret = button_release_handler (item, event, RegionViewName);
882 case GDK_MOTION_NOTIFY:
883 ret = motion_handler (item, event);
885 case GDK_ENTER_NOTIFY:
886 ret = enter_handler (item, event, RegionViewName);
889 case GDK_LEAVE_NOTIFY:
890 ret = leave_handler (item, event, RegionViewName);
901 Editor::canvas_feature_line_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView*)
905 switch (event->type) {
906 case GDK_BUTTON_PRESS:
907 case GDK_2BUTTON_PRESS:
908 case GDK_3BUTTON_PRESS:
909 clicked_regionview = 0;
910 clicked_control_point = 0;
911 clicked_axisview = 0;
912 clicked_routeview = 0; //dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
913 ret = button_press_handler (item, event, FeatureLineItem);
916 case GDK_BUTTON_RELEASE:
917 ret = button_release_handler (item, event, FeatureLineItem);
920 case GDK_MOTION_NOTIFY:
921 ret = motion_handler (item, event);
924 case GDK_ENTER_NOTIFY:
925 ret = enter_handler (item, event, FeatureLineItem);
928 case GDK_LEAVE_NOTIFY:
929 ret = leave_handler (item, event, FeatureLineItem);
940 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* /*marker*/)
942 return typed_event (item, event, MarkerItem);
946 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
948 return typed_event (item, event, MarkerBarItem);
952 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
954 return typed_event (item, event, RangeMarkerBarItem);
958 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
960 return typed_event (item, event, TransportMarkerBarItem);
964 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
966 return typed_event (item, event, CdMarkerBarItem);
970 Editor::canvas_videotl_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
972 return typed_event (item, event, VideoBarItem);
976 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* /*marker*/)
978 return typed_event (item, event, TempoMarkerItem);
982 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* /*marker*/)
984 return typed_event (item, event, MeterMarkerItem);
988 Editor::canvas_ruler_event (GdkEvent *event, ArdourCanvas::Item* item, ItemType type)
991 bool handled = false;
993 if (event->type == GDK_SCROLL) {
995 /* scroll events in the rulers are handled a little differently from
996 scrolling elsewhere in the canvas.
999 switch (event->scroll.direction) {
1001 temporal_zoom_step (false);
1005 case GDK_SCROLL_DOWN:
1006 temporal_zoom_step (true);
1010 case GDK_SCROLL_LEFT:
1011 xdelta = (current_page_samples() / 2);
1012 if (leftmost_frame > xdelta) {
1013 reset_x_origin (leftmost_frame - xdelta);
1020 case GDK_SCROLL_RIGHT:
1021 xdelta = (current_page_samples() / 2);
1022 if (max_framepos - xdelta > leftmost_frame) {
1023 reset_x_origin (leftmost_frame + xdelta);
1025 reset_x_origin (max_framepos - current_page_samples());
1037 return typed_event (item, event, type);
1041 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1043 return typed_event (item, event, TempoBarItem);
1047 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1049 return typed_event (item, event, MeterBarItem);
1053 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
1055 return typed_event (item, event, PlayheadCursorItem);
1059 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
1061 return typed_event (item, event, NoItem);
1065 Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
1067 if (!internal_editing()) {
1071 return typed_event (item, event, NoteItem);
1075 Editor::canvas_drop_zone_event (GdkEvent* /*event*/)
1081 Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const& context, int x, int y, guint time)
1083 boost::shared_ptr<Region> region;
1084 boost::shared_ptr<Region> region_copy;
1085 RouteTimeAxisView* rtav;
1090 string target = _track_canvas->drag_dest_find_target (context, _track_canvas->drag_dest_get_target_list());
1092 if (target.empty()) {
1096 event.type = GDK_MOTION_NOTIFY;
1099 /* assume we're dragging with button 1 */
1100 event.motion.state = Gdk::BUTTON1_MASK;
1102 (void) window_event_sample (&event, &px, &py);
1104 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py);
1105 bool can_drop = false;
1107 if (tv.first != 0) {
1109 /* over a time axis view of some kind */
1111 rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1113 if (rtav != 0 && rtav->is_track ()) {
1114 /* over a track, not a bus */
1120 /* not over a time axis view, so drop is possible */
1125 region = _regions->get_dragged_region ();
1129 if ((boost::dynamic_pointer_cast<AudioRegion> (region) != 0 &&
1130 dynamic_cast<AudioTimeAxisView*> (tv.first) != 0) ||
1131 (boost::dynamic_pointer_cast<MidiRegion> (region) != 0 &&
1132 dynamic_cast<MidiTimeAxisView*> (tv.first) != 0)) {
1139 context->drag_status (context->get_suggested_action(), time);
1143 /* DND originating from outside ardour
1145 * TODO: check if file is audio/midi, allow drops on same track-type only,
1146 * currently: if audio is dropped on a midi-track, it is only added to the region-list
1148 if (Profile->get_sae() || Config->get_only_copy_imported_files()) {
1149 context->drag_status(Gdk::ACTION_COPY, time);
1151 if ((context->get_actions() & (Gdk::ACTION_COPY | Gdk::ACTION_LINK | Gdk::ACTION_MOVE)) == Gdk::ACTION_COPY) {
1152 context->drag_status(Gdk::ACTION_COPY, time);
1154 context->drag_status(Gdk::ACTION_LINK, time);
1162 context->drag_status (Gdk::DragAction (0), time);
1167 Editor::drop_regions (const Glib::RefPtr<Gdk::DragContext>& /*context*/,
1169 const SelectionData& /*data*/,
1170 guint /*info*/, guint /*time*/)
1172 boost::shared_ptr<Region> region;
1173 boost::shared_ptr<Region> region_copy;
1174 RouteTimeAxisView* rtav;
1179 event.type = GDK_MOTION_NOTIFY;
1182 /* assume we're dragging with button 1 */
1183 event.motion.state = Gdk::BUTTON1_MASK;
1185 framepos_t const pos = window_event_sample (&event, &px, &py);
1187 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py);
1189 if (tv.first != 0) {
1191 rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1193 if (rtav != 0 && rtav->is_track ()) {
1195 boost::shared_ptr<Region> region = _regions->get_dragged_region ();
1199 region_copy = RegionFactory::create (region, true);
1202 if ((boost::dynamic_pointer_cast<AudioRegion> (region_copy) != 0 &&
1203 dynamic_cast<AudioTimeAxisView*> (tv.first) != 0) ||
1204 (boost::dynamic_pointer_cast<MidiRegion> (region_copy) != 0 &&
1205 dynamic_cast<MidiTimeAxisView*> (tv.first) != 0)) {
1213 _drags->set (new RegionInsertDrag (this, region_copy, rtav, pos), &event);
1214 _drags->end_grab (0);
1222 Editor::key_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType)
1228 Editor::key_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType type)
1231 bool handled = false;
1234 case TempoMarkerItem:
1235 switch (event->key.keyval) {
1237 remove_tempo_marker (item);
1245 case MeterMarkerItem:
1246 switch (event->key.keyval) {
1248 remove_meter_marker (item);