f7fd030a01715cb5613c8bd5df820a422edc54cd
[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 "interactive-item.h"
48 #include "editor_drag.h"
49 #include "midi_time_axis.h"
50 #include "editor_regions.h"
51
52 #include "i18n.h"
53
54 using namespace std;
55 using namespace ARDOUR;
56 using namespace PBD;
57 using namespace Gtk;
58 using namespace ArdourCanvas;
59
60 using Gtkmm2ext::Keyboard;
61
62 bool
63 Editor::track_canvas_scroll (GdkEventScroll* ev)
64 {
65         int x, y;
66         double wx, wy;
67         nframes64_t xdelta;
68         int direction = ev->direction;
69
70         Gnome::Canvas::Item* item = track_canvas->get_item_at(ev->x, ev->y);
71         InteractiveItem* interactive_item = dynamic_cast<InteractiveItem*>(item);
72         if (interactive_item) {
73                 return interactive_item->on_event(reinterpret_cast<GdkEvent*>(ev));
74         }
75
76   retry:
77         switch (direction) {
78         case GDK_SCROLL_UP:
79                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
80                         temporal_zoom_step (false);
81                         return true;
82                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
83                         direction = GDK_SCROLL_LEFT;
84                         goto retry;
85                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
86                         if (!current_stepping_trackview) {
87                                 step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
88                                 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize);
89                                 current_stepping_trackview = p.first;
90                                 if (!current_stepping_trackview) {
91                                         return false;
92                                 }
93                         }
94                         last_track_height_step_timestamp = get_microseconds();
95                         current_stepping_trackview->step_height (true);
96                         return true;
97                 } else {
98                         scroll_tracks_up_line ();
99                         return true;
100                 }
101                 break;
102
103         case GDK_SCROLL_DOWN:
104                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
105                         temporal_zoom_step (true);
106                         return true;
107                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
108                         direction = GDK_SCROLL_RIGHT;
109                         goto retry;
110                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
111                         if (!current_stepping_trackview) {
112                                 step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
113                                 std::pair<TimeAxisView*, int> const p = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize);
114                                 current_stepping_trackview = p.first;
115                                 if (!current_stepping_trackview) {
116                                         return false;
117                                 }
118                         }
119                         last_track_height_step_timestamp = get_microseconds();
120                         current_stepping_trackview->step_height (false);
121                         return true;
122                 } else {
123                         scroll_tracks_down_line ();
124                         return true;
125                 }
126                 break;
127
128         case GDK_SCROLL_LEFT:
129                 xdelta = (current_page_frames() / 8);
130                 if (leftmost_frame > xdelta) {
131                         reset_x_origin (leftmost_frame - xdelta);
132                 } else {
133                         reset_x_origin (0);
134                 }
135                 break;
136
137         case GDK_SCROLL_RIGHT:
138                 xdelta = (current_page_frames() / 8);
139                 if (max_frames - xdelta > leftmost_frame) {
140                         reset_x_origin (leftmost_frame + xdelta);
141                 } else {
142                         reset_x_origin (max_frames - current_page_frames());
143                 }
144                 break;
145
146         default:
147                 /* what? */
148                 break;
149         }
150
151         return false;
152 }
153
154 bool
155 Editor::track_canvas_scroll_event (GdkEventScroll *event)
156 {
157         track_canvas->grab_focus();
158         track_canvas_scroll (event);
159         return false;
160 }
161
162 bool
163 Editor::track_canvas_button_press_event (GdkEventButton */*event*/)
164 {
165         selection->clear ();
166         track_canvas->grab_focus();
167         return false;
168 }
169
170 bool
171 Editor::track_canvas_button_release_event (GdkEventButton *event)
172 {
173         if (_drags->active ()) {
174                 _drags->end_grab ((GdkEvent*) event);
175         }
176         return false;
177 }
178
179 bool
180 Editor::track_canvas_motion_notify_event (GdkEventMotion */*event*/)
181 {
182         int x, y;
183         /* keep those motion events coming */
184         track_canvas->get_pointer (x, y);
185         return false;
186 }
187
188 bool
189 Editor::track_canvas_motion (GdkEvent *ev)
190 {
191         if (verbose_cursor_visible) {
192                 verbose_canvas_cursor->property_x() = clamp_verbose_cursor_x (ev->motion.x + 10);
193                 verbose_canvas_cursor->property_y() = clamp_verbose_cursor_y (ev->motion.y + 10);
194         }
195
196         return false;
197 }
198
199 bool
200 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
201 {
202         gint ret = FALSE;
203
204         switch (event->type) {
205         case GDK_BUTTON_PRESS:
206         case GDK_2BUTTON_PRESS:
207         case GDK_3BUTTON_PRESS:
208                 ret = button_press_handler (item, event, type);
209                 break;
210         case GDK_BUTTON_RELEASE:
211                 ret = button_release_handler (item, event, type);
212                 break;
213         case GDK_MOTION_NOTIFY:
214                 ret = motion_handler (item, event);
215                 break;
216
217         case GDK_ENTER_NOTIFY:
218                 ret = enter_handler (item, event, type);
219                 break;
220
221         case GDK_LEAVE_NOTIFY:
222                 ret = leave_handler (item, event, type);
223                 break;
224
225         default:
226                 break;
227         }
228         return ret;
229 }
230
231 bool
232 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
233 {
234         bool ret = false;
235
236         if (!rv->sensitive ()) {
237                 return false;
238         }
239
240         switch (event->type) {
241         case GDK_BUTTON_PRESS:
242         case GDK_2BUTTON_PRESS:
243         case GDK_3BUTTON_PRESS:
244                 clicked_regionview = rv;
245                 clicked_control_point = 0;
246                 clicked_axisview = &rv->get_time_axis_view();
247                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
248                 ret = button_press_handler (item, event, RegionItem);
249                 break;
250
251         case GDK_BUTTON_RELEASE:
252                 ret = button_release_handler (item, event, RegionItem);
253                 break;
254
255         case GDK_MOTION_NOTIFY:
256                 ret = motion_handler (item, event);
257                 break;
258
259         case GDK_ENTER_NOTIFY:
260                 set_entered_track (&rv->get_time_axis_view ());
261                 set_entered_regionview (rv);
262                 break;
263
264         case GDK_LEAVE_NOTIFY:
265                 set_entered_track (0);
266                 set_entered_regionview (0);
267                 break;
268
269         default:
270                 break;
271         }
272
273         return ret;
274 }
275
276 bool
277 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
278 {
279         bool ret = FALSE;
280
281         switch (event->type) {
282         case GDK_BUTTON_PRESS:
283         case GDK_2BUTTON_PRESS:
284         case GDK_3BUTTON_PRESS:
285                 clicked_regionview = 0;
286                 clicked_control_point = 0;
287                 clicked_axisview = tv;
288                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(tv);
289                 ret = button_press_handler (item, event, StreamItem);
290                 break;
291
292         case GDK_BUTTON_RELEASE:
293                 ret = button_release_handler (item, event, StreamItem);
294                 break;
295
296         case GDK_MOTION_NOTIFY:
297                 ret = motion_handler (item, event);
298                 break;
299
300         case GDK_ENTER_NOTIFY:
301                 set_entered_track (tv);
302                 break;
303
304         case GDK_LEAVE_NOTIFY:
305                 set_entered_track (0);
306                 break;
307
308         default:
309                 break;
310         }
311
312         return ret;
313 }
314
315 bool
316 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
317 {
318         bool ret = false;
319
320         switch (event->type) {
321         case GDK_BUTTON_PRESS:
322         case GDK_2BUTTON_PRESS:
323         case GDK_3BUTTON_PRESS:
324                 clicked_regionview = 0;
325                 clicked_control_point = 0;
326                 clicked_axisview = atv;
327                 clicked_routeview = 0;
328                 ret = button_press_handler (item, event, AutomationTrackItem);
329                 break;
330
331         case GDK_BUTTON_RELEASE:
332                 ret = button_release_handler (item, event, AutomationTrackItem);
333                 break;
334
335         case GDK_MOTION_NOTIFY:
336                 ret = motion_handler (item, event);
337                 break;
338
339         case GDK_ENTER_NOTIFY:
340                 ret = enter_handler (item, event, AutomationTrackItem);
341                 break;
342
343         case GDK_LEAVE_NOTIFY:
344                 ret = leave_handler (item, event, AutomationTrackItem);
345                 break;
346
347         default:
348                 break;
349         }
350
351         return ret;
352 }
353
354 bool
355 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
356 {
357         /* we handle only button 3 press/release events */
358
359         if (!rv->sensitive()) {
360                 return false;
361         }
362
363         switch (event->type) {
364         case GDK_BUTTON_PRESS:
365                 clicked_regionview = rv;
366                 clicked_control_point = 0;
367                 clicked_axisview = &rv->get_time_axis_view();
368                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
369                 if (event->button.button == 3) {
370                         return button_press_handler (item, event, FadeInItem);
371                 }
372                 break;
373
374         case GDK_BUTTON_RELEASE:
375                 if (event->button.button == 3) {
376                         return button_release_handler (item, event, FadeInItem);
377                 }
378                 break;
379
380         default:
381                 break;
382
383         }
384
385         /* proxy for the regionview */
386
387         return canvas_region_view_event (event, rv->get_canvas_group(), rv);
388 }
389
390 bool
391 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
392 {
393         bool ret = false;
394
395         if (!rv->sensitive()) {
396                 return false;
397         }
398
399         switch (event->type) {
400         case GDK_BUTTON_PRESS:
401         case GDK_2BUTTON_PRESS:
402         case GDK_3BUTTON_PRESS:
403                 clicked_regionview = rv;
404                 clicked_control_point = 0;
405                 clicked_axisview = &rv->get_time_axis_view();
406                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
407                 ret = button_press_handler (item, event, FadeInHandleItem);
408                 break;
409
410         case GDK_BUTTON_RELEASE:
411                 ret = button_release_handler (item, event, FadeInHandleItem);
412                 break;
413
414         case GDK_MOTION_NOTIFY:
415                 ret = motion_handler (item, event);
416                 break;
417
418         case GDK_ENTER_NOTIFY:
419                 ret = enter_handler (item, event, FadeInHandleItem);
420                 break;
421
422         case GDK_LEAVE_NOTIFY:
423                 ret = leave_handler (item, event, FadeInHandleItem);
424                 break;
425
426         default:
427                 break;
428         }
429
430         return ret;
431 }
432
433 bool
434 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
435 {
436         /* we handle only button 3 press/release events */
437
438         if (!rv->sensitive()) {
439                 return false;
440         }
441
442         switch (event->type) {
443         case GDK_BUTTON_PRESS:
444                 clicked_regionview = rv;
445                 clicked_control_point = 0;
446                 clicked_axisview = &rv->get_time_axis_view();
447                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
448                 if (event->button.button == 3) {
449                         return button_press_handler (item, event, FadeOutItem);
450                 }
451                 break;
452
453         case GDK_BUTTON_RELEASE:
454                 if (event->button.button == 3) {
455                         return button_release_handler (item, event, FadeOutItem);
456                 }
457                 break;
458
459         default:
460                 break;
461
462         }
463
464         /* proxy for the regionview */
465
466         return canvas_region_view_event (event, rv->get_canvas_group(), rv);
467 }
468
469 bool
470 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
471 {
472         bool ret = false;
473
474         if (!rv->sensitive()) {
475                 return false;
476         }
477
478         switch (event->type) {
479         case GDK_BUTTON_PRESS:
480         case GDK_2BUTTON_PRESS:
481         case GDK_3BUTTON_PRESS:
482                 clicked_regionview = rv;
483                 clicked_control_point = 0;
484                 clicked_axisview = &rv->get_time_axis_view();
485                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
486                 ret = button_press_handler (item, event, FadeOutHandleItem);
487                 break;
488
489         case GDK_BUTTON_RELEASE:
490                 ret = button_release_handler (item, event, FadeOutHandleItem);
491                 break;
492
493         case GDK_MOTION_NOTIFY:
494                 ret = motion_handler (item, event);
495                 break;
496
497         case GDK_ENTER_NOTIFY:
498                 ret = enter_handler (item, event, FadeOutHandleItem);
499                 break;
500
501         case GDK_LEAVE_NOTIFY:
502                 ret = leave_handler (item, event, FadeOutHandleItem);
503                 break;
504
505         default:
506                 break;
507         }
508
509         return ret;
510 }
511
512 struct DescendingRegionLayerSorter {
513     bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
514             return a->layer() > b->layer();
515     }
516 };
517
518 bool
519 Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv)
520 {
521         /* we handle only button 3 press/release events */
522
523         switch (event->type) {
524         case GDK_BUTTON_PRESS:
525                 clicked_crossfadeview = xfv;
526                 clicked_axisview = &clicked_crossfadeview->get_time_axis_view();
527                 if (event->button.button == 3) {
528                         return button_press_handler (item, event, CrossfadeViewItem);
529                 }
530                 break;
531
532         case GDK_BUTTON_RELEASE:
533                 if (event->button.button == 3) {
534                         bool ret = button_release_handler (item, event, CrossfadeViewItem);
535                         return ret;
536                 }
537                 break;
538
539         default:
540                 break;
541
542         }
543
544         /* XXX do not forward double clicks */
545
546         if (event->type == GDK_2BUTTON_PRESS) {
547                 return false;
548         }
549
550         /* proxy for an underlying regionview */
551
552         /* XXX really need to check if we are in the name highlight,
553            and proxy to that when required.
554         */
555
556         TimeAxisView& tv (xfv->get_time_axis_view());
557         AudioTimeAxisView* atv;
558
559         if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
560
561                 if (atv->is_audio_track()) {
562
563                         boost::shared_ptr<AudioPlaylist> pl;
564                         if ((pl = boost::dynamic_pointer_cast<AudioPlaylist> (atv->track()->playlist())) != 0) {
565
566                                 Playlist::RegionList* rl = pl->regions_at (event_frame (event));
567                                 if (!rl->empty()) {
568
569                                         if (atv->layer_display() == Overlaid) {
570
571                                                 /* we're in overlaid mode; proxy to the uppermost region view */
572
573                                                 DescendingRegionLayerSorter cmp;
574                                                 rl->sort (cmp);
575
576                                                 RegionView* rv = atv->view()->find_view (rl->front());
577
578                                                 delete rl;
579
580                                                 /* proxy */
581                                                 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
582
583                                         } else {
584
585                                                 /* we're in stacked mode; proxy to the region view under the mouse */
586
587                                                 /* XXX: FIXME: this is an evil hack; it assumes that any event for which
588                                                    this proxy is being used has its GdkEvent laid out such that the y
589                                                    member is in the same place as that for a GdkEventButton */
590
591                                                 /* position of the event within the track */
592                                                 double cx = event->button.x;
593                                                 double cy = event->button.y;
594                                                 atv->view()->canvas_item()->w2i (cx, cy);
595
596                                                 /* hence layer that we're over */
597                                                 double const c = atv->view()->child_height ();
598                                                 layer_t const l = pl->top_layer () + 1 - (cy / c);
599
600                                                 /* hence region */
601                                                 Playlist::RegionList::iterator i = rl->begin();
602                                                 while (i != rl->end() && (*i)->layer() != l) {
603                                                         ++i;
604                                                 }
605
606                                                 if (i != rl->end()) {
607                                                         RegionView* rv = atv->view()->find_view (*i);
608                                                         delete rl;
609
610                                                         /* proxy */
611                                                         return canvas_region_view_event (event, rv->get_canvas_group(), rv);
612                                                 }
613                                         }
614                                 }
615
616                                 delete rl;
617                         }
618                 }
619         }
620
621         return TRUE;
622 }
623
624 bool
625 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
626 {
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;
635                 break;
636
637         case GDK_SCROLL_UP:
638                 break;
639
640         case GDK_SCROLL_DOWN:
641                 break;
642
643         default:
644                 break;
645         }
646
647         return typed_event (item, event, ControlPointItem);
648 }
649
650 bool
651 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
652 {
653         ItemType type;
654
655         if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
656                 type = GainLineItem;
657         } else {
658                 type = AutomationLineItem;
659         }
660
661         return typed_event (item, event, type);
662 }
663
664 bool
665 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
666 {
667         bool ret = false;
668
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);
675                 break;
676         case GDK_BUTTON_RELEASE:
677                 ret = button_release_handler (item, event, SelectionItem);
678                 break;
679         case GDK_MOTION_NOTIFY:
680                 ret = motion_handler (item, event);
681                 break;
682                 /* Don't need these at the moment. */
683         case GDK_ENTER_NOTIFY:
684                 ret = enter_handler (item, event, SelectionItem);
685                 break;
686
687         case GDK_LEAVE_NOTIFY:
688                 ret = leave_handler (item, event, SelectionItem);
689                 break;
690
691         default:
692                 break;
693         }
694
695         return ret;
696 }
697
698 bool
699 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
700 {
701         bool ret = false;
702
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);
709                 break;
710         case GDK_BUTTON_RELEASE:
711                 ret = button_release_handler (item, event, StartSelectionTrimItem);
712                 break;
713         case GDK_MOTION_NOTIFY:
714                 ret = motion_handler (item, event);
715                 break;
716         case GDK_ENTER_NOTIFY:
717                 ret = enter_handler (item, event, StartSelectionTrimItem);
718                 break;
719
720         case GDK_LEAVE_NOTIFY:
721                 ret = leave_handler (item, event, StartSelectionTrimItem);
722                 break;
723
724         default:
725                 break;
726         }
727
728         return ret;
729 }
730
731 bool
732 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
733 {
734         bool ret = false;
735
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);
742                 break;
743         case GDK_BUTTON_RELEASE:
744                 ret = button_release_handler (item, event, EndSelectionTrimItem);
745                 break;
746         case GDK_MOTION_NOTIFY:
747                 ret = motion_handler (item, event);
748                 break;
749         case GDK_ENTER_NOTIFY:
750                 ret = enter_handler (item, event, EndSelectionTrimItem);
751                 break;
752
753         case GDK_LEAVE_NOTIFY:
754                 ret = leave_handler (item, event, EndSelectionTrimItem);
755                 break;
756
757         default:
758                 break;
759         }
760
761         return ret;
762 }
763
764 bool
765 Editor::canvas_frame_handle_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
766 {
767         bool ret = false;
768
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.
771         */
772
773         if (internal_editing() || !rv->sensitive()) {
774                 return false;
775         }
776
777         /* NOTE: frame handles pretend to be the colored trim bar from an event handling
778            perspective. XXX change this ??
779         */
780
781         switch (event->type) {
782         case GDK_BUTTON_PRESS:
783         case GDK_2BUTTON_PRESS:
784         case GDK_3BUTTON_PRESS:
785                 clicked_regionview = rv;
786                 clicked_control_point = 0;
787                 clicked_axisview = &clicked_regionview->get_time_axis_view();
788                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
789                 ret = button_press_handler (item, event, RegionViewNameHighlight);
790                 break;
791         case GDK_BUTTON_RELEASE:
792                 ret = button_release_handler (item, event, RegionViewNameHighlight);
793                 break;
794         case GDK_MOTION_NOTIFY:
795                 ret = motion_handler (item, event);
796                 break;
797         case GDK_ENTER_NOTIFY:
798                 ret = enter_handler (item, event, RegionViewNameHighlight);
799                 break;
800
801         case GDK_LEAVE_NOTIFY:
802                 ret = leave_handler (item, event, RegionViewNameHighlight);
803                 break;
804
805         default:
806                 break;
807         }
808
809         return ret;
810 }
811
812
813 bool
814 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
815 {
816         bool ret = false;
817
818         if (!rv->sensitive()) {
819                 return false;
820         }
821
822         switch (event->type) {
823         case GDK_BUTTON_PRESS:
824         case GDK_2BUTTON_PRESS:
825         case GDK_3BUTTON_PRESS:
826                 clicked_regionview = rv;
827                 clicked_control_point = 0;
828                 clicked_axisview = &clicked_regionview->get_time_axis_view();
829                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
830                 ret = button_press_handler (item, event, RegionViewNameHighlight);
831                 break;
832         case GDK_BUTTON_RELEASE:
833                 ret = button_release_handler (item, event, RegionViewNameHighlight);
834                 break;
835         case GDK_MOTION_NOTIFY:
836                 ret = motion_handler (item, event);
837                 break;
838         case GDK_ENTER_NOTIFY:
839                 ret = enter_handler (item, event, RegionViewNameHighlight);
840                 break;
841
842         case GDK_LEAVE_NOTIFY:
843                 ret = leave_handler (item, event, RegionViewNameHighlight);
844                 break;
845
846         default:
847                 break;
848         }
849
850         return ret;
851 }
852
853 bool
854 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
855 {
856         bool ret = false;
857
858         if (!rv->sensitive()) {
859                 return false;
860         }
861
862         switch (event->type) {
863         case GDK_BUTTON_PRESS:
864         case GDK_2BUTTON_PRESS:
865         case GDK_3BUTTON_PRESS:
866                 clicked_regionview = rv;
867                 clicked_control_point = 0;
868                 clicked_axisview = &clicked_regionview->get_time_axis_view();
869                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
870                 ret = button_press_handler (item, event, RegionViewName);
871                 break;
872         case GDK_BUTTON_RELEASE:
873                 ret = button_release_handler (item, event, RegionViewName);
874                 break;
875         case GDK_MOTION_NOTIFY:
876                 ret = motion_handler (item, event);
877                 break;
878         case GDK_ENTER_NOTIFY:
879                 ret = enter_handler (item, event, RegionViewName);
880                 break;
881
882         case GDK_LEAVE_NOTIFY:
883                 ret = leave_handler (item, event, RegionViewName);
884                 break;
885
886         default:
887                 break;
888         }
889
890         return ret;
891 }
892
893 bool
894 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* /*marker*/)
895 {
896         return typed_event (item, event, MarkerItem);
897 }
898
899 bool
900 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
901 {
902         return typed_event (item, event, MarkerBarItem);
903 }
904
905 bool
906 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
907 {
908         return typed_event (item, event, RangeMarkerBarItem);
909 }
910
911 bool
912 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
913 {
914         return typed_event (item, event, TransportMarkerBarItem);
915 }
916
917 bool
918 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
919 {
920         return typed_event (item, event, CdMarkerBarItem);
921 }
922
923 bool
924 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* /*marker*/)
925 {
926         return typed_event (item, event, TempoMarkerItem);
927 }
928
929 bool
930 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* /*marker*/)
931 {
932         return typed_event (item, event, MeterMarkerItem);
933 }
934
935 bool
936 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
937 {
938         return typed_event (item, event, TempoBarItem);
939 }
940
941 bool
942 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
943 {
944         return typed_event (item, event, MeterBarItem);
945 }
946
947 bool
948 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
949 {
950         return typed_event (item, event, PlayheadCursorItem);
951 }
952
953 bool
954 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
955 {
956         return typed_event (item, event, NoItem);
957 }
958
959 bool
960 Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
961 {
962         if (!internal_editing()) {
963                 return false;
964         }
965
966         return typed_event (item, event, NoteItem);
967 }
968
969 bool
970 Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const & /*c*/, int x, int y, guint /*time*/)
971 {
972         double wx;
973         double wy;
974         track_canvas->window_to_world (x, y, wx, wy);
975
976         GdkEvent event;
977         event.type = GDK_MOTION_NOTIFY;
978         event.button.x = wx;
979         event.button.y = wy;
980         /* assume we're dragging with button 1 */
981         event.motion.state = Gdk::BUTTON1_MASK;
982
983         if (!_drags->active ()) {
984
985                 double px;
986                 double py;
987                 nframes64_t const pos = event_frame (&event, &px, &py);
988
989                 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py);
990                 if (tv.first == 0) {
991                         return true;
992                 }
993
994                 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
995                 if (rtav == 0 || !rtav->is_track ()) {
996                         return true;
997                 }
998
999                 boost::shared_ptr<Region> region = _regions->get_dragged_region ();
1000
1001                 boost::shared_ptr<Region> region_copy = RegionFactory::create (region);
1002
1003                 if (boost::dynamic_pointer_cast<AudioRegion> (region_copy) != 0 &&
1004                     dynamic_cast<AudioTimeAxisView*> (tv.first) == 0) {
1005
1006                         /* audio -> non-audio */
1007                         return true;
1008                 }
1009
1010                 if (boost::dynamic_pointer_cast<MidiRegion> (region_copy) == 0 &&
1011                     dynamic_cast<MidiTimeAxisView*> (tv.first) != 0) {
1012
1013                         /* MIDI -> non-MIDI */
1014                         return true;
1015                 }
1016
1017                 _drags->set (new RegionInsertDrag (this, region_copy, rtav, pos), &event);
1018         }
1019
1020         _drags->motion_handler (&event, false);
1021
1022         return true;
1023 }