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