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