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, bool from_canvas)
166 boost::optional<Rect> rulers = _time_markers_group->bounding_box();
167 if (rulers && rulers->contains (Duple (event->x, event->y))) {
168 return canvas_ruler_event ((GdkEvent*) event, timecode_ruler, TimecodeRulerItem);
172 _track_canvas->grab_focus();
173 return track_canvas_scroll (event);
177 Editor::track_canvas_button_press_event (GdkEventButton */*event*/)
180 _track_canvas->grab_focus();
185 Editor::track_canvas_button_release_event (GdkEventButton *event)
187 if (_drags->active ()) {
188 _drags->end_grab ((GdkEvent*) event);
194 Editor::track_canvas_motion_notify_event (GdkEventMotion */*event*/)
197 /* keep those motion events coming */
198 _track_canvas->get_pointer (x, y);
203 Editor::track_canvas_motion (GdkEvent *ev)
205 if (_verbose_cursor->visible ()) {
206 _verbose_cursor->set_position (ev->motion.x + 10, ev->motion.y + 10);
213 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
217 switch (event->type) {
218 case GDK_BUTTON_PRESS:
219 case GDK_2BUTTON_PRESS:
220 case GDK_3BUTTON_PRESS:
221 ret = button_press_handler (item, event, type);
223 case GDK_BUTTON_RELEASE:
224 ret = button_release_handler (item, event, type);
226 case GDK_MOTION_NOTIFY:
227 ret = motion_handler (item, event);
230 case GDK_ENTER_NOTIFY:
231 ret = enter_handler (item, event, type);
234 case GDK_LEAVE_NOTIFY:
235 ret = leave_handler (item, event, type);
239 ret = key_press_handler (item, event, type);
242 case GDK_KEY_RELEASE:
243 ret = key_release_handler (item, event, type);
253 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
257 if (!rv->sensitive ()) {
261 switch (event->type) {
262 case GDK_BUTTON_PRESS:
263 case GDK_2BUTTON_PRESS:
264 case GDK_3BUTTON_PRESS:
265 clicked_regionview = rv;
266 clicked_control_point = 0;
267 clicked_axisview = &rv->get_time_axis_view();
268 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
269 ret = button_press_handler (item, event, RegionItem);
272 case GDK_BUTTON_RELEASE:
273 ret = button_release_handler (item, event, RegionItem);
276 case GDK_MOTION_NOTIFY:
277 ret = motion_handler (item, event);
280 case GDK_ENTER_NOTIFY:
281 if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
282 set_entered_regionview (rv);
287 case GDK_LEAVE_NOTIFY:
288 if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
289 set_entered_regionview (0);
302 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
306 switch (event->type) {
307 case GDK_BUTTON_PRESS:
308 case GDK_2BUTTON_PRESS:
309 case GDK_3BUTTON_PRESS:
310 clicked_regionview = 0;
311 clicked_control_point = 0;
312 clicked_axisview = tv;
313 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
314 ret = button_press_handler (item, event, StreamItem);
317 case GDK_BUTTON_RELEASE:
318 ret = button_release_handler (item, event, StreamItem);
321 case GDK_MOTION_NOTIFY:
322 ret = motion_handler (item, event);
325 case GDK_ENTER_NOTIFY:
326 set_entered_track (tv);
330 case GDK_LEAVE_NOTIFY:
331 set_entered_track (0);
342 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
346 switch (event->type) {
347 case GDK_BUTTON_PRESS:
348 case GDK_2BUTTON_PRESS:
349 case GDK_3BUTTON_PRESS:
350 clicked_regionview = 0;
351 clicked_control_point = 0;
352 clicked_axisview = atv;
353 clicked_routeview = 0;
354 ret = button_press_handler (item, event, AutomationTrackItem);
357 case GDK_BUTTON_RELEASE:
358 ret = button_release_handler (item, event, AutomationTrackItem);
361 case GDK_MOTION_NOTIFY:
362 ret = motion_handler (item, event);
365 case GDK_ENTER_NOTIFY:
366 ret = enter_handler (item, event, AutomationTrackItem);
369 case GDK_LEAVE_NOTIFY:
370 ret = leave_handler (item, event, AutomationTrackItem);
381 Editor::canvas_start_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
383 if (!rv->sensitive()) {
387 switch (event->type) {
388 case GDK_BUTTON_PRESS:
389 clicked_regionview = rv;
390 clicked_control_point = 0;
391 clicked_axisview = &rv->get_time_axis_view();
392 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
393 if (event->button.button == 3) {
394 return button_press_handler (item, event, StartCrossFadeItem);
398 case GDK_BUTTON_RELEASE:
399 if (event->button.button == 3) {
400 return button_release_handler (item, event, StartCrossFadeItem);
409 /* In Mixbus, the crossfade area is used to trim the region while leaving the fade anchor intact (see preserve_fade_anchor)*/
410 /* however in A3 this feature is unfinished, and it might be better to do it with a modifier-trim instead, anyway */
411 /* if we return RegionItem here then we avoid the issue until it is resolved later */
412 return typed_event (item, event, RegionItem); // StartCrossFadeItem);
416 Editor::canvas_end_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, EndCrossFadeItem);
433 case GDK_BUTTON_RELEASE:
434 if (event->button.button == 3) {
435 return button_release_handler (item, event, EndCrossFadeItem);
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); // EndCrossFadeItem);
451 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
453 /* we handle only button 3 press/release events */
455 if (!rv->sensitive()) {
459 switch (event->type) {
460 case GDK_BUTTON_PRESS:
461 clicked_regionview = rv;
462 clicked_control_point = 0;
463 clicked_axisview = &rv->get_time_axis_view();
464 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
465 if (event->button.button == 3) {
466 return button_press_handler (item, event, FadeInItem);
470 case GDK_BUTTON_RELEASE:
471 if (event->button.button == 3) {
472 return button_release_handler (item, event, FadeInItem);
481 /* proxy for the regionview, except enter/leave events */
483 if (event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) {
486 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
491 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv, bool trim)
495 if (!rv->sensitive()) {
499 switch (event->type) {
500 case GDK_BUTTON_PRESS:
501 case GDK_2BUTTON_PRESS:
502 case GDK_3BUTTON_PRESS:
503 clicked_regionview = rv;
504 clicked_control_point = 0;
505 clicked_axisview = &rv->get_time_axis_view();
506 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
507 ret = button_press_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
510 case GDK_BUTTON_RELEASE:
511 ret = button_release_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
512 maybe_locate_with_edit_preroll ( rv->region()->position() );
515 case GDK_MOTION_NOTIFY:
516 ret = motion_handler (item, event);
519 case GDK_ENTER_NOTIFY:
520 ret = enter_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
523 case GDK_LEAVE_NOTIFY:
524 ret = leave_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
535 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
537 /* we handle only button 3 press/release events */
539 if (!rv->sensitive()) {
543 switch (event->type) {
544 case GDK_BUTTON_PRESS:
545 clicked_regionview = rv;
546 clicked_control_point = 0;
547 clicked_axisview = &rv->get_time_axis_view();
548 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
549 if (event->button.button == 3) {
550 return button_press_handler (item, event, FadeOutItem);
554 case GDK_BUTTON_RELEASE:
555 if (event->button.button == 3) {
556 return button_release_handler (item, event, FadeOutItem);
565 /* proxy for the regionview, except enter/leave events */
567 if (event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) {
570 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
575 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv, bool trim)
579 if (!rv->sensitive()) {
583 switch (event->type) {
584 case GDK_BUTTON_PRESS:
585 case GDK_2BUTTON_PRESS:
586 case GDK_3BUTTON_PRESS:
587 clicked_regionview = rv;
588 clicked_control_point = 0;
589 clicked_axisview = &rv->get_time_axis_view();
590 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
591 ret = button_press_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
594 case GDK_BUTTON_RELEASE:
595 ret = button_release_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
596 maybe_locate_with_edit_preroll ( rv->region()->last_frame() - rv->get_fade_out_shape_width() );
599 case GDK_MOTION_NOTIFY:
600 ret = motion_handler (item, event);
603 case GDK_ENTER_NOTIFY:
604 ret = enter_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
607 case GDK_LEAVE_NOTIFY:
608 ret = leave_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
618 struct DescendingRegionLayerSorter {
619 bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
620 return a->layer() > b->layer();
625 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
627 switch (event->type) {
628 case GDK_BUTTON_PRESS:
629 case GDK_2BUTTON_PRESS:
630 case GDK_3BUTTON_PRESS:
631 clicked_control_point = cp;
632 clicked_axisview = &cp->line().trackview;
633 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
634 clicked_regionview = 0;
640 case GDK_SCROLL_DOWN:
647 return typed_event (item, event, ControlPointItem);
651 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
655 if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
658 type = AutomationLineItem;
661 return typed_event (item, event, type);
665 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
669 switch (event->type) {
670 case GDK_BUTTON_PRESS:
671 case GDK_2BUTTON_PRESS:
672 case GDK_3BUTTON_PRESS:
673 clicked_selection = rect->id;
674 ret = button_press_handler (item, event, SelectionItem);
676 case GDK_BUTTON_RELEASE:
677 ret = button_release_handler (item, event, SelectionItem);
679 case GDK_MOTION_NOTIFY:
680 ret = motion_handler (item, event);
682 /* Don't need these at the moment. */
683 case GDK_ENTER_NOTIFY:
684 ret = enter_handler (item, event, SelectionItem);
687 case GDK_LEAVE_NOTIFY:
688 ret = leave_handler (item, event, SelectionItem);
699 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
703 switch (event->type) {
704 case GDK_BUTTON_PRESS:
705 case GDK_2BUTTON_PRESS:
706 case GDK_3BUTTON_PRESS:
707 clicked_selection = rect->id;
708 ret = button_press_handler (item, event, StartSelectionTrimItem);
710 case GDK_BUTTON_RELEASE:
711 ret = button_release_handler (item, event, StartSelectionTrimItem);
713 case GDK_MOTION_NOTIFY:
714 ret = motion_handler (item, event);
716 case GDK_ENTER_NOTIFY:
717 ret = enter_handler (item, event, StartSelectionTrimItem);
720 case GDK_LEAVE_NOTIFY:
721 ret = leave_handler (item, event, StartSelectionTrimItem);
732 Editor::canvas_selection_end_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, EndSelectionTrimItem);
743 case GDK_BUTTON_RELEASE:
744 ret = button_release_handler (item, event, EndSelectionTrimItem);
746 case GDK_MOTION_NOTIFY:
747 ret = motion_handler (item, event);
749 case GDK_ENTER_NOTIFY:
750 ret = enter_handler (item, event, EndSelectionTrimItem);
753 case GDK_LEAVE_NOTIFY:
754 ret = leave_handler (item, event, EndSelectionTrimItem);
765 Editor::canvas_frame_handle_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
769 /* frame handles are not active when in internal edit mode, because actual notes
770 might be in the area occupied by the handle - we want them to be editable as normal.
773 if (internal_editing() || !rv->sensitive()) {
777 /* NOTE: frame handles pretend to be the colored trim bar from an event handling
778 perspective. XXX change this ??
783 if (item->get_data ("isleft")) {
784 type = LeftFrameHandle;
786 type = RightFrameHandle;
789 switch (event->type) {
790 case GDK_BUTTON_PRESS:
791 case GDK_2BUTTON_PRESS:
792 case GDK_3BUTTON_PRESS:
793 clicked_regionview = rv;
794 clicked_control_point = 0;
795 clicked_axisview = &clicked_regionview->get_time_axis_view();
796 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
797 ret = button_press_handler (item, event, type);
799 case GDK_BUTTON_RELEASE:
800 ret = button_release_handler (item, event, type);
802 case GDK_MOTION_NOTIFY:
803 ret = motion_handler (item, event);
805 case GDK_ENTER_NOTIFY:
806 ret = enter_handler (item, event, type);
809 case GDK_LEAVE_NOTIFY:
810 ret = leave_handler (item, event, type);
822 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
826 if (!rv->sensitive()) {
830 switch (event->type) {
831 case GDK_BUTTON_PRESS:
832 case GDK_2BUTTON_PRESS:
833 case GDK_3BUTTON_PRESS:
834 clicked_regionview = rv;
835 clicked_control_point = 0;
836 clicked_axisview = &clicked_regionview->get_time_axis_view();
837 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
838 ret = button_press_handler (item, event, RegionViewNameHighlight);
840 case GDK_BUTTON_RELEASE:
841 ret = button_release_handler (item, event, RegionViewNameHighlight);
843 case GDK_MOTION_NOTIFY:
844 motion_handler (item, event);
845 ret = true; // force this to avoid progagating the event into the regionview
847 case GDK_ENTER_NOTIFY:
848 ret = enter_handler (item, event, RegionViewNameHighlight);
851 case GDK_LEAVE_NOTIFY:
852 ret = leave_handler (item, event, RegionViewNameHighlight);
863 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
867 if (!rv->sensitive()) {
871 switch (event->type) {
872 case GDK_BUTTON_PRESS:
873 case GDK_2BUTTON_PRESS:
874 case GDK_3BUTTON_PRESS:
875 clicked_regionview = rv;
876 clicked_control_point = 0;
877 clicked_axisview = &clicked_regionview->get_time_axis_view();
878 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
879 ret = button_press_handler (item, event, RegionViewName);
881 case GDK_BUTTON_RELEASE:
882 ret = button_release_handler (item, event, RegionViewName);
884 case GDK_MOTION_NOTIFY:
885 ret = motion_handler (item, event);
887 case GDK_ENTER_NOTIFY:
888 ret = enter_handler (item, event, RegionViewName);
891 case GDK_LEAVE_NOTIFY:
892 ret = leave_handler (item, event, RegionViewName);
903 Editor::canvas_feature_line_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView*)
907 switch (event->type) {
908 case GDK_BUTTON_PRESS:
909 case GDK_2BUTTON_PRESS:
910 case GDK_3BUTTON_PRESS:
911 clicked_regionview = 0;
912 clicked_control_point = 0;
913 clicked_axisview = 0;
914 clicked_routeview = 0; //dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
915 ret = button_press_handler (item, event, FeatureLineItem);
918 case GDK_BUTTON_RELEASE:
919 ret = button_release_handler (item, event, FeatureLineItem);
922 case GDK_MOTION_NOTIFY:
923 ret = motion_handler (item, event);
926 case GDK_ENTER_NOTIFY:
927 ret = enter_handler (item, event, FeatureLineItem);
930 case GDK_LEAVE_NOTIFY:
931 ret = leave_handler (item, event, FeatureLineItem);
942 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* /*marker*/)
944 return typed_event (item, event, MarkerItem);
948 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
950 return typed_event (item, event, MarkerBarItem);
954 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
956 return typed_event (item, event, RangeMarkerBarItem);
960 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
962 return typed_event (item, event, TransportMarkerBarItem);
966 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
968 return typed_event (item, event, CdMarkerBarItem);
972 Editor::canvas_videotl_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
974 return typed_event (item, event, VideoBarItem);
978 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* /*marker*/)
980 return typed_event (item, event, TempoMarkerItem);
984 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* /*marker*/)
986 return typed_event (item, event, MeterMarkerItem);
990 Editor::canvas_ruler_event (GdkEvent *event, ArdourCanvas::Item* item, ItemType type)
993 bool handled = false;
995 if (event->type == GDK_SCROLL) {
997 /* scroll events in the rulers are handled a little differently from
998 scrolling elsewhere in the canvas.
1001 switch (event->scroll.direction) {
1003 temporal_zoom_step (false);
1007 case GDK_SCROLL_DOWN:
1008 temporal_zoom_step (true);
1012 case GDK_SCROLL_LEFT:
1013 xdelta = (current_page_samples() / 2);
1014 if (leftmost_frame > xdelta) {
1015 reset_x_origin (leftmost_frame - xdelta);
1022 case GDK_SCROLL_RIGHT:
1023 xdelta = (current_page_samples() / 2);
1024 if (max_framepos - xdelta > leftmost_frame) {
1025 reset_x_origin (leftmost_frame + xdelta);
1027 reset_x_origin (max_framepos - current_page_samples());
1039 return typed_event (item, event, type);
1043 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1045 return typed_event (item, event, TempoBarItem);
1049 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1051 return typed_event (item, event, MeterBarItem);
1055 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
1057 return typed_event (item, event, PlayheadCursorItem);
1061 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
1063 return typed_event (item, event, NoItem);
1067 Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
1069 if (!internal_editing()) {
1073 return typed_event (item, event, NoteItem);
1077 Editor::canvas_drop_zone_event (GdkEvent* /*event*/)
1083 Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const& context, int x, int y, guint time)
1085 boost::shared_ptr<Region> region;
1086 boost::shared_ptr<Region> region_copy;
1087 RouteTimeAxisView* rtav;
1092 string target = _track_canvas->drag_dest_find_target (context, _track_canvas->drag_dest_get_target_list());
1094 if (target.empty()) {
1098 event.type = GDK_MOTION_NOTIFY;
1101 /* assume we're dragging with button 1 */
1102 event.motion.state = Gdk::BUTTON1_MASK;
1104 (void) window_event_sample (&event, &px, &py);
1106 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py);
1107 bool can_drop = false;
1109 if (tv.first != 0) {
1111 /* over a time axis view of some kind */
1113 rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1115 if (rtav != 0 && rtav->is_track ()) {
1116 /* over a track, not a bus */
1122 /* not over a time axis view, so drop is possible */
1127 region = _regions->get_dragged_region ();
1131 if ((boost::dynamic_pointer_cast<AudioRegion> (region) != 0 &&
1132 dynamic_cast<AudioTimeAxisView*> (tv.first) != 0) ||
1133 (boost::dynamic_pointer_cast<MidiRegion> (region) != 0 &&
1134 dynamic_cast<MidiTimeAxisView*> (tv.first) != 0)) {
1141 context->drag_status (context->get_suggested_action(), time);
1145 /* DND originating from outside ardour
1147 * TODO: check if file is audio/midi, allow drops on same track-type only,
1148 * currently: if audio is dropped on a midi-track, it is only added to the region-list
1150 if (Profile->get_sae() || Config->get_only_copy_imported_files()) {
1151 context->drag_status(Gdk::ACTION_COPY, time);
1153 if ((context->get_actions() & (Gdk::ACTION_COPY | Gdk::ACTION_LINK | Gdk::ACTION_MOVE)) == Gdk::ACTION_COPY) {
1154 context->drag_status(Gdk::ACTION_COPY, time);
1156 context->drag_status(Gdk::ACTION_LINK, time);
1164 context->drag_status (Gdk::DragAction (0), time);
1169 Editor::drop_regions (const Glib::RefPtr<Gdk::DragContext>& /*context*/,
1171 const SelectionData& /*data*/,
1172 guint /*info*/, guint /*time*/)
1174 boost::shared_ptr<Region> region;
1175 boost::shared_ptr<Region> region_copy;
1176 RouteTimeAxisView* rtav;
1181 event.type = GDK_MOTION_NOTIFY;
1184 /* assume we're dragging with button 1 */
1185 event.motion.state = Gdk::BUTTON1_MASK;
1187 framepos_t const pos = window_event_sample (&event, &px, &py);
1189 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py);
1191 if (tv.first != 0) {
1193 rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1195 if (rtav != 0 && rtav->is_track ()) {
1197 boost::shared_ptr<Region> region = _regions->get_dragged_region ();
1201 region_copy = RegionFactory::create (region, true);
1204 if ((boost::dynamic_pointer_cast<AudioRegion> (region_copy) != 0 &&
1205 dynamic_cast<AudioTimeAxisView*> (tv.first) != 0) ||
1206 (boost::dynamic_pointer_cast<MidiRegion> (region_copy) != 0 &&
1207 dynamic_cast<MidiTimeAxisView*> (tv.first) != 0)) {
1215 _drags->set (new RegionInsertDrag (this, region_copy, rtav, pos), &event);
1216 _drags->end_grab (0);
1224 Editor::key_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType)
1230 Editor::key_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType type)
1233 bool handled = false;
1236 case TempoMarkerItem:
1237 switch (event->key.keyval) {
1239 remove_tempo_marker (item);
1247 case MeterMarkerItem:
1248 switch (event->key.keyval) {
1250 remove_meter_marker (item);