First cut of some Pro-tools inspired editing features; linked play/play range
[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 (_drag) {
200                 _drag->end_grab ((GdkEvent*) event);
201                 delete _drag;
202                 _drag = 0;
203         }
204         return false;
205 }
206
207 bool
208 Editor::track_canvas_motion_notify_event (GdkEventMotion */*event*/)
209 {
210         int x, y;
211         /* keep those motion events coming */
212         track_canvas->get_pointer (x, y);
213         return false;
214 }
215
216 bool
217 Editor::track_canvas_motion (GdkEvent *ev)
218 {
219         if (verbose_cursor_visible) {
220                 verbose_canvas_cursor->property_x() = clamp_verbose_cursor_x (ev->motion.x + 10);
221                 verbose_canvas_cursor->property_y() = clamp_verbose_cursor_y (ev->motion.y + 10);
222         }
223
224         return false;
225 }
226
227 bool
228 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
229 {
230         gint ret = FALSE;
231
232         switch (event->type) {
233         case GDK_BUTTON_PRESS:
234         case GDK_2BUTTON_PRESS:
235         case GDK_3BUTTON_PRESS:
236                 ret = button_press_handler (item, event, type);
237                 break;
238         case GDK_BUTTON_RELEASE:
239                 ret = button_release_handler (item, event, type);
240                 break;
241         case GDK_MOTION_NOTIFY:
242                 ret = motion_handler (item, event);
243                 break;
244
245         case GDK_ENTER_NOTIFY:
246                 ret = enter_handler (item, event, type);
247                 break;
248
249         case GDK_LEAVE_NOTIFY:
250                 ret = leave_handler (item, event, type);
251                 break;
252
253         default:
254                 break;
255         }
256         return ret;
257 }
258
259 bool
260 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
261 {
262         bool ret = false;
263
264         if (!rv->sensitive ()) {
265                 return false;
266         }
267
268         switch (event->type) {
269         case GDK_BUTTON_PRESS:
270         case GDK_2BUTTON_PRESS:
271         case GDK_3BUTTON_PRESS:
272                 clicked_regionview = rv;
273                 clicked_control_point = 0;
274                 clicked_axisview = &rv->get_time_axis_view();
275                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
276                 ret = button_press_handler (item, event, RegionItem);
277                 break;
278
279         case GDK_BUTTON_RELEASE:
280                 ret = button_release_handler (item, event, RegionItem);
281                 break;
282
283         case GDK_MOTION_NOTIFY:
284                 ret = motion_handler (item, event);
285                 break;
286
287         case GDK_ENTER_NOTIFY:
288                 set_entered_track (&rv->get_time_axis_view ());
289                 set_entered_regionview (rv);
290                 break;
291
292         case GDK_LEAVE_NOTIFY:
293                 set_entered_track (0);
294                 set_entered_regionview (0);
295                 break;
296
297         default:
298                 break;
299         }
300
301         return ret;
302 }
303
304 bool
305 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
306 {
307         bool ret = FALSE;
308
309         switch (event->type) {
310         case GDK_BUTTON_PRESS:
311         case GDK_2BUTTON_PRESS:
312         case GDK_3BUTTON_PRESS:
313                 clicked_regionview = 0;
314                 clicked_control_point = 0;
315                 clicked_axisview = tv;
316                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(tv);
317                 ret = button_press_handler (item, event, StreamItem);
318                 break;
319
320         case GDK_BUTTON_RELEASE:
321                 ret = button_release_handler (item, event, StreamItem);
322                 break;
323
324         case GDK_MOTION_NOTIFY:
325                 ret = motion_handler (item, event);
326                 break;
327
328         case GDK_ENTER_NOTIFY:
329                 set_entered_track (tv);
330                 break;
331
332         case GDK_LEAVE_NOTIFY:
333                 set_entered_track (0);
334                 break;
335
336         default:
337                 break;
338         }
339
340         return ret;
341 }
342
343 bool
344 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
345 {
346         bool ret = false;
347
348         switch (event->type) {
349         case GDK_BUTTON_PRESS:
350         case GDK_2BUTTON_PRESS:
351         case GDK_3BUTTON_PRESS:
352                 clicked_regionview = 0;
353                 clicked_control_point = 0;
354                 clicked_axisview = atv;
355                 clicked_routeview = 0;
356                 ret = button_press_handler (item, event, AutomationTrackItem);
357                 break;
358
359         case GDK_BUTTON_RELEASE:
360                 ret = button_release_handler (item, event, AutomationTrackItem);
361                 break;
362
363         case GDK_MOTION_NOTIFY:
364                 ret = motion_handler (item, event);
365                 break;
366
367         case GDK_ENTER_NOTIFY:
368                 ret = enter_handler (item, event, AutomationTrackItem);
369                 break;
370
371         case GDK_LEAVE_NOTIFY:
372                 ret = leave_handler (item, event, AutomationTrackItem);
373                 break;
374
375         default:
376                 break;
377         }
378
379         return ret;
380 }
381
382 bool
383 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
384 {
385         /* we handle only button 3 press/release events */
386
387         if (!rv->sensitive()) {
388                 return false;
389         }
390
391         switch (event->type) {
392         case GDK_BUTTON_PRESS:
393                 clicked_regionview = rv;
394                 clicked_control_point = 0;
395                 clicked_axisview = &rv->get_time_axis_view();
396                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
397                 if (event->button.button == 3) {
398                         return button_press_handler (item, event, FadeInItem);
399                 }
400                 break;
401
402         case GDK_BUTTON_RELEASE:
403                 if (event->button.button == 3) {
404                         return button_release_handler (item, event, FadeInItem);
405                 }
406                 break;
407
408         default:
409                 break;
410
411         }
412
413         /* proxy for the regionview */
414
415         return canvas_region_view_event (event, rv->get_canvas_group(), rv);
416 }
417
418 bool
419 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
420 {
421         bool ret = false;
422
423         if (!rv->sensitive()) {
424                 return false;
425         }
426
427         switch (event->type) {
428         case GDK_BUTTON_PRESS:
429         case GDK_2BUTTON_PRESS:
430         case GDK_3BUTTON_PRESS:
431                 clicked_regionview = rv;
432                 clicked_control_point = 0;
433                 clicked_axisview = &rv->get_time_axis_view();
434                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
435                 ret = button_press_handler (item, event, FadeInHandleItem);
436                 break;
437
438         case GDK_BUTTON_RELEASE:
439                 ret = button_release_handler (item, event, FadeInHandleItem);
440                 break;
441
442         case GDK_MOTION_NOTIFY:
443                 ret = motion_handler (item, event);
444                 break;
445
446         case GDK_ENTER_NOTIFY:
447                 ret = enter_handler (item, event, FadeInHandleItem);
448                 break;
449
450         case GDK_LEAVE_NOTIFY:
451                 ret = leave_handler (item, event, FadeInHandleItem);
452                 break;
453
454         default:
455                 break;
456         }
457
458         return ret;
459 }
460
461 bool
462 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
463 {
464         /* we handle only button 3 press/release events */
465
466         if (!rv->sensitive()) {
467                 return false;
468         }
469
470         switch (event->type) {
471         case GDK_BUTTON_PRESS:
472                 clicked_regionview = rv;
473                 clicked_control_point = 0;
474                 clicked_axisview = &rv->get_time_axis_view();
475                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
476                 if (event->button.button == 3) {
477                         return button_press_handler (item, event, FadeOutItem);
478                 }
479                 break;
480
481         case GDK_BUTTON_RELEASE:
482                 if (event->button.button == 3) {
483                         return button_release_handler (item, event, FadeOutItem);
484                 }
485                 break;
486
487         default:
488                 break;
489
490         }
491
492         /* proxy for the regionview */
493
494         return canvas_region_view_event (event, rv->get_canvas_group(), rv);
495 }
496
497 bool
498 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
499 {
500         bool ret = false;
501
502         if (!rv->sensitive()) {
503                 return false;
504         }
505
506         switch (event->type) {
507         case GDK_BUTTON_PRESS:
508         case GDK_2BUTTON_PRESS:
509         case GDK_3BUTTON_PRESS:
510                 clicked_regionview = rv;
511                 clicked_control_point = 0;
512                 clicked_axisview = &rv->get_time_axis_view();
513                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
514                 ret = button_press_handler (item, event, FadeOutHandleItem);
515                 break;
516
517         case GDK_BUTTON_RELEASE:
518                 ret = button_release_handler (item, event, FadeOutHandleItem);
519                 break;
520
521         case GDK_MOTION_NOTIFY:
522                 ret = motion_handler (item, event);
523                 break;
524
525         case GDK_ENTER_NOTIFY:
526                 ret = enter_handler (item, event, FadeOutHandleItem);
527                 break;
528
529         case GDK_LEAVE_NOTIFY:
530                 ret = leave_handler (item, event, FadeOutHandleItem);
531                 break;
532
533         default:
534                 break;
535         }
536
537         return ret;
538 }
539
540 struct DescendingRegionLayerSorter {
541     bool operator()(boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
542             return a->layer() > b->layer();
543     }
544 };
545
546 bool
547 Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv)
548 {
549         /* we handle only button 3 press/release events */
550
551         switch (event->type) {
552         case GDK_BUTTON_PRESS:
553                 clicked_crossfadeview = xfv;
554                 clicked_axisview = &clicked_crossfadeview->get_time_axis_view();
555                 if (event->button.button == 3) {
556                         return button_press_handler (item, event, CrossfadeViewItem);
557                 }
558                 break;
559
560         case GDK_BUTTON_RELEASE:
561                 if (event->button.button == 3) {
562                         bool ret = button_release_handler (item, event, CrossfadeViewItem);
563                         return ret;
564                 }
565                 break;
566
567         default:
568                 break;
569
570         }
571
572         /* XXX do not forward double clicks */
573
574         if (event->type == GDK_2BUTTON_PRESS) {
575                 return false;
576         }
577
578         /* proxy for an underlying regionview */
579
580         /* XXX really need to check if we are in the name highlight,
581            and proxy to that when required.
582         */
583
584         TimeAxisView& tv (xfv->get_time_axis_view());
585         AudioTimeAxisView* atv;
586
587         if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
588
589                 if (atv->is_audio_track()) {
590
591                         boost::shared_ptr<AudioPlaylist> pl;
592                         if ((pl = boost::dynamic_pointer_cast<AudioPlaylist> (atv->get_diskstream()->playlist())) != 0) {
593
594                                 Playlist::RegionList* rl = pl->regions_at (event_frame (event));
595                                 if (!rl->empty()) {
596
597                                         if (atv->layer_display() == Overlaid) {
598
599                                                 /* we're in overlaid mode; proxy to the uppermost region view */
600
601                                                 DescendingRegionLayerSorter cmp;
602                                                 rl->sort (cmp);
603
604                                                 RegionView* rv = atv->view()->find_view (rl->front());
605
606                                                 delete rl;
607
608                                                 /* proxy */
609                                                 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
610
611                                         } else {
612
613                                                 /* we're in stacked mode; proxy to the region view under the mouse */
614
615                                                 /* XXX: FIXME: this is an evil hack; it assumes that any event for which
616                                                    this proxy is being used has its GdkEvent laid out such that the y
617                                                    member is in the same place as that for a GdkEventButton */
618
619                                                 /* position of the event within the track */
620                                                 double cx = event->button.x;
621                                                 double cy = event->button.y;
622                                                 atv->view()->canvas_item()->w2i (cx, cy);
623
624                                                 /* hence layer that we're over */
625                                                 double const c = atv->view()->child_height ();
626                                                 layer_t const l = pl->top_layer () + 1 - (cy / c);
627
628                                                 /* hence region */
629                                                 Playlist::RegionList::iterator i = rl->begin();
630                                                 while (i != rl->end() && (*i)->layer() != l) {
631                                                         ++i;
632                                                 }
633
634                                                 if (i != rl->end()) {
635                                                         RegionView* rv = atv->view()->find_view (*i);
636                                                         delete rl;
637
638                                                         /* proxy */
639                                                         return canvas_region_view_event (event, rv->get_canvas_group(), rv);
640                                                 }
641                                         }
642                                 }
643
644                                 delete rl;
645                         }
646                 }
647         }
648
649         return TRUE;
650 }
651
652 bool
653 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
654 {
655         switch (event->type) {
656         case GDK_BUTTON_PRESS:
657         case GDK_2BUTTON_PRESS:
658         case GDK_3BUTTON_PRESS:
659                 clicked_control_point = cp;
660                 clicked_axisview = &cp->line().trackview;
661                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
662                 clicked_regionview = 0;
663                 break;
664
665         case GDK_SCROLL_UP:
666                 break;
667
668         case GDK_SCROLL_DOWN:
669                 break;
670
671         default:
672                 break;
673         }
674
675         return typed_event (item, event, ControlPointItem);
676 }
677
678 bool
679 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
680 {
681         ItemType type;
682
683         if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
684                 type = GainLineItem;
685         } else {
686                 type = AutomationLineItem;
687         }
688
689         return typed_event (item, event, type);
690 }
691
692 bool
693 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
694 {
695         bool ret = false;
696
697         switch (event->type) {
698         case GDK_BUTTON_PRESS:
699         case GDK_2BUTTON_PRESS:
700         case GDK_3BUTTON_PRESS:
701                 clicked_selection = rect->id;
702                 ret = button_press_handler (item, event, SelectionItem);
703                 break;
704         case GDK_BUTTON_RELEASE:
705                 ret = button_release_handler (item, event, SelectionItem);
706                 break;
707         case GDK_MOTION_NOTIFY:
708                 ret = motion_handler (item, event);
709                 break;
710                 /* Don't need these at the moment. */
711         case GDK_ENTER_NOTIFY:
712                 ret = enter_handler (item, event, SelectionItem);
713                 break;
714
715         case GDK_LEAVE_NOTIFY:
716                 ret = leave_handler (item, event, SelectionItem);
717                 break;
718
719         default:
720                 break;
721         }
722
723         return ret;
724 }
725
726 bool
727 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
728 {
729         bool ret = false;
730
731         switch (event->type) {
732         case GDK_BUTTON_PRESS:
733         case GDK_2BUTTON_PRESS:
734         case GDK_3BUTTON_PRESS:
735                 clicked_selection = rect->id;
736                 ret = button_press_handler (item, event, StartSelectionTrimItem);
737                 break;
738         case GDK_BUTTON_RELEASE:
739                 ret = button_release_handler (item, event, StartSelectionTrimItem);
740                 break;
741         case GDK_MOTION_NOTIFY:
742                 ret = motion_handler (item, event);
743                 break;
744         case GDK_ENTER_NOTIFY:
745                 ret = enter_handler (item, event, StartSelectionTrimItem);
746                 break;
747
748         case GDK_LEAVE_NOTIFY:
749                 ret = leave_handler (item, event, StartSelectionTrimItem);
750                 break;
751
752         default:
753                 break;
754         }
755
756         return ret;
757 }
758
759 bool
760 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
761 {
762         bool ret = false;
763
764         switch (event->type) {
765         case GDK_BUTTON_PRESS:
766         case GDK_2BUTTON_PRESS:
767         case GDK_3BUTTON_PRESS:
768                 clicked_selection = rect->id;
769                 ret = button_press_handler (item, event, EndSelectionTrimItem);
770                 break;
771         case GDK_BUTTON_RELEASE:
772                 ret = button_release_handler (item, event, EndSelectionTrimItem);
773                 break;
774         case GDK_MOTION_NOTIFY:
775                 ret = motion_handler (item, event);
776                 break;
777         case GDK_ENTER_NOTIFY:
778                 ret = enter_handler (item, event, EndSelectionTrimItem);
779                 break;
780
781         case GDK_LEAVE_NOTIFY:
782                 ret = leave_handler (item, event, EndSelectionTrimItem);
783                 break;
784
785         default:
786                 break;
787         }
788
789         return ret;
790 }
791
792 bool
793 Editor::canvas_frame_handle_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
794 {
795         bool ret = false;
796
797         /* frame handles are not active when in internal edit mode, because actual notes
798            might be in the area occupied by the handle - we want them to be editable as normal.
799         */
800
801         if (internal_editing() || !rv->sensitive()) {
802                 return false;
803         }
804
805         /* NOTE: frame handles pretend to be the colored trim bar from an event handling
806            perspective. XXX change this ??
807         */
808
809         switch (event->type) {
810         case GDK_BUTTON_PRESS:
811         case GDK_2BUTTON_PRESS:
812         case GDK_3BUTTON_PRESS:
813                 clicked_regionview = rv;
814                 clicked_control_point = 0;
815                 clicked_axisview = &clicked_regionview->get_time_axis_view();
816                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
817                 ret = button_press_handler (item, event, RegionViewNameHighlight);
818                 break;
819         case GDK_BUTTON_RELEASE:
820                 ret = button_release_handler (item, event, RegionViewNameHighlight);
821                 break;
822         case GDK_MOTION_NOTIFY:
823                 ret = motion_handler (item, event);
824                 break;
825         case GDK_ENTER_NOTIFY:
826                 ret = enter_handler (item, event, RegionViewNameHighlight);
827                 break;
828
829         case GDK_LEAVE_NOTIFY:
830                 ret = leave_handler (item, event, RegionViewNameHighlight);
831                 break;
832
833         default:
834                 break;
835         }
836
837         return ret;
838 }
839
840
841 bool
842 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
843 {
844         bool ret = false;
845
846         if (!rv->sensitive()) {
847                 return false;
848         }
849
850         switch (event->type) {
851         case GDK_BUTTON_PRESS:
852         case GDK_2BUTTON_PRESS:
853         case GDK_3BUTTON_PRESS:
854                 clicked_regionview = rv;
855                 clicked_control_point = 0;
856                 clicked_axisview = &clicked_regionview->get_time_axis_view();
857                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
858                 ret = button_press_handler (item, event, RegionViewNameHighlight);
859                 break;
860         case GDK_BUTTON_RELEASE:
861                 ret = button_release_handler (item, event, RegionViewNameHighlight);
862                 break;
863         case GDK_MOTION_NOTIFY:
864                 ret = motion_handler (item, event);
865                 break;
866         case GDK_ENTER_NOTIFY:
867                 ret = enter_handler (item, event, RegionViewNameHighlight);
868                 break;
869
870         case GDK_LEAVE_NOTIFY:
871                 ret = leave_handler (item, event, RegionViewNameHighlight);
872                 break;
873
874         default:
875                 break;
876         }
877
878         return ret;
879 }
880
881 bool
882 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
883 {
884         bool ret = false;
885
886         if (!rv->sensitive()) {
887                 return false;
888         }
889
890         switch (event->type) {
891         case GDK_BUTTON_PRESS:
892         case GDK_2BUTTON_PRESS:
893         case GDK_3BUTTON_PRESS:
894                 clicked_regionview = rv;
895                 clicked_control_point = 0;
896                 clicked_axisview = &clicked_regionview->get_time_axis_view();
897                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
898                 ret = button_press_handler (item, event, RegionViewName);
899                 break;
900         case GDK_BUTTON_RELEASE:
901                 ret = button_release_handler (item, event, RegionViewName);
902                 break;
903         case GDK_MOTION_NOTIFY:
904                 ret = motion_handler (item, event);
905                 break;
906         case GDK_ENTER_NOTIFY:
907                 ret = enter_handler (item, event, RegionViewName);
908                 break;
909
910         case GDK_LEAVE_NOTIFY:
911                 ret = leave_handler (item, event, RegionViewName);
912                 break;
913
914         default:
915                 break;
916         }
917
918         return ret;
919 }
920
921 bool
922 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* /*marker*/)
923 {
924         return typed_event (item, event, MarkerItem);
925 }
926
927 bool
928 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
929 {
930         return typed_event (item, event, MarkerBarItem);
931 }
932
933 bool
934 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
935 {
936         return typed_event (item, event, RangeMarkerBarItem);
937 }
938
939 bool
940 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
941 {
942         return typed_event (item, event, TransportMarkerBarItem);
943 }
944
945 bool
946 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
947 {
948         return typed_event (item, event, CdMarkerBarItem);
949 }
950
951 bool
952 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* /*marker*/)
953 {
954         return typed_event (item, event, TempoMarkerItem);
955 }
956
957 bool
958 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* /*marker*/)
959 {
960         return typed_event (item, event, MeterMarkerItem);
961 }
962
963 bool
964 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
965 {
966         return typed_event (item, event, TempoBarItem);
967 }
968
969 bool
970 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
971 {
972         return typed_event (item, event, MeterBarItem);
973 }
974
975 bool
976 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
977 {
978         return typed_event (item, event, PlayheadCursorItem);
979 }
980
981 bool
982 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
983 {
984         return typed_event (item, event, NoItem);
985 }
986
987 bool
988 Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
989 {
990         if (!internal_editing()) {
991                 return false;
992         }
993
994         return typed_event (item, event, NoteItem);
995 }
996
997 bool
998 Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const & /*c*/, int x, int y, guint /*time*/)
999 {
1000         double wx;
1001         double wy;
1002         track_canvas->window_to_world (x, y, wx, wy);
1003
1004         GdkEvent event;
1005         event.type = GDK_MOTION_NOTIFY;
1006         event.button.x = wx;
1007         event.button.y = wy;
1008         /* assume we're dragging with button 1 */
1009         event.motion.state = Gdk::BUTTON1_MASK;
1010
1011         if (_drag == 0) {
1012
1013                 double px;
1014                 double py;
1015                 nframes64_t const pos = event_frame (&event, &px, &py);
1016
1017                 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py);
1018                 if (tv.first == 0) {
1019                         return true;
1020                 }
1021
1022                 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1023                 if (rtav == 0 || !rtav->is_track ()) {
1024                         return true;
1025                 }
1026
1027                 boost::shared_ptr<Region> region = _regions->get_dragged_region ();
1028
1029                 boost::shared_ptr<Region> region_copy = RegionFactory::create (region);
1030
1031                 if (boost::dynamic_pointer_cast<AudioRegion> (region_copy) != 0 &&
1032                     dynamic_cast<AudioTimeAxisView*> (tv.first) == 0) {
1033
1034                         /* audio -> non-audio */
1035                         return true;
1036                 }
1037
1038                 if (boost::dynamic_pointer_cast<MidiRegion> (region_copy) == 0 &&
1039                     dynamic_cast<MidiTimeAxisView*> (tv.first) != 0) {
1040
1041                         /* MIDI -> non-MIDI */
1042                         return true;
1043                 }
1044
1045                 _drag = new RegionInsertDrag (this, region_copy, rtav, pos);
1046                 _drag->start_grab (&event);
1047         }
1048
1049         _drag->motion_handler (&event, false);
1050
1051         return true;
1052 }