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