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