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