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