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