Add test for #3356.
[ardour.git] / gtk2_ardour / editor_canvas_events.cc
1 /*
2     Copyright (C) 2000 Paul Davis
3
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.
8
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.
13
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.
17
18 */
19
20 #include <cstdlib>
21 #include <cmath>
22 #include <algorithm>
23 #include <typeinfo>
24
25 #include "pbd/stacktrace.h"
26
27 #include "ardour/audioplaylist.h"
28 #include "ardour/audioregion.h"
29 #include "ardour/region_factory.h"
30 #include "ardour/midi_region.h"
31
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"
50
51 #include "i18n.h"
52
53 using namespace std;
54 using namespace ARDOUR;
55 using namespace PBD;
56 using namespace Gtk;
57 using namespace ArdourCanvas;
58
59 using Gtkmm2ext::Keyboard;
60
61 bool
62 Editor::track_canvas_scroll (GdkEventScroll* ev)
63 {
64         nframes64_t xdelta;
65         int direction = ev->direction;
66
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;
83                                 }
84                         }
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;
91                 }
92                 break;
93
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;
108                                 }
109                         }
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;
116                 }
117                 break;
118
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);
125                 }
126                 break;
127
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());
134                 }
135                 break;
136
137         default:
138                 /* what? */
139                 break;
140         }
141
142         return false;
143 }
144
145 bool
146 Editor::track_canvas_scroll_event (GdkEventScroll *event)
147 {
148         track_canvas->grab_focus();
149         return track_canvas_scroll (event);
150 }
151
152 bool
153 Editor::track_canvas_button_press_event (GdkEventButton */*event*/)
154 {
155         selection->clear ();
156         track_canvas->grab_focus();
157         return false;
158 }
159
160 bool
161 Editor::track_canvas_button_release_event (GdkEventButton *event)
162 {
163         if (_drags->active ()) {
164                 _drags->end_grab ((GdkEvent*) event);
165         }
166         return false;
167 }
168
169 bool
170 Editor::track_canvas_motion_notify_event (GdkEventMotion */*event*/)
171 {
172         int x, y;
173         /* keep those motion events coming */
174         track_canvas->get_pointer (x, y);
175         return false;
176 }
177
178 bool
179 Editor::track_canvas_motion (GdkEvent *ev)
180 {
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);
184         }
185
186         return false;
187 }
188
189 bool
190 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
191 {
192         gint ret = FALSE;
193
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;
206
207         case GDK_ENTER_NOTIFY:
208                 ret = enter_handler (item, event, type);
209                 break;
210
211         case GDK_LEAVE_NOTIFY:
212                 ret = leave_handler (item, event, type);
213                 break;
214
215         default:
216                 break;
217         }
218         return ret;
219 }
220
221 bool
222 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
223 {
224         bool ret = false;
225
226         if (!rv->sensitive ()) {
227                 return false;
228         }
229
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;
240
241         case GDK_BUTTON_RELEASE:
242                 ret = button_release_handler (item, event, RegionItem);
243                 break;
244
245         case GDK_MOTION_NOTIFY:
246                 ret = motion_handler (item, event);
247                 break;
248
249         case GDK_ENTER_NOTIFY:
250                 set_entered_track (&rv->get_time_axis_view ());
251                 set_entered_regionview (rv);
252                 break;
253
254         case GDK_LEAVE_NOTIFY:
255                 set_entered_track (0);
256                 set_entered_regionview (0);
257                 break;
258
259         default:
260                 break;
261         }
262
263         return ret;
264 }
265
266 bool
267 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
268 {
269         bool ret = FALSE;
270
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;
281
282         case GDK_BUTTON_RELEASE:
283                 ret = button_release_handler (item, event, StreamItem);
284                 break;
285
286         case GDK_MOTION_NOTIFY:
287                 ret = motion_handler (item, event);
288                 break;
289
290         case GDK_ENTER_NOTIFY:
291                 set_entered_track (tv);
292                 break;
293
294         case GDK_LEAVE_NOTIFY:
295                 set_entered_track (0);
296                 break;
297
298         default:
299                 break;
300         }
301
302         return ret;
303 }
304
305 bool
306 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
307 {
308         bool ret = false;
309
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;
320
321         case GDK_BUTTON_RELEASE:
322                 ret = button_release_handler (item, event, AutomationTrackItem);
323                 break;
324
325         case GDK_MOTION_NOTIFY:
326                 ret = motion_handler (item, event);
327                 break;
328
329         case GDK_ENTER_NOTIFY:
330                 ret = enter_handler (item, event, AutomationTrackItem);
331                 break;
332
333         case GDK_LEAVE_NOTIFY:
334                 ret = leave_handler (item, event, AutomationTrackItem);
335                 break;
336
337         default:
338                 break;
339         }
340
341         return ret;
342 }
343
344 bool
345 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
346 {
347         /* we handle only button 3 press/release events */
348
349         if (!rv->sensitive()) {
350                 return false;
351         }
352
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);
361                 }
362                 break;
363
364         case GDK_BUTTON_RELEASE:
365                 if (event->button.button == 3) {
366                         return button_release_handler (item, event, FadeInItem);
367                 }
368                 break;
369
370         default:
371                 break;
372
373         }
374
375         /* proxy for the regionview */
376
377         return canvas_region_view_event (event, rv->get_canvas_group(), rv);
378 }
379
380 bool
381 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
382 {
383         bool ret = false;
384
385         if (!rv->sensitive()) {
386                 return false;
387         }
388
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;
399
400         case GDK_BUTTON_RELEASE:
401                 ret = button_release_handler (item, event, FadeInHandleItem);
402                 break;
403
404         case GDK_MOTION_NOTIFY:
405                 ret = motion_handler (item, event);
406                 break;
407
408         case GDK_ENTER_NOTIFY:
409                 set_entered_regionview (rv);
410                 ret = enter_handler (item, event, FadeInHandleItem);
411                 break;
412
413         case GDK_LEAVE_NOTIFY:
414                 set_entered_regionview (0);
415                 ret = leave_handler (item, event, FadeInHandleItem);
416                 break;
417
418         default:
419                 break;
420         }
421
422         return ret;
423 }
424
425 bool
426 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
427 {
428         /* we handle only button 3 press/release events */
429
430         if (!rv->sensitive()) {
431                 return false;
432         }
433
434         switch (event->type) {
435         case GDK_BUTTON_PRESS:
436                 clicked_regionview = rv;
437                 clicked_control_point = 0;
438                 clicked_axisview = &rv->get_time_axis_view();
439                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
440                 if (event->button.button == 3) {
441                         return button_press_handler (item, event, FadeOutItem);
442                 }
443                 break;
444
445         case GDK_BUTTON_RELEASE:
446                 if (event->button.button == 3) {
447                         return button_release_handler (item, event, FadeOutItem);
448                 }
449                 break;
450
451         default:
452                 break;
453
454         }
455
456         /* proxy for the regionview */
457
458         return canvas_region_view_event (event, rv->get_canvas_group(), rv);
459 }
460
461 bool
462 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
463 {
464         bool ret = false;
465
466         if (!rv->sensitive()) {
467                 return false;
468         }
469
470         switch (event->type) {
471         case GDK_BUTTON_PRESS:
472         case GDK_2BUTTON_PRESS:
473         case GDK_3BUTTON_PRESS:
474                 clicked_regionview = rv;
475                 clicked_control_point = 0;
476                 clicked_axisview = &rv->get_time_axis_view();
477                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
478                 ret = button_press_handler (item, event, FadeOutHandleItem);
479                 break;
480
481         case GDK_BUTTON_RELEASE:
482                 ret = button_release_handler (item, event, FadeOutHandleItem);
483                 break;
484
485         case GDK_MOTION_NOTIFY:
486                 ret = motion_handler (item, event);
487                 break;
488
489         case GDK_ENTER_NOTIFY:
490                 set_entered_regionview (rv);
491                 ret = enter_handler (item, event, FadeOutHandleItem);
492                 break;
493
494         case GDK_LEAVE_NOTIFY:
495                 set_entered_regionview (0);
496                 ret = leave_handler (item, event, FadeOutHandleItem);
497                 break;
498
499         default:
500                 break;
501         }
502
503         return ret;
504 }
505
506 struct DescendingRegionLayerSorter {
507     bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
508             return a->layer() > b->layer();
509     }
510 };
511
512 bool
513 Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv)
514 {
515         /* we handle only button 3 press/release events */
516
517         switch (event->type) {
518         case GDK_BUTTON_PRESS:
519                 clicked_crossfadeview = xfv;
520                 clicked_axisview = &clicked_crossfadeview->get_time_axis_view();
521                 if (event->button.button == 3) {
522                         return button_press_handler (item, event, CrossfadeViewItem);
523                 }
524                 break;
525
526         case GDK_BUTTON_RELEASE:
527                 if (event->button.button == 3) {
528                         bool ret = button_release_handler (item, event, CrossfadeViewItem);
529                         return ret;
530                 }
531                 break;
532
533         default:
534                 break;
535
536         }
537
538         /* XXX do not forward double clicks */
539
540         if (event->type == GDK_2BUTTON_PRESS) {
541                 return false;
542         }
543
544         /* proxy for an underlying regionview */
545
546         /* XXX really need to check if we are in the name highlight,
547            and proxy to that when required.
548         */
549
550         TimeAxisView& tv (xfv->get_time_axis_view());
551         AudioTimeAxisView* atv;
552
553         if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
554
555                 if (atv->is_audio_track()) {
556
557                         boost::shared_ptr<AudioPlaylist> pl;
558                         if ((pl = boost::dynamic_pointer_cast<AudioPlaylist> (atv->track()->playlist())) != 0) {
559
560                                 Playlist::RegionList* rl = pl->regions_at (event_frame (event));
561                                 if (!rl->empty()) {
562
563                                         if (atv->layer_display() == Overlaid) {
564
565                                                 /* we're in overlaid mode; proxy to the uppermost region view */
566
567                                                 DescendingRegionLayerSorter cmp;
568                                                 rl->sort (cmp);
569
570                                                 RegionView* rv = atv->view()->find_view (rl->front());
571
572                                                 delete rl;
573
574                                                 /* proxy */
575                                                 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
576
577                                         } else {
578
579                                                 /* we're in stacked mode; proxy to the region view under the mouse */
580
581                                                 /* XXX: FIXME: this is an evil hack; it assumes that any event for which
582                                                    this proxy is being used has its GdkEvent laid out such that the y
583                                                    member is in the same place as that for a GdkEventButton */
584
585                                                 /* position of the event within the track */
586                                                 double cx = event->button.x;
587                                                 double cy = event->button.y;
588                                                 atv->view()->canvas_item()->w2i (cx, cy);
589
590                                                 /* hence layer that we're over */
591                                                 double const c = atv->view()->child_height ();
592                                                 layer_t const l = pl->top_layer () + 1 - (cy / c);
593
594                                                 /* hence region */
595                                                 Playlist::RegionList::iterator i = rl->begin();
596                                                 while (i != rl->end() && (*i)->layer() != l) {
597                                                         ++i;
598                                                 }
599
600                                                 if (i != rl->end()) {
601                                                         RegionView* rv = atv->view()->find_view (*i);
602                                                         delete rl;
603
604                                                         /* proxy */
605                                                         return canvas_region_view_event (event, rv->get_canvas_group(), rv);
606                                                 }
607                                         }
608                                 }
609
610                                 delete rl;
611                         }
612                 }
613         }
614
615         return TRUE;
616 }
617
618 bool
619 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
620 {
621         switch (event->type) {
622         case GDK_BUTTON_PRESS:
623         case GDK_2BUTTON_PRESS:
624         case GDK_3BUTTON_PRESS:
625                 clicked_control_point = cp;
626                 clicked_axisview = &cp->line().trackview;
627                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
628                 clicked_regionview = 0;
629                 break;
630
631         case GDK_SCROLL_UP:
632                 break;
633
634         case GDK_SCROLL_DOWN:
635                 break;
636
637         default:
638                 break;
639         }
640
641         return typed_event (item, event, ControlPointItem);
642 }
643
644 bool
645 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
646 {
647         ItemType type;
648
649         if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
650                 type = GainLineItem;
651         } else {
652                 type = AutomationLineItem;
653         }
654
655         return typed_event (item, event, type);
656 }
657
658 bool
659 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
660 {
661         bool ret = false;
662
663         switch (event->type) {
664         case GDK_BUTTON_PRESS:
665         case GDK_2BUTTON_PRESS:
666         case GDK_3BUTTON_PRESS:
667                 clicked_selection = rect->id;
668                 ret = button_press_handler (item, event, SelectionItem);
669                 break;
670         case GDK_BUTTON_RELEASE:
671                 ret = button_release_handler (item, event, SelectionItem);
672                 break;
673         case GDK_MOTION_NOTIFY:
674                 ret = motion_handler (item, event);
675                 break;
676                 /* Don't need these at the moment. */
677         case GDK_ENTER_NOTIFY:
678                 ret = enter_handler (item, event, SelectionItem);
679                 break;
680
681         case GDK_LEAVE_NOTIFY:
682                 ret = leave_handler (item, event, SelectionItem);
683                 break;
684
685         default:
686                 break;
687         }
688
689         return ret;
690 }
691
692 bool
693 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
694 {
695         bool ret = false;
696
697         switch (event->type) {
698         case GDK_BUTTON_PRESS:
699         case GDK_2BUTTON_PRESS:
700         case GDK_3BUTTON_PRESS:
701                 clicked_selection = rect->id;
702                 ret = button_press_handler (item, event, StartSelectionTrimItem);
703                 break;
704         case GDK_BUTTON_RELEASE:
705                 ret = button_release_handler (item, event, StartSelectionTrimItem);
706                 break;
707         case GDK_MOTION_NOTIFY:
708                 ret = motion_handler (item, event);
709                 break;
710         case GDK_ENTER_NOTIFY:
711                 ret = enter_handler (item, event, StartSelectionTrimItem);
712                 break;
713
714         case GDK_LEAVE_NOTIFY:
715                 ret = leave_handler (item, event, StartSelectionTrimItem);
716                 break;
717
718         default:
719                 break;
720         }
721
722         return ret;
723 }
724
725 bool
726 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
727 {
728         bool ret = false;
729
730         switch (event->type) {
731         case GDK_BUTTON_PRESS:
732         case GDK_2BUTTON_PRESS:
733         case GDK_3BUTTON_PRESS:
734                 clicked_selection = rect->id;
735                 ret = button_press_handler (item, event, EndSelectionTrimItem);
736                 break;
737         case GDK_BUTTON_RELEASE:
738                 ret = button_release_handler (item, event, EndSelectionTrimItem);
739                 break;
740         case GDK_MOTION_NOTIFY:
741                 ret = motion_handler (item, event);
742                 break;
743         case GDK_ENTER_NOTIFY:
744                 ret = enter_handler (item, event, EndSelectionTrimItem);
745                 break;
746
747         case GDK_LEAVE_NOTIFY:
748                 ret = leave_handler (item, event, EndSelectionTrimItem);
749                 break;
750
751         default:
752                 break;
753         }
754
755         return ret;
756 }
757
758 bool
759 Editor::canvas_frame_handle_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
760 {
761         bool ret = false;
762
763         /* frame handles are not active when in internal edit mode, because actual notes
764            might be in the area occupied by the handle - we want them to be editable as normal.
765         */
766
767         if (internal_editing() || !rv->sensitive()) {
768                 return false;
769         }
770
771         /* NOTE: frame handles pretend to be the colored trim bar from an event handling
772            perspective. XXX change this ??
773         */
774
775         ItemType type;
776
777         if (item->get_data ("isleft")) {
778                 type = LeftFrameHandle;
779         } else {
780                 type = RightFrameHandle;
781         }
782
783         switch (event->type) {
784         case GDK_BUTTON_PRESS:
785         case GDK_2BUTTON_PRESS:
786         case GDK_3BUTTON_PRESS:
787                 clicked_regionview = rv;
788                 clicked_control_point = 0;
789                 clicked_axisview = &clicked_regionview->get_time_axis_view();
790                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
791                 ret = button_press_handler (item, event, type);
792                 break;
793         case GDK_BUTTON_RELEASE:
794                 ret = button_release_handler (item, event, type);
795                 break;
796         case GDK_MOTION_NOTIFY:
797                 ret = motion_handler (item, event);
798                 break;
799         case GDK_ENTER_NOTIFY:
800                 set_entered_regionview (rv);
801                 ret = enter_handler (item, event, type);
802                 break;
803
804         case GDK_LEAVE_NOTIFY:
805                 set_entered_regionview (0);
806                 ret = leave_handler (item, event, type);
807                 break;
808
809         default:
810                 break;
811         }
812
813         return ret;
814 }
815
816
817 bool
818 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
819 {
820         bool ret = false;
821
822         if (!rv->sensitive()) {
823                 return false;
824         }
825
826         switch (event->type) {
827         case GDK_BUTTON_PRESS:
828         case GDK_2BUTTON_PRESS:
829         case GDK_3BUTTON_PRESS:
830                 clicked_regionview = rv;
831                 clicked_control_point = 0;
832                 clicked_axisview = &clicked_regionview->get_time_axis_view();
833                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
834                 ret = button_press_handler (item, event, RegionViewNameHighlight);
835                 break;
836         case GDK_BUTTON_RELEASE:
837                 ret = button_release_handler (item, event, RegionViewNameHighlight);
838                 break;
839         case GDK_MOTION_NOTIFY:
840                 motion_handler (item, event);
841                 ret = true; // force this to avoid progagating the event into the regionview
842                 break;
843         case GDK_ENTER_NOTIFY:
844                 set_entered_regionview (rv);
845                 ret = enter_handler (item, event, RegionViewNameHighlight);
846                 break;
847
848         case GDK_LEAVE_NOTIFY:
849                 set_entered_regionview (0);
850                 ret = leave_handler (item, event, RegionViewNameHighlight);
851                 break;
852
853         default:
854                 break;
855         }
856
857         return ret;
858 }
859
860 bool
861 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
862 {
863         bool ret = false;
864
865         if (!rv->sensitive()) {
866                 return false;
867         }
868
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);
878                 break;
879         case GDK_BUTTON_RELEASE:
880                 ret = button_release_handler (item, event, RegionViewName);
881                 break;
882         case GDK_MOTION_NOTIFY:
883                 ret = motion_handler (item, event);
884                 break;
885         case GDK_ENTER_NOTIFY:
886                 set_entered_regionview (rv);
887                 ret = enter_handler (item, event, RegionViewName);
888                 break;
889
890         case GDK_LEAVE_NOTIFY:
891                 set_entered_regionview (0);
892                 ret = leave_handler (item, event, RegionViewName);
893                 break;
894
895         default:
896                 break;
897         }
898
899         return ret;
900 }
901
902 bool
903 Editor::canvas_feature_line_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
904 {
905         bool ret = false;
906
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);
916                 break;
917
918         case GDK_BUTTON_RELEASE:
919                 ret = button_release_handler (item, event, FeatureLineItem);
920                 break;
921
922         case GDK_MOTION_NOTIFY:
923                 ret = motion_handler (item, event);
924                 break;
925
926         case GDK_ENTER_NOTIFY:
927                 ret = enter_handler (item, event, FeatureLineItem);
928                 break;
929
930         case GDK_LEAVE_NOTIFY:
931                 ret = leave_handler (item, event, FeatureLineItem);
932                 break;
933
934         default:
935                 break;
936         }
937
938         return ret;
939 }
940
941 bool
942 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* /*marker*/)
943 {
944         return typed_event (item, event, MarkerItem);
945 }
946
947 bool
948 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
949 {
950         return typed_event (item, event, MarkerBarItem);
951 }
952
953 bool
954 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
955 {
956         return typed_event (item, event, RangeMarkerBarItem);
957 }
958
959 bool
960 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
961 {
962         return typed_event (item, event, TransportMarkerBarItem);
963 }
964
965 bool
966 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
967 {
968         return typed_event (item, event, CdMarkerBarItem);
969 }
970
971 bool
972 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* /*marker*/)
973 {
974         return typed_event (item, event, TempoMarkerItem);
975 }
976
977 bool
978 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* /*marker*/)
979 {
980         return typed_event (item, event, MeterMarkerItem);
981 }
982
983 bool
984 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
985 {
986         return typed_event (item, event, TempoBarItem);
987 }
988
989 bool
990 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
991 {
992         return typed_event (item, event, MeterBarItem);
993 }
994
995 bool
996 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
997 {
998         return typed_event (item, event, PlayheadCursorItem);
999 }
1000
1001 bool
1002 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
1003 {
1004         return typed_event (item, event, NoItem);
1005 }
1006
1007 bool
1008 Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
1009 {
1010         if (!internal_editing()) {
1011                 return false;
1012         }
1013
1014         return typed_event (item, event, NoteItem);
1015 }
1016
1017 bool
1018 Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const & /*c*/, int x, int y, guint /*time*/)
1019 {
1020         double wx;
1021         double wy;
1022         track_canvas->window_to_world (x, y, wx, wy);
1023
1024         GdkEvent event;
1025         event.type = GDK_MOTION_NOTIFY;
1026         event.button.x = wx;
1027         event.button.y = wy;
1028         /* assume we're dragging with button 1 */
1029         event.motion.state = Gdk::BUTTON1_MASK;
1030
1031         if (!_drags->active ()) {
1032
1033                 double px;
1034                 double py;
1035                 nframes64_t const pos = event_frame (&event, &px, &py);
1036
1037                 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py);
1038                 if (tv.first == 0) {
1039                         return true;
1040                 }
1041
1042                 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1043                 if (rtav == 0 || !rtav->is_track ()) {
1044                         return true;
1045                 }
1046
1047                 boost::shared_ptr<Region> region = _regions->get_dragged_region ();
1048
1049                 if (!region) {
1050                         return true;
1051                 }
1052
1053                 boost::shared_ptr<Region> region_copy = RegionFactory::create (region);
1054
1055                 if (boost::dynamic_pointer_cast<AudioRegion> (region_copy) != 0 &&
1056                     dynamic_cast<AudioTimeAxisView*> (tv.first) == 0) {
1057
1058                         /* audio -> non-audio */
1059                         return true;
1060                 }
1061
1062                 if (boost::dynamic_pointer_cast<MidiRegion> (region_copy) == 0 &&
1063                     dynamic_cast<MidiTimeAxisView*> (tv.first) != 0) {
1064
1065                         /* MIDI -> non-MIDI */
1066                         return true;
1067                 }
1068
1069                 _drags->set (new RegionInsertDrag (this, region_copy, rtav, pos), &event);
1070         }
1071
1072         _drags->motion_handler (&event, false);
1073
1074         return true;
1075 }