fix math bug with numthreads computation
[ardour2.git] / gtk2_ardour / editor_canvas_events.cc
blobbf84eb20e9c4ee58c9c6e3da3cf13e451aae01ce
1 /*
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.
20 #include <cstdlib>
21 #include <cmath>
22 #include <algorithm>
23 #include <typeinfo>
25 #include "pbd/stacktrace.h"
27 #include "ardour/audioplaylist.h"
28 #include "ardour/audioregion.h"
29 #include "ardour/region_factory.h"
30 #include "ardour/midi_region.h"
32 #include "editor.h"
33 #include "keyboard.h"
34 #include "public_editor.h"
35 #include "audio_region_view.h"
36 #include "audio_streamview.h"
37 #include "canvas-noevent-text.h"
38 #include "crossfade_view.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 "canvas_impl.h"
46 #include "simplerect.h"
47 #include "editor_drag.h"
48 #include "midi_time_axis.h"
49 #include "editor_regions.h"
51 #include "i18n.h"
53 using namespace std;
54 using namespace ARDOUR;
55 using namespace PBD;
56 using namespace Gtk;
57 using namespace ArdourCanvas;
59 using Gtkmm2ext::Keyboard;
61 bool
62 Editor::track_canvas_scroll (GdkEventScroll* ev)
64 nframes64_t xdelta;
65 int direction = ev->direction;
67 retry:
68 switch (direction) {
69 case GDK_SCROLL_UP:
70 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
71 temporal_zoom_step (false);
72 return true;
73 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
74 direction = GDK_SCROLL_LEFT;
75 goto retry;
76 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
77 if (!current_stepping_trackview) {
78 step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
79 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize);
80 current_stepping_trackview = p.first;
81 if (!current_stepping_trackview) {
82 return false;
85 last_track_height_step_timestamp = get_microseconds();
86 current_stepping_trackview->step_height (true);
87 return true;
88 } else {
89 scroll_tracks_up_line ();
90 return true;
92 break;
94 case GDK_SCROLL_DOWN:
95 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
96 temporal_zoom_step (true);
97 return true;
98 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
99 direction = GDK_SCROLL_RIGHT;
100 goto retry;
101 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
102 if (!current_stepping_trackview) {
103 step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
104 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize);
105 current_stepping_trackview = p.first;
106 if (!current_stepping_trackview) {
107 return false;
110 last_track_height_step_timestamp = get_microseconds();
111 current_stepping_trackview->step_height (false);
112 return true;
113 } else {
114 scroll_tracks_down_line ();
115 return true;
117 break;
119 case GDK_SCROLL_LEFT:
120 xdelta = (current_page_frames() / 8);
121 if (leftmost_frame > xdelta) {
122 reset_x_origin (leftmost_frame - xdelta);
123 } else {
124 reset_x_origin (0);
126 break;
128 case GDK_SCROLL_RIGHT:
129 xdelta = (current_page_frames() / 8);
130 if (max_frames - xdelta > leftmost_frame) {
131 reset_x_origin (leftmost_frame + xdelta);
132 } else {
133 reset_x_origin (max_frames - current_page_frames());
135 break;
137 default:
138 /* what? */
139 break;
142 return false;
145 bool
146 Editor::track_canvas_scroll_event (GdkEventScroll *event)
148 track_canvas->grab_focus();
149 return track_canvas_scroll (event);
152 bool
153 Editor::track_canvas_button_press_event (GdkEventButton */*event*/)
155 selection->clear ();
156 track_canvas->grab_focus();
157 return false;
160 bool
161 Editor::track_canvas_button_release_event (GdkEventButton *event)
163 if (_drags->active ()) {
164 _drags->end_grab ((GdkEvent*) event);
166 return false;
169 bool
170 Editor::track_canvas_motion_notify_event (GdkEventMotion */*event*/)
172 int x, y;
173 /* keep those motion events coming */
174 track_canvas->get_pointer (x, y);
175 return false;
178 bool
179 Editor::track_canvas_motion (GdkEvent *ev)
181 if (verbose_cursor_visible) {
182 verbose_canvas_cursor->property_x() = clamp_verbose_cursor_x (ev->motion.x + 10);
183 verbose_canvas_cursor->property_y() = clamp_verbose_cursor_y (ev->motion.y + 10);
186 return false;
189 bool
190 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
192 gint ret = FALSE;
194 switch (event->type) {
195 case GDK_BUTTON_PRESS:
196 case GDK_2BUTTON_PRESS:
197 case GDK_3BUTTON_PRESS:
198 ret = button_press_handler (item, event, type);
199 break;
200 case GDK_BUTTON_RELEASE:
201 ret = button_release_handler (item, event, type);
202 break;
203 case GDK_MOTION_NOTIFY:
204 ret = motion_handler (item, event);
205 break;
207 case GDK_ENTER_NOTIFY:
208 ret = enter_handler (item, event, type);
209 break;
211 case GDK_LEAVE_NOTIFY:
212 ret = leave_handler (item, event, type);
213 break;
215 default:
216 break;
218 return ret;
221 bool
222 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
224 bool ret = false;
226 if (!rv->sensitive ()) {
227 return false;
230 switch (event->type) {
231 case GDK_BUTTON_PRESS:
232 case GDK_2BUTTON_PRESS:
233 case GDK_3BUTTON_PRESS:
234 clicked_regionview = rv;
235 clicked_control_point = 0;
236 clicked_axisview = &rv->get_time_axis_view();
237 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
238 ret = button_press_handler (item, event, RegionItem);
239 break;
241 case GDK_BUTTON_RELEASE:
242 ret = button_release_handler (item, event, RegionItem);
243 break;
245 case GDK_MOTION_NOTIFY:
246 ret = motion_handler (item, event);
247 break;
249 case GDK_ENTER_NOTIFY:
250 set_entered_track (&rv->get_time_axis_view ());
251 set_entered_regionview (rv);
252 break;
254 case GDK_LEAVE_NOTIFY:
255 set_entered_track (0);
256 set_entered_regionview (0);
257 break;
259 default:
260 break;
263 return ret;
266 bool
267 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
269 bool ret = FALSE;
271 switch (event->type) {
272 case GDK_BUTTON_PRESS:
273 case GDK_2BUTTON_PRESS:
274 case GDK_3BUTTON_PRESS:
275 clicked_regionview = 0;
276 clicked_control_point = 0;
277 clicked_axisview = tv;
278 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(tv);
279 ret = button_press_handler (item, event, StreamItem);
280 break;
282 case GDK_BUTTON_RELEASE:
283 ret = button_release_handler (item, event, StreamItem);
284 break;
286 case GDK_MOTION_NOTIFY:
287 ret = motion_handler (item, event);
288 break;
290 case GDK_ENTER_NOTIFY:
291 set_entered_track (tv);
292 break;
294 case GDK_LEAVE_NOTIFY:
295 set_entered_track (0);
296 break;
298 default:
299 break;
302 return ret;
305 bool
306 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
308 bool ret = false;
310 switch (event->type) {
311 case GDK_BUTTON_PRESS:
312 case GDK_2BUTTON_PRESS:
313 case GDK_3BUTTON_PRESS:
314 clicked_regionview = 0;
315 clicked_control_point = 0;
316 clicked_axisview = atv;
317 clicked_routeview = 0;
318 ret = button_press_handler (item, event, AutomationTrackItem);
319 break;
321 case GDK_BUTTON_RELEASE:
322 ret = button_release_handler (item, event, AutomationTrackItem);
323 break;
325 case GDK_MOTION_NOTIFY:
326 ret = motion_handler (item, event);
327 break;
329 case GDK_ENTER_NOTIFY:
330 ret = enter_handler (item, event, AutomationTrackItem);
331 break;
333 case GDK_LEAVE_NOTIFY:
334 ret = leave_handler (item, event, AutomationTrackItem);
335 break;
337 default:
338 break;
341 return ret;
344 bool
345 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
347 /* we handle only button 3 press/release events */
349 if (!rv->sensitive()) {
350 return false;
353 switch (event->type) {
354 case GDK_BUTTON_PRESS:
355 clicked_regionview = rv;
356 clicked_control_point = 0;
357 clicked_axisview = &rv->get_time_axis_view();
358 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
359 if (event->button.button == 3) {
360 return button_press_handler (item, event, FadeInItem);
362 break;
364 case GDK_BUTTON_RELEASE:
365 if (event->button.button == 3) {
366 return button_release_handler (item, event, FadeInItem);
368 break;
370 default:
371 break;
375 /* proxy for the regionview */
377 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
380 bool
381 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
383 bool ret = false;
385 if (!rv->sensitive()) {
386 return false;
389 switch (event->type) {
390 case GDK_BUTTON_PRESS:
391 case GDK_2BUTTON_PRESS:
392 case GDK_3BUTTON_PRESS:
393 clicked_regionview = rv;
394 clicked_control_point = 0;
395 clicked_axisview = &rv->get_time_axis_view();
396 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
397 ret = button_press_handler (item, event, FadeInHandleItem);
398 break;
400 case GDK_BUTTON_RELEASE:
401 ret = button_release_handler (item, event, FadeInHandleItem);
402 break;
404 case GDK_MOTION_NOTIFY:
405 ret = motion_handler (item, event);
406 break;
408 case GDK_ENTER_NOTIFY:
409 ret = enter_handler (item, event, FadeInHandleItem);
410 break;
412 case GDK_LEAVE_NOTIFY:
413 ret = leave_handler (item, event, FadeInHandleItem);
414 break;
416 default:
417 break;
420 return ret;
423 bool
424 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
426 /* we handle only button 3 press/release events */
428 if (!rv->sensitive()) {
429 return false;
432 switch (event->type) {
433 case GDK_BUTTON_PRESS:
434 clicked_regionview = rv;
435 clicked_control_point = 0;
436 clicked_axisview = &rv->get_time_axis_view();
437 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
438 if (event->button.button == 3) {
439 return button_press_handler (item, event, FadeOutItem);
441 break;
443 case GDK_BUTTON_RELEASE:
444 if (event->button.button == 3) {
445 return button_release_handler (item, event, FadeOutItem);
447 break;
449 default:
450 break;
454 /* proxy for the regionview */
456 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
459 bool
460 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
462 bool ret = false;
464 if (!rv->sensitive()) {
465 return false;
468 switch (event->type) {
469 case GDK_BUTTON_PRESS:
470 case GDK_2BUTTON_PRESS:
471 case GDK_3BUTTON_PRESS:
472 clicked_regionview = rv;
473 clicked_control_point = 0;
474 clicked_axisview = &rv->get_time_axis_view();
475 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
476 ret = button_press_handler (item, event, FadeOutHandleItem);
477 break;
479 case GDK_BUTTON_RELEASE:
480 ret = button_release_handler (item, event, FadeOutHandleItem);
481 break;
483 case GDK_MOTION_NOTIFY:
484 ret = motion_handler (item, event);
485 break;
487 case GDK_ENTER_NOTIFY:
488 ret = enter_handler (item, event, FadeOutHandleItem);
489 break;
491 case GDK_LEAVE_NOTIFY:
492 ret = leave_handler (item, event, FadeOutHandleItem);
493 break;
495 default:
496 break;
499 return ret;
502 struct DescendingRegionLayerSorter {
503 bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
504 return a->layer() > b->layer();
508 bool
509 Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv)
511 /* we handle only button 3 press/release events */
513 switch (event->type) {
514 case GDK_BUTTON_PRESS:
515 clicked_crossfadeview = xfv;
516 clicked_axisview = &clicked_crossfadeview->get_time_axis_view();
517 if (event->button.button == 3) {
518 return button_press_handler (item, event, CrossfadeViewItem);
520 break;
522 case GDK_BUTTON_RELEASE:
523 if (event->button.button == 3) {
524 bool ret = button_release_handler (item, event, CrossfadeViewItem);
525 return ret;
527 break;
529 default:
530 break;
534 /* XXX do not forward double clicks */
536 if (event->type == GDK_2BUTTON_PRESS) {
537 return false;
540 /* proxy for an underlying regionview */
542 /* XXX really need to check if we are in the name highlight,
543 and proxy to that when required.
546 TimeAxisView& tv (xfv->get_time_axis_view());
547 AudioTimeAxisView* atv;
549 if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
551 if (atv->is_audio_track()) {
553 boost::shared_ptr<AudioPlaylist> pl;
554 if ((pl = boost::dynamic_pointer_cast<AudioPlaylist> (atv->track()->playlist())) != 0) {
556 Playlist::RegionList* rl = pl->regions_at (event_frame (event));
557 if (!rl->empty()) {
559 if (atv->layer_display() == Overlaid) {
561 /* we're in overlaid mode; proxy to the uppermost region view */
563 DescendingRegionLayerSorter cmp;
564 rl->sort (cmp);
566 RegionView* rv = atv->view()->find_view (rl->front());
568 delete rl;
570 /* proxy */
571 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
573 } else {
575 /* we're in stacked mode; proxy to the region view under the mouse */
577 /* XXX: FIXME: this is an evil hack; it assumes that any event for which
578 this proxy is being used has its GdkEvent laid out such that the y
579 member is in the same place as that for a GdkEventButton */
581 /* position of the event within the track */
582 double cx = event->button.x;
583 double cy = event->button.y;
584 atv->view()->canvas_item()->w2i (cx, cy);
586 /* hence layer that we're over */
587 double const c = atv->view()->child_height ();
588 layer_t const l = pl->top_layer () + 1 - (cy / c);
590 /* hence region */
591 Playlist::RegionList::iterator i = rl->begin();
592 while (i != rl->end() && (*i)->layer() != l) {
593 ++i;
596 if (i != rl->end()) {
597 RegionView* rv = atv->view()->find_view (*i);
598 delete rl;
600 /* proxy */
601 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
606 delete rl;
611 return TRUE;
614 bool
615 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
617 switch (event->type) {
618 case GDK_BUTTON_PRESS:
619 case GDK_2BUTTON_PRESS:
620 case GDK_3BUTTON_PRESS:
621 clicked_control_point = cp;
622 clicked_axisview = &cp->line().trackview;
623 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
624 clicked_regionview = 0;
625 break;
627 case GDK_SCROLL_UP:
628 break;
630 case GDK_SCROLL_DOWN:
631 break;
633 default:
634 break;
637 return typed_event (item, event, ControlPointItem);
640 bool
641 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
643 ItemType type;
645 if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
646 type = GainLineItem;
647 } else {
648 type = AutomationLineItem;
651 return typed_event (item, event, type);
654 bool
655 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
657 bool ret = false;
659 switch (event->type) {
660 case GDK_BUTTON_PRESS:
661 case GDK_2BUTTON_PRESS:
662 case GDK_3BUTTON_PRESS:
663 clicked_selection = rect->id;
664 ret = button_press_handler (item, event, SelectionItem);
665 break;
666 case GDK_BUTTON_RELEASE:
667 ret = button_release_handler (item, event, SelectionItem);
668 break;
669 case GDK_MOTION_NOTIFY:
670 ret = motion_handler (item, event);
671 break;
672 /* Don't need these at the moment. */
673 case GDK_ENTER_NOTIFY:
674 ret = enter_handler (item, event, SelectionItem);
675 break;
677 case GDK_LEAVE_NOTIFY:
678 ret = leave_handler (item, event, SelectionItem);
679 break;
681 default:
682 break;
685 return ret;
688 bool
689 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
691 bool ret = false;
693 switch (event->type) {
694 case GDK_BUTTON_PRESS:
695 case GDK_2BUTTON_PRESS:
696 case GDK_3BUTTON_PRESS:
697 clicked_selection = rect->id;
698 ret = button_press_handler (item, event, StartSelectionTrimItem);
699 break;
700 case GDK_BUTTON_RELEASE:
701 ret = button_release_handler (item, event, StartSelectionTrimItem);
702 break;
703 case GDK_MOTION_NOTIFY:
704 ret = motion_handler (item, event);
705 break;
706 case GDK_ENTER_NOTIFY:
707 ret = enter_handler (item, event, StartSelectionTrimItem);
708 break;
710 case GDK_LEAVE_NOTIFY:
711 ret = leave_handler (item, event, StartSelectionTrimItem);
712 break;
714 default:
715 break;
718 return ret;
721 bool
722 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
724 bool ret = false;
726 switch (event->type) {
727 case GDK_BUTTON_PRESS:
728 case GDK_2BUTTON_PRESS:
729 case GDK_3BUTTON_PRESS:
730 clicked_selection = rect->id;
731 ret = button_press_handler (item, event, EndSelectionTrimItem);
732 break;
733 case GDK_BUTTON_RELEASE:
734 ret = button_release_handler (item, event, EndSelectionTrimItem);
735 break;
736 case GDK_MOTION_NOTIFY:
737 ret = motion_handler (item, event);
738 break;
739 case GDK_ENTER_NOTIFY:
740 ret = enter_handler (item, event, EndSelectionTrimItem);
741 break;
743 case GDK_LEAVE_NOTIFY:
744 ret = leave_handler (item, event, EndSelectionTrimItem);
745 break;
747 default:
748 break;
751 return ret;
754 bool
755 Editor::canvas_frame_handle_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
757 bool ret = false;
759 /* frame handles are not active when in internal edit mode, because actual notes
760 might be in the area occupied by the handle - we want them to be editable as normal.
763 if (internal_editing() || !rv->sensitive()) {
764 return false;
767 /* NOTE: frame handles pretend to be the colored trim bar from an event handling
768 perspective. XXX change this ??
771 ItemType type;
773 if (item->get_data ("isleft")) {
774 type = LeftFrameHandle;
775 } else {
776 type = RightFrameHandle;
779 switch (event->type) {
780 case GDK_BUTTON_PRESS:
781 case GDK_2BUTTON_PRESS:
782 case GDK_3BUTTON_PRESS:
783 clicked_regionview = rv;
784 clicked_control_point = 0;
785 clicked_axisview = &clicked_regionview->get_time_axis_view();
786 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
787 ret = button_press_handler (item, event, type);
788 break;
789 case GDK_BUTTON_RELEASE:
790 ret = button_release_handler (item, event, type);
791 break;
792 case GDK_MOTION_NOTIFY:
793 ret = motion_handler (item, event);
794 break;
795 case GDK_ENTER_NOTIFY:
796 ret = enter_handler (item, event, type);
797 break;
799 case GDK_LEAVE_NOTIFY:
800 ret = leave_handler (item, event, type);
801 break;
803 default:
804 break;
807 return ret;
811 bool
812 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
814 bool ret = false;
816 if (!rv->sensitive()) {
817 return false;
820 switch (event->type) {
821 case GDK_BUTTON_PRESS:
822 case GDK_2BUTTON_PRESS:
823 case GDK_3BUTTON_PRESS:
824 clicked_regionview = rv;
825 clicked_control_point = 0;
826 clicked_axisview = &clicked_regionview->get_time_axis_view();
827 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
828 ret = button_press_handler (item, event, RegionViewNameHighlight);
829 break;
830 case GDK_BUTTON_RELEASE:
831 ret = button_release_handler (item, event, RegionViewNameHighlight);
832 break;
833 case GDK_MOTION_NOTIFY:
834 motion_handler (item, event);
835 ret = true; // force this to avoid progagating the event into the regionview
836 break;
837 case GDK_ENTER_NOTIFY:
838 ret = enter_handler (item, event, RegionViewNameHighlight);
839 break;
841 case GDK_LEAVE_NOTIFY:
842 ret = leave_handler (item, event, RegionViewNameHighlight);
843 break;
845 default:
846 break;
849 return ret;
852 bool
853 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
855 bool ret = false;
857 if (!rv->sensitive()) {
858 return false;
861 switch (event->type) {
862 case GDK_BUTTON_PRESS:
863 case GDK_2BUTTON_PRESS:
864 case GDK_3BUTTON_PRESS:
865 clicked_regionview = rv;
866 clicked_control_point = 0;
867 clicked_axisview = &clicked_regionview->get_time_axis_view();
868 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
869 ret = button_press_handler (item, event, RegionViewName);
870 break;
871 case GDK_BUTTON_RELEASE:
872 ret = button_release_handler (item, event, RegionViewName);
873 break;
874 case GDK_MOTION_NOTIFY:
875 ret = motion_handler (item, event);
876 break;
877 case GDK_ENTER_NOTIFY:
878 ret = enter_handler (item, event, RegionViewName);
879 break;
881 case GDK_LEAVE_NOTIFY:
882 ret = leave_handler (item, event, RegionViewName);
883 break;
885 default:
886 break;
889 return ret;
892 bool
893 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* /*marker*/)
895 return typed_event (item, event, MarkerItem);
898 bool
899 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
901 return typed_event (item, event, MarkerBarItem);
904 bool
905 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
907 return typed_event (item, event, RangeMarkerBarItem);
910 bool
911 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
913 return typed_event (item, event, TransportMarkerBarItem);
916 bool
917 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
919 return typed_event (item, event, CdMarkerBarItem);
922 bool
923 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* /*marker*/)
925 return typed_event (item, event, TempoMarkerItem);
928 bool
929 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* /*marker*/)
931 return typed_event (item, event, MeterMarkerItem);
934 bool
935 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
937 return typed_event (item, event, TempoBarItem);
940 bool
941 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
943 return typed_event (item, event, MeterBarItem);
946 bool
947 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
949 return typed_event (item, event, PlayheadCursorItem);
952 bool
953 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
955 return typed_event (item, event, NoItem);
958 bool
959 Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
961 if (!internal_editing()) {
962 return false;
965 return typed_event (item, event, NoteItem);
968 bool
969 Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const & /*c*/, int x, int y, guint /*time*/)
971 double wx;
972 double wy;
973 track_canvas->window_to_world (x, y, wx, wy);
975 GdkEvent event;
976 event.type = GDK_MOTION_NOTIFY;
977 event.button.x = wx;
978 event.button.y = wy;
979 /* assume we're dragging with button 1 */
980 event.motion.state = Gdk::BUTTON1_MASK;
982 if (!_drags->active ()) {
984 double px;
985 double py;
986 nframes64_t const pos = event_frame (&event, &px, &py);
988 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py);
989 if (tv.first == 0) {
990 return true;
993 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
994 if (rtav == 0 || !rtav->is_track ()) {
995 return true;
998 boost::shared_ptr<Region> region = _regions->get_dragged_region ();
1000 if (!region) {
1001 return true;
1004 boost::shared_ptr<Region> region_copy = RegionFactory::create (region);
1006 if (boost::dynamic_pointer_cast<AudioRegion> (region_copy) != 0 &&
1007 dynamic_cast<AudioTimeAxisView*> (tv.first) == 0) {
1009 /* audio -> non-audio */
1010 return true;
1013 if (boost::dynamic_pointer_cast<MidiRegion> (region_copy) == 0 &&
1014 dynamic_cast<MidiTimeAxisView*> (tv.first) != 0) {
1016 /* MIDI -> non-MIDI */
1017 return true;
1020 _drags->set (new RegionInsertDrag (this, region_copy, rtav, pos), &event);
1023 _drags->motion_handler (&event, false);
1025 return true;