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