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