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