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