215cea347043ef18a0568d5a6e052c6d1aa5c175
[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                                 Playlist::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                                                 delete rl;
584
585                                                 /* proxy */
586                                                 return canvas_region_view_event (event, rv->get_canvas_group(), rv);
587
588                                         } else {
589
590                                                 /* we're in stacked mode; proxy to the region view under the mouse */
591
592                                                 double cx = 0;
593                                                 double cy = 0;
594                                                 switch (event->type) {
595                                                 case GDK_BUTTON_PRESS:
596                                                 case GDK_BUTTON_RELEASE:
597                                                         cx = event->button.x;
598                                                         cy = event->button.y;
599                                                         break;
600                                                 case GDK_MOTION_NOTIFY:
601                                                         cx = event->motion.x;
602                                                         cy = event->motion.y;
603                                                         break;
604                                                 case GDK_ENTER_NOTIFY:
605                                                 case GDK_LEAVE_NOTIFY:
606                                                         cx = event->crossing.x;
607                                                         cy = event->crossing.y;
608                                                         break;
609                                                 default:
610                                                         /* XXX: this may be wrong for some events */
611                                                         cx = event->button.x;
612                                                         cy = event->button.y;
613                                                 }
614
615                                                 /* position of the event within the track */
616                                                 atv->view()->canvas_item()->w2i (cx, cy);
617
618                                                 /* hence layer that we're over */
619                                                 double const c = atv->view()->child_height ();
620                                                 layer_t const l = pl->top_layer () + 1 - (cy / c);
621
622                                                 /* hence region */
623                                                 Playlist::RegionList::iterator i = rl->begin();
624                                                 while (i != rl->end() && (*i)->layer() != l) {
625                                                         ++i;
626                                                 }
627
628                                                 if (i != rl->end()) {
629                                                         RegionView* rv = atv->view()->find_view (*i);
630                                                         delete rl;
631
632                                                         /* proxy */
633                                                         return canvas_region_view_event (event, rv->get_canvas_group(), rv);
634                                                 }
635                                         }
636                                 }
637
638                                 delete rl;
639                         }
640                 }
641         }
642
643         return TRUE;
644 }
645
646 bool
647 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
648 {
649         switch (event->type) {
650         case GDK_BUTTON_PRESS:
651         case GDK_2BUTTON_PRESS:
652         case GDK_3BUTTON_PRESS:
653                 clicked_control_point = cp;
654                 clicked_axisview = &cp->line().trackview;
655                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
656                 clicked_regionview = 0;
657                 break;
658
659         case GDK_SCROLL_UP:
660                 break;
661
662         case GDK_SCROLL_DOWN:
663                 break;
664
665         default:
666                 break;
667         }
668
669         return typed_event (item, event, ControlPointItem);
670 }
671
672 bool
673 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
674 {
675         ItemType type;
676
677         if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
678                 type = GainLineItem;
679         } else {
680                 type = AutomationLineItem;
681         }
682
683         return typed_event (item, event, type);
684 }
685
686 bool
687 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
688 {
689         bool ret = false;
690
691         switch (event->type) {
692         case GDK_BUTTON_PRESS:
693         case GDK_2BUTTON_PRESS:
694         case GDK_3BUTTON_PRESS:
695                 clicked_selection = rect->id;
696                 ret = button_press_handler (item, event, SelectionItem);
697                 break;
698         case GDK_BUTTON_RELEASE:
699                 ret = button_release_handler (item, event, SelectionItem);
700                 break;
701         case GDK_MOTION_NOTIFY:
702                 ret = motion_handler (item, event);
703                 break;
704                 /* Don't need these at the moment. */
705         case GDK_ENTER_NOTIFY:
706                 ret = enter_handler (item, event, SelectionItem);
707                 break;
708
709         case GDK_LEAVE_NOTIFY:
710                 ret = leave_handler (item, event, SelectionItem);
711                 break;
712
713         default:
714                 break;
715         }
716
717         return ret;
718 }
719
720 bool
721 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
722 {
723         bool ret = false;
724
725         switch (event->type) {
726         case GDK_BUTTON_PRESS:
727         case GDK_2BUTTON_PRESS:
728         case GDK_3BUTTON_PRESS:
729                 clicked_selection = rect->id;
730                 ret = button_press_handler (item, event, StartSelectionTrimItem);
731                 break;
732         case GDK_BUTTON_RELEASE:
733                 ret = button_release_handler (item, event, StartSelectionTrimItem);
734                 break;
735         case GDK_MOTION_NOTIFY:
736                 ret = motion_handler (item, event);
737                 break;
738         case GDK_ENTER_NOTIFY:
739                 ret = enter_handler (item, event, StartSelectionTrimItem);
740                 break;
741
742         case GDK_LEAVE_NOTIFY:
743                 ret = leave_handler (item, event, StartSelectionTrimItem);
744                 break;
745
746         default:
747                 break;
748         }
749
750         return ret;
751 }
752
753 bool
754 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
755 {
756         bool ret = false;
757
758         switch (event->type) {
759         case GDK_BUTTON_PRESS:
760         case GDK_2BUTTON_PRESS:
761         case GDK_3BUTTON_PRESS:
762                 clicked_selection = rect->id;
763                 ret = button_press_handler (item, event, EndSelectionTrimItem);
764                 break;
765         case GDK_BUTTON_RELEASE:
766                 ret = button_release_handler (item, event, EndSelectionTrimItem);
767                 break;
768         case GDK_MOTION_NOTIFY:
769                 ret = motion_handler (item, event);
770                 break;
771         case GDK_ENTER_NOTIFY:
772                 ret = enter_handler (item, event, EndSelectionTrimItem);
773                 break;
774
775         case GDK_LEAVE_NOTIFY:
776                 ret = leave_handler (item, event, EndSelectionTrimItem);
777                 break;
778
779         default:
780                 break;
781         }
782
783         return ret;
784 }
785
786 bool
787 Editor::canvas_frame_handle_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
788 {
789         bool ret = false;
790
791         /* frame handles are not active when in internal edit mode, because actual notes
792            might be in the area occupied by the handle - we want them to be editable as normal.
793         */
794
795         if (internal_editing() || !rv->sensitive()) {
796                 return false;
797         }
798
799         /* NOTE: frame handles pretend to be the colored trim bar from an event handling
800            perspective. XXX change this ??
801         */
802
803         ItemType type;
804
805         if (item->get_data ("isleft")) {
806                 type = LeftFrameHandle;
807         } else {
808                 type = RightFrameHandle;
809         }
810
811         switch (event->type) {
812         case GDK_BUTTON_PRESS:
813         case GDK_2BUTTON_PRESS:
814         case GDK_3BUTTON_PRESS:
815                 clicked_regionview = rv;
816                 clicked_control_point = 0;
817                 clicked_axisview = &clicked_regionview->get_time_axis_view();
818                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
819                 ret = button_press_handler (item, event, type);
820                 break;
821         case GDK_BUTTON_RELEASE:
822                 ret = button_release_handler (item, event, type);
823                 break;
824         case GDK_MOTION_NOTIFY:
825                 ret = motion_handler (item, event);
826                 break;
827         case GDK_ENTER_NOTIFY:
828                 set_entered_regionview (rv);
829                 ret = enter_handler (item, event, type);
830                 break;
831
832         case GDK_LEAVE_NOTIFY:
833                 set_entered_regionview (0);
834                 ret = leave_handler (item, event, type);
835                 break;
836
837         default:
838                 break;
839         }
840
841         return ret;
842 }
843
844
845 bool
846 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
847 {
848         bool ret = false;
849
850         if (!rv->sensitive()) {
851                 return false;
852         }
853
854         switch (event->type) {
855         case GDK_BUTTON_PRESS:
856         case GDK_2BUTTON_PRESS:
857         case GDK_3BUTTON_PRESS:
858                 clicked_regionview = rv;
859                 clicked_control_point = 0;
860                 clicked_axisview = &clicked_regionview->get_time_axis_view();
861                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
862                 ret = button_press_handler (item, event, RegionViewNameHighlight);
863                 break;
864         case GDK_BUTTON_RELEASE:
865                 ret = button_release_handler (item, event, RegionViewNameHighlight);
866                 break;
867         case GDK_MOTION_NOTIFY:
868                 motion_handler (item, event);
869                 ret = true; // force this to avoid progagating the event into the regionview
870                 break;
871         case GDK_ENTER_NOTIFY:
872                 set_entered_regionview (rv);
873                 ret = enter_handler (item, event, RegionViewNameHighlight);
874                 break;
875
876         case GDK_LEAVE_NOTIFY:
877                 set_entered_regionview (0);
878                 ret = leave_handler (item, event, RegionViewNameHighlight);
879                 break;
880
881         default:
882                 break;
883         }
884
885         return ret;
886 }
887
888 bool
889 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
890 {
891         bool ret = false;
892
893         if (!rv->sensitive()) {
894                 return false;
895         }
896
897         switch (event->type) {
898         case GDK_BUTTON_PRESS:
899         case GDK_2BUTTON_PRESS:
900         case GDK_3BUTTON_PRESS:
901                 clicked_regionview = rv;
902                 clicked_control_point = 0;
903                 clicked_axisview = &clicked_regionview->get_time_axis_view();
904                 clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
905                 ret = button_press_handler (item, event, RegionViewName);
906                 break;
907         case GDK_BUTTON_RELEASE:
908                 ret = button_release_handler (item, event, RegionViewName);
909                 break;
910         case GDK_MOTION_NOTIFY:
911                 ret = motion_handler (item, event);
912                 break;
913         case GDK_ENTER_NOTIFY:
914                 set_entered_regionview (rv);
915                 ret = enter_handler (item, event, RegionViewName);
916                 break;
917
918         case GDK_LEAVE_NOTIFY:
919                 set_entered_regionview (0);
920                 ret = leave_handler (item, event, RegionViewName);
921                 break;
922
923         default:
924                 break;
925         }
926
927         return ret;
928 }
929
930 bool
931 Editor::canvas_feature_line_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView*)
932 {
933         bool ret = false;
934
935         switch (event->type) {
936         case GDK_BUTTON_PRESS:
937         case GDK_2BUTTON_PRESS:
938         case GDK_3BUTTON_PRESS:
939                 clicked_regionview = 0;
940                 clicked_control_point = 0;
941                 clicked_axisview = 0;
942                 clicked_routeview = 0; //dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
943                 ret = button_press_handler (item, event, FeatureLineItem);
944                 break;
945
946         case GDK_BUTTON_RELEASE:
947                 ret = button_release_handler (item, event, FeatureLineItem);
948                 break;
949
950         case GDK_MOTION_NOTIFY:
951                 ret = motion_handler (item, event);
952                 break;
953
954         case GDK_ENTER_NOTIFY:
955                 ret = enter_handler (item, event, FeatureLineItem);
956                 break;
957
958         case GDK_LEAVE_NOTIFY:
959                 ret = leave_handler (item, event, FeatureLineItem);
960                 break;
961
962         default:
963                 break;
964         }
965
966         return ret;
967 }
968
969 bool
970 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* /*marker*/)
971 {
972         return typed_event (item, event, MarkerItem);
973 }
974
975 bool
976 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
977 {
978         return typed_event (item, event, MarkerBarItem);
979 }
980
981 bool
982 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
983 {
984         return typed_event (item, event, RangeMarkerBarItem);
985 }
986
987 bool
988 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
989 {
990         return typed_event (item, event, TransportMarkerBarItem);
991 }
992
993 bool
994 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
995 {
996         return typed_event (item, event, CdMarkerBarItem);
997 }
998
999 bool
1000 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* /*marker*/)
1001 {
1002         return typed_event (item, event, TempoMarkerItem);
1003 }
1004
1005 bool
1006 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* /*marker*/)
1007 {
1008         return typed_event (item, event, MeterMarkerItem);
1009 }
1010
1011 bool
1012 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1013 {
1014         return typed_event (item, event, TempoBarItem);
1015 }
1016
1017 bool
1018 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1019 {
1020         return typed_event (item, event, MeterBarItem);
1021 }
1022
1023 bool
1024 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
1025 {
1026         return typed_event (item, event, PlayheadCursorItem);
1027 }
1028
1029 bool
1030 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
1031 {
1032         return typed_event (item, event, NoItem);
1033 }
1034
1035 bool
1036 Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
1037 {
1038         if (!internal_editing()) {
1039                 return false;
1040         }
1041
1042         return typed_event (item, event, NoteItem);
1043 }
1044
1045 bool
1046 Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const & /*c*/, int x, int y, guint /*time*/)
1047 {
1048         double wx;
1049         double wy;
1050         track_canvas->window_to_world (x, y, wx, wy);
1051
1052         GdkEvent event;
1053         event.type = GDK_MOTION_NOTIFY;
1054         event.button.x = wx;
1055         event.button.y = wy;
1056         /* assume we're dragging with button 1 */
1057         event.motion.state = Gdk::BUTTON1_MASK;
1058
1059         if (!_drags->active ()) {
1060
1061                 double px;
1062                 double py;
1063                 framepos_t const pos = event_frame (&event, &px, &py);
1064
1065                 std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py);
1066                 if (tv.first == 0) {
1067                         return true;
1068                 }
1069
1070                 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1071                 if (rtav == 0 || !rtav->is_track ()) {
1072                         return true;
1073                 }
1074
1075                 boost::shared_ptr<Region> region = _regions->get_dragged_region ();
1076
1077                 if (!region) {
1078                         return true;
1079                 }
1080
1081                 boost::shared_ptr<Region> region_copy = RegionFactory::create (region);
1082
1083                 if (boost::dynamic_pointer_cast<AudioRegion> (region_copy) != 0 &&
1084                     dynamic_cast<AudioTimeAxisView*> (tv.first) == 0) {
1085
1086                         /* audio -> non-audio */
1087                         return true;
1088                 }
1089
1090                 if (boost::dynamic_pointer_cast<MidiRegion> (region_copy) == 0 &&
1091                     dynamic_cast<MidiTimeAxisView*> (tv.first) != 0) {
1092
1093                         /* MIDI -> non-MIDI */
1094                         return true;
1095                 }
1096
1097                 _drags->set (new RegionInsertDrag (this, region_copy, rtav, pos), &event);
1098         }
1099
1100         _drags->motion_handler (&event, false);
1101
1102         return true;
1103 }
1104
1105 bool
1106 Editor::key_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType)
1107 {
1108         return false;
1109 }
1110
1111 bool
1112 Editor::key_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType type)
1113 {
1114
1115         bool handled = false;
1116
1117         switch (type) {
1118         case TempoMarkerItem:
1119                 switch (event->key.keyval) {
1120                 case GDK_Delete:
1121                         remove_tempo_marker (item);
1122                         handled = true;
1123                         break;
1124                 default:
1125                         break;
1126                 }
1127                 break;
1128
1129         case MeterMarkerItem:
1130                 switch (event->key.keyval) {
1131                 case GDK_Delete:
1132                         remove_meter_marker (item);
1133                         handled = true;
1134                         break;
1135                 default:
1136                         break;
1137                 }
1138                 break;
1139
1140         default:
1141                 break;
1142         }
1143
1144         return handled;
1145 }