ardour
editor_canvas_events.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2000 Paul Davis
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #include <cstdlib>
21 #include <cmath>
22 #include <algorithm>
23 #include <typeinfo>
24 
25 #include "pbd/stacktrace.h"
26 
27 #include "ardour/audio_track.h"
28 #include "ardour/midi_track.h"
29 #include "ardour/midi_region.h"
30 #include "ardour/region_factory.h"
31 #include "ardour/profile.h"
32 
33 #include "canvas/canvas.h"
34 #include "canvas/text.h"
35 #include "canvas/scroll_group.h"
36 
37 #include "editor.h"
38 #include "keyboard.h"
39 #include "public_editor.h"
40 #include "ardour_ui.h"
41 #include "audio_region_view.h"
42 #include "audio_streamview.h"
43 #include "audio_time_axis.h"
44 #include "region_gain_line.h"
45 #include "automation_line.h"
46 #include "automation_time_axis.h"
47 #include "automation_line.h"
48 #include "control_point.h"
49 #include "editor_drag.h"
50 #include "midi_time_axis.h"
51 #include "editor_regions.h"
52 #include "verbose_cursor.h"
53 
54 #include "i18n.h"
55 
56 using namespace std;
57 using namespace ARDOUR;
58 using namespace PBD;
59 using namespace Gtk;
60 using namespace ArdourCanvas;
61 
63 
64 bool
65 Editor::track_canvas_scroll (GdkEventScroll* ev)
66 {
67  if (Keyboard::some_magic_widget_has_focus()) {
68  return false;
69  }
70 
71  framepos_t xdelta;
72  int direction = ev->direction;
73 
74  /* this event arrives without transformation by the canvas, so we have
75  * to transform the coordinates to be able to look things up.
76  */
77 
78  Duple event_coords = _track_canvas->window_to_canvas (Duple (ev->x, ev->y));
79 
80  retry:
81  switch (direction) {
82  case GDK_SCROLL_UP:
83  if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) {
84  //for mouse-wheel zoom, force zoom-focus to mouse
85  Editing::ZoomFocus temp_focus = zoom_focus;
86  zoom_focus = Editing::ZoomFocusMouse;
87  temporal_zoom_step (false);
88  zoom_focus = temp_focus;
89  return true;
90  } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) {
91  direction = GDK_SCROLL_LEFT;
92  goto retry;
93  } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) {
94  if (!current_stepping_trackview) {
95  step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
96  std::pair<TimeAxisView*, int> const p = trackview_by_y_position (event_coords.y, false);
97  current_stepping_trackview = p.first;
98  if (!current_stepping_trackview) {
99  return false;
100  }
101  }
102  last_track_height_step_timestamp = get_microseconds();
103  current_stepping_trackview->step_height (false);
104  return true;
105  } else {
106  scroll_up_one_track ();
107  return true;
108  }
109  break;
110 
111  case GDK_SCROLL_DOWN:
112  if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) {
113  //for mouse-wheel zoom, force zoom-focus to mouse
114  Editing::ZoomFocus temp_focus = zoom_focus;
115  zoom_focus = Editing::ZoomFocusMouse;
116  temporal_zoom_step (true);
117  zoom_focus = temp_focus;
118  return true;
119  } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) {
120  direction = GDK_SCROLL_RIGHT;
121  goto retry;
122  } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) {
123  if (!current_stepping_trackview) {
124  step_timeout = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Editor::track_height_step_timeout), 500);
125  std::pair<TimeAxisView*, int> const p = trackview_by_y_position (event_coords.y, false);
126  current_stepping_trackview = p.first;
127  if (!current_stepping_trackview) {
128  return false;
129  }
130  }
131  last_track_height_step_timestamp = get_microseconds();
132  current_stepping_trackview->step_height (true);
133  return true;
134  } else {
135  scroll_down_one_track ();
136  return true;
137  }
138  break;
139 
140  case GDK_SCROLL_LEFT:
141  xdelta = (current_page_samples() / 8);
142  if (leftmost_frame > xdelta) {
143  reset_x_origin (leftmost_frame - xdelta);
144  } else {
145  reset_x_origin (0);
146  }
147  break;
148 
149  case GDK_SCROLL_RIGHT:
150  xdelta = (current_page_samples() / 8);
151  if (max_framepos - xdelta > leftmost_frame) {
152  reset_x_origin (leftmost_frame + xdelta);
153  } else {
154  reset_x_origin (max_framepos - current_page_samples());
155  }
156  break;
157 
158  default:
159  /* what? */
160  break;
161  }
162 
163  return false;
164 }
165 
166 bool
167 Editor::canvas_scroll_event (GdkEventScroll *event, bool from_canvas)
168 {
169  if (from_canvas) {
170  boost::optional<ArdourCanvas::Rect> rulers = _time_markers_group->bounding_box();
171  if (rulers && rulers->contains (Duple (event->x, event->y))) {
172  return canvas_ruler_event ((GdkEvent*) event, timecode_ruler, TimecodeRulerItem);
173  }
174  }
175 
176  _track_canvas->grab_focus();
177  return track_canvas_scroll (event);
178 }
179 
180 bool
182 {
183  _track_canvas->grab_focus();
184  if (!Keyboard::is_context_menu_event (event)) {
185  begin_reversible_selection_op (X_("Clear Selection Click (track canvas)"));
186  selection->clear ();
187  commit_reversible_selection_op();
188  }
189  return false;
190 }
191 
192 bool
194 {
195  if (!Keyboard::is_context_menu_event (event)) {
196  if (_drags->active ()) {
197  _drags->end_grab ((GdkEvent*) event);
198  }
199  }
200  return false;
201 }
202 
203 bool
204 Editor::track_canvas_motion_notify_event (GdkEventMotion */*event*/)
205 {
206  int x, y;
207  /* keep those motion events coming */
208  _track_canvas->get_pointer (x, y);
209  return false;
210 }
211 
212 bool
213 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
214 {
215  gint ret = FALSE;
216 
217  switch (event->type) {
218  case GDK_BUTTON_PRESS:
219  case GDK_2BUTTON_PRESS:
220  case GDK_3BUTTON_PRESS:
221  ret = button_press_handler (item, event, type);
222  break;
223  case GDK_BUTTON_RELEASE:
224  ret = button_release_handler (item, event, type);
225  break;
226  case GDK_MOTION_NOTIFY:
227  ret = motion_handler (item, event);
228  break;
229 
230  case GDK_ENTER_NOTIFY:
231  ret = enter_handler (item, event, type);
232  break;
233 
234  case GDK_LEAVE_NOTIFY:
235  ret = leave_handler (item, event, type);
236  break;
237 
238  case GDK_KEY_PRESS:
239  ret = key_press_handler (item, event, type);
240  break;
241 
242  case GDK_KEY_RELEASE:
243  ret = key_release_handler (item, event, type);
244  break;
245 
246  default:
247  break;
248  }
249  return ret;
250 }
251 
252 bool
253 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
254 {
255  bool ret = false;
256 
257  if (!rv->sensitive ()) {
258  return false;
259  }
260 
261  switch (event->type) {
262  case GDK_BUTTON_PRESS:
263  case GDK_2BUTTON_PRESS:
264  case GDK_3BUTTON_PRESS:
265  clicked_regionview = rv;
266  clicked_control_point = 0;
267  clicked_axisview = &rv->get_time_axis_view();
268  clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
269  ret = button_press_handler (item, event, RegionItem);
270  break;
271 
272  case GDK_BUTTON_RELEASE:
273  ret = button_release_handler (item, event, RegionItem);
274  break;
275 
276  case GDK_MOTION_NOTIFY:
277  ret = motion_handler (item, event);
278  break;
279 
280  case GDK_ENTER_NOTIFY:
281  set_entered_regionview (rv);
282  ret = enter_handler (item, event, RegionItem);
283  break;
284 
285  case GDK_LEAVE_NOTIFY:
286  if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
287  set_entered_regionview (0);
288  ret = leave_handler (item, event, RegionItem);
289  }
290  break;
291 
292  default:
293  break;
294  }
295 
296  return ret;
297 }
298 
299 bool
300 Editor::canvas_wave_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
301 {
302  /* we only care about enter events here, required for mouse/cursor
303  * tracking. there is a non-linear (non-child/non-parent) relationship
304  * between various components of a regionview and so when we leave one
305  * of them (e.g. a trim handle) and enter another (e.g. the waveview)
306  * no other items get notified. enter/leave handling does not propagate
307  * in the same way as other events, so we need to catch this because
308  * entering (and leaving) the waveview is equivalent to
309  * entering/leaving the regionview (which is why it is passed in as a
310  * third argument).
311  *
312  * And in fact, we really only care about enter events.
313  */
314 
315  bool ret = false;
316 
317  if (!rv->sensitive ()) {
318  return false;
319  }
320 
321  switch (event->type) {
322  case GDK_ENTER_NOTIFY:
323  set_entered_regionview (rv);
324  ret = enter_handler (item, event, WaveItem);
325  break;
326 
327  default:
328  break;
329  }
330 
331  return ret;
332 }
333 
334 
335 bool
336 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
337 {
338  bool ret = FALSE;
339 
340  switch (event->type) {
341  case GDK_BUTTON_PRESS:
342  case GDK_2BUTTON_PRESS:
343  case GDK_3BUTTON_PRESS:
344  clicked_regionview = 0;
345  clicked_control_point = 0;
346  clicked_axisview = tv;
347  clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
348  ret = button_press_handler (item, event, StreamItem);
349  break;
350 
351  case GDK_BUTTON_RELEASE:
352  ret = button_release_handler (item, event, StreamItem);
353  break;
354 
355  case GDK_MOTION_NOTIFY:
356  ret = motion_handler (item, event);
357  break;
358 
359  case GDK_ENTER_NOTIFY:
360  set_entered_track (tv);
361  ret = enter_handler (item, event, StreamItem);
362  break;
363 
364  case GDK_LEAVE_NOTIFY:
365  if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
366  set_entered_track (0);
367  }
368  ret = leave_handler (item, event, StreamItem);
369  break;
370 
371  default:
372  break;
373  }
374 
375  return ret;
376 }
377 
378 bool
379 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
380 {
381  bool ret = false;
382 
383  switch (event->type) {
384  case GDK_BUTTON_PRESS:
385  case GDK_2BUTTON_PRESS:
386  case GDK_3BUTTON_PRESS:
387  clicked_regionview = 0;
388  clicked_control_point = 0;
389  clicked_axisview = atv;
390  clicked_routeview = 0;
391  ret = button_press_handler (item, event, AutomationTrackItem);
392  break;
393 
394  case GDK_BUTTON_RELEASE:
395  ret = button_release_handler (item, event, AutomationTrackItem);
396  break;
397 
398  case GDK_MOTION_NOTIFY:
399  ret = motion_handler (item, event);
400  break;
401 
402  case GDK_ENTER_NOTIFY:
403  ret = enter_handler (item, event, AutomationTrackItem);
404  break;
405 
406  case GDK_LEAVE_NOTIFY:
407  ret = leave_handler (item, event, AutomationTrackItem);
408  break;
409 
410  default:
411  break;
412  }
413 
414  return ret;
415 }
416 
417 bool
418 Editor::canvas_start_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
419 {
420  if (!rv->sensitive()) {
421  return false;
422  }
423 
424  switch (event->type) {
425  case GDK_BUTTON_PRESS:
426  clicked_regionview = rv;
427  clicked_control_point = 0;
428  clicked_axisview = &rv->get_time_axis_view();
429  clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
430  if (event->button.button == 3) {
431  return button_press_handler (item, event, StartCrossFadeItem);
432  }
433  break;
434 
435  case GDK_BUTTON_RELEASE:
436  if (event->button.button == 3) {
437  return button_release_handler (item, event, StartCrossFadeItem);
438  }
439  break;
440 
441  default:
442  break;
443 
444  }
445 
446  /* In Mixbus, the crossfade area is used to trim the region while leaving the fade anchor intact (see preserve_fade_anchor)*/
447  /* however in A3 this feature is unfinished, and it might be better to do it with a modifier-trim instead, anyway */
448  /* if we return RegionItem here then we avoid the issue until it is resolved later */
449  return typed_event (item, event, RegionItem); // StartCrossFadeItem);
450 }
451 
452 bool
453 Editor::canvas_end_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
454 {
455  if (!rv->sensitive()) {
456  return false;
457  }
458 
459  switch (event->type) {
460  case GDK_BUTTON_PRESS:
461  clicked_regionview = rv;
462  clicked_control_point = 0;
463  clicked_axisview = &rv->get_time_axis_view();
464  clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
465  if (event->button.button == 3) {
466  return button_press_handler (item, event, EndCrossFadeItem);
467  }
468  break;
469 
470  case GDK_BUTTON_RELEASE:
471  if (event->button.button == 3) {
472  return button_release_handler (item, event, EndCrossFadeItem);
473  }
474  break;
475 
476  default:
477  break;
478 
479  }
480 
481  /* In Mixbus, the crossfade area is used to trim the region while leaving the fade anchor intact (see preserve_fade_anchor)*/
482  /* however in A3 this feature is unfinished, and it might be better to do it with a modifier-trim instead, anyway */
483  /* if we return RegionItem here then we avoid the issue until it is resolved later */
484  return typed_event (item, event, RegionItem); // EndCrossFadeItem);
485 }
486 
487 bool
488 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
489 {
490  /* we handle only button 3 press/release events */
491 
492  if (!rv->sensitive()) {
493  return false;
494  }
495 
496  switch (event->type) {
497  case GDK_BUTTON_PRESS:
498  clicked_regionview = rv;
499  clicked_control_point = 0;
500  clicked_axisview = &rv->get_time_axis_view();
501  clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
502  if (event->button.button == 3) {
503  return button_press_handler (item, event, FadeInItem);
504  }
505  break;
506 
507  case GDK_BUTTON_RELEASE:
508  if (event->button.button == 3) {
509  return button_release_handler (item, event, FadeInItem);
510  }
511  break;
512 
513  default:
514  break;
515 
516  }
517 
518  /* proxy for the regionview, except enter/leave events */
519 
520  if (event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) {
521  return true;
522  } else {
523  return canvas_region_view_event (event, rv->get_canvas_group(), rv);
524  }
525 }
526 
527 bool
528 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv, bool trim)
529 {
530  bool ret = false;
531 
532  if (!rv->sensitive()) {
533  return false;
534  }
535 
536  switch (event->type) {
537  case GDK_BUTTON_PRESS:
538  case GDK_2BUTTON_PRESS:
539  case GDK_3BUTTON_PRESS:
540  clicked_regionview = rv;
541  clicked_control_point = 0;
542  clicked_axisview = &rv->get_time_axis_view();
543  clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
544  ret = button_press_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
545  break;
546 
547  case GDK_BUTTON_RELEASE:
548  ret = button_release_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
549  maybe_locate_with_edit_preroll ( rv->region()->position() );
550  break;
551 
552  case GDK_MOTION_NOTIFY:
553  ret = motion_handler (item, event);
554  break;
555 
556  case GDK_ENTER_NOTIFY:
557  ret = enter_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
558  break;
559 
560  case GDK_LEAVE_NOTIFY:
561  ret = leave_handler (item, event, trim ? FadeInTrimHandleItem : FadeInHandleItem);
562  break;
563 
564  default:
565  break;
566  }
567 
568  return ret;
569 }
570 
571 bool
572 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
573 {
574  /* we handle only button 3 press/release events */
575 
576  if (!rv->sensitive()) {
577  return false;
578  }
579 
580  switch (event->type) {
581  case GDK_BUTTON_PRESS:
582  clicked_regionview = rv;
583  clicked_control_point = 0;
584  clicked_axisview = &rv->get_time_axis_view();
585  clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
586  if (event->button.button == 3) {
587  return button_press_handler (item, event, FadeOutItem);
588  }
589  break;
590 
591  case GDK_BUTTON_RELEASE:
592  if (event->button.button == 3) {
593  return button_release_handler (item, event, FadeOutItem);
594  }
595  break;
596 
597  default:
598  break;
599 
600  }
601 
602  /* proxy for the regionview, except enter/leave events */
603 
604  if (event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) {
605  return true;
606  } else {
607  return canvas_region_view_event (event, rv->get_canvas_group(), rv);
608  }
609 }
610 
611 bool
612 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv, bool trim)
613 {
614  bool ret = false;
615 
616  if (!rv->sensitive()) {
617  return false;
618  }
619 
620  switch (event->type) {
621  case GDK_BUTTON_PRESS:
622  case GDK_2BUTTON_PRESS:
623  case GDK_3BUTTON_PRESS:
624  clicked_regionview = rv;
625  clicked_control_point = 0;
626  clicked_axisview = &rv->get_time_axis_view();
627  clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
628  ret = button_press_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
629  break;
630 
631  case GDK_BUTTON_RELEASE:
632  ret = button_release_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
633  maybe_locate_with_edit_preroll ( rv->region()->last_frame() - rv->get_fade_out_shape_width() );
634  break;
635 
636  case GDK_MOTION_NOTIFY:
637  ret = motion_handler (item, event);
638  break;
639 
640  case GDK_ENTER_NOTIFY:
641  ret = enter_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
642  break;
643 
644  case GDK_LEAVE_NOTIFY:
645  ret = leave_handler (item, event, trim ? FadeOutTrimHandleItem : FadeOutHandleItem);
646  break;
647 
648  default:
649  break;
650  }
651 
652  return ret;
653 }
654 
657  return a->layer() > b->layer();
658  }
659 };
660 
661 bool
662 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
663 {
664  switch (event->type) {
665  case GDK_BUTTON_PRESS:
666  case GDK_2BUTTON_PRESS:
667  case GDK_3BUTTON_PRESS:
668  clicked_control_point = cp;
669  clicked_axisview = &cp->line().trackview;
670  clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
671  clicked_regionview = 0;
672  break;
673 
674  case GDK_SCROLL_UP:
675  break;
676 
677  case GDK_SCROLL_DOWN:
678  break;
679 
680  default:
681  break;
682  }
683 
684  return typed_event (item, event, ControlPointItem);
685 }
686 
687 bool
688 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
689 {
690  ItemType type;
691 
692  if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
693  type = GainLineItem;
694  } else {
695  type = AutomationLineItem;
696  }
697 
698  return typed_event (item, event, type);
699 }
700 
701 bool
702 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
703 {
704  bool ret = false;
705 
706  switch (event->type) {
707  case GDK_BUTTON_PRESS:
708  case GDK_2BUTTON_PRESS:
709  case GDK_3BUTTON_PRESS:
710  clicked_selection = rect->id;
711  ret = button_press_handler (item, event, SelectionItem);
712  break;
713  case GDK_BUTTON_RELEASE:
714  ret = button_release_handler (item, event, SelectionItem);
715  break;
716  case GDK_MOTION_NOTIFY:
717  ret = motion_handler (item, event);
718  break;
719  /* Don't need these at the moment. */
720  case GDK_ENTER_NOTIFY:
721  ret = enter_handler (item, event, SelectionItem);
722  break;
723 
724  case GDK_LEAVE_NOTIFY:
725  ret = leave_handler (item, event, SelectionItem);
726  break;
727 
728  default:
729  break;
730  }
731 
732  return ret;
733 }
734 
735 bool
736 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
737 {
738  bool ret = false;
739 
740  switch (event->type) {
741  case GDK_BUTTON_PRESS:
742  case GDK_2BUTTON_PRESS:
743  case GDK_3BUTTON_PRESS:
744  clicked_selection = rect->id;
745  ret = button_press_handler (item, event, StartSelectionTrimItem);
746  break;
747  case GDK_BUTTON_RELEASE:
748  ret = button_release_handler (item, event, StartSelectionTrimItem);
749  break;
750  case GDK_MOTION_NOTIFY:
751  ret = motion_handler (item, event);
752  break;
753  case GDK_ENTER_NOTIFY:
754  ret = enter_handler (item, event, StartSelectionTrimItem);
755  break;
756 
757  case GDK_LEAVE_NOTIFY:
758  ret = leave_handler (item, event, StartSelectionTrimItem);
759  break;
760 
761  default:
762  break;
763  }
764 
765  return ret;
766 }
767 
768 bool
769 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
770 {
771  bool ret = false;
772 
773  switch (event->type) {
774  case GDK_BUTTON_PRESS:
775  case GDK_2BUTTON_PRESS:
776  case GDK_3BUTTON_PRESS:
777  clicked_selection = rect->id;
778  ret = button_press_handler (item, event, EndSelectionTrimItem);
779  break;
780  case GDK_BUTTON_RELEASE:
781  ret = button_release_handler (item, event, EndSelectionTrimItem);
782  break;
783  case GDK_MOTION_NOTIFY:
784  ret = motion_handler (item, event);
785  break;
786  case GDK_ENTER_NOTIFY:
787  ret = enter_handler (item, event, EndSelectionTrimItem);
788  break;
789 
790  case GDK_LEAVE_NOTIFY:
791  ret = leave_handler (item, event, EndSelectionTrimItem);
792  break;
793 
794  default:
795  break;
796  }
797 
798  return ret;
799 }
800 
801 bool
802 Editor::canvas_frame_handle_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
803 {
804  bool ret = false;
805 
806  /* frame handles are not active when in internal edit mode, because actual notes
807  might be in the area occupied by the handle - we want them to be editable as normal.
808  */
809 
810  if (internal_editing() || !rv->sensitive()) {
811  return false;
812  }
813 
814  /* NOTE: frame handles pretend to be the colored trim bar from an event handling
815  perspective. XXX change this ??
816  */
817 
818  ItemType type;
819 
820  if (item->get_data ("isleft")) {
821  type = LeftFrameHandle;
822  } else {
823  type = RightFrameHandle;
824  }
825 
826  switch (event->type) {
827  case GDK_BUTTON_PRESS:
828  case GDK_2BUTTON_PRESS:
829  case GDK_3BUTTON_PRESS:
830  clicked_regionview = rv;
831  clicked_control_point = 0;
832  clicked_axisview = &clicked_regionview->get_time_axis_view();
833  clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
834  ret = button_press_handler (item, event, type);
835  break;
836  case GDK_BUTTON_RELEASE:
837  ret = button_release_handler (item, event, type);
838  break;
839  case GDK_MOTION_NOTIFY:
840  ret = motion_handler (item, event);
841  break;
842  case GDK_ENTER_NOTIFY:
843  ret = enter_handler (item, event, type);
844  break;
845 
846  case GDK_LEAVE_NOTIFY:
847  ret = leave_handler (item, event, type);
848  break;
849 
850  default:
851  break;
852  }
853 
854  return ret;
855 }
856 
857 
858 bool
859 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
860 {
861  bool ret = false;
862 
863  if (!rv->sensitive()) {
864  return false;
865  }
866 
867  switch (event->type) {
868  case GDK_BUTTON_PRESS:
869  case GDK_2BUTTON_PRESS:
870  case GDK_3BUTTON_PRESS:
871  clicked_regionview = rv;
872  clicked_control_point = 0;
873  clicked_axisview = &clicked_regionview->get_time_axis_view();
874  clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
875  ret = button_press_handler (item, event, RegionViewNameHighlight);
876  break;
877  case GDK_BUTTON_RELEASE:
878  ret = button_release_handler (item, event, RegionViewNameHighlight);
879  break;
880  case GDK_MOTION_NOTIFY:
881  motion_handler (item, event);
882  ret = true; // force this to avoid progagating the event into the regionview
883  break;
884  case GDK_ENTER_NOTIFY:
885  ret = enter_handler (item, event, RegionViewNameHighlight);
886  break;
887 
888  case GDK_LEAVE_NOTIFY:
889  ret = leave_handler (item, event, RegionViewNameHighlight);
890  break;
891 
892  default:
893  break;
894  }
895 
896  return ret;
897 }
898 
899 bool
900 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
901 {
902  bool ret = false;
903 
904  if (!rv->sensitive()) {
905  return false;
906  }
907 
908  switch (event->type) {
909  case GDK_BUTTON_PRESS:
910  case GDK_2BUTTON_PRESS:
911  case GDK_3BUTTON_PRESS:
912  clicked_regionview = rv;
913  clicked_control_point = 0;
914  clicked_axisview = &clicked_regionview->get_time_axis_view();
915  clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
916  ret = button_press_handler (item, event, RegionViewName);
917  break;
918  case GDK_BUTTON_RELEASE:
919  ret = button_release_handler (item, event, RegionViewName);
920  break;
921  case GDK_MOTION_NOTIFY:
922  ret = motion_handler (item, event);
923  break;
924  case GDK_ENTER_NOTIFY:
925  ret = enter_handler (item, event, RegionViewName);
926  break;
927 
928  case GDK_LEAVE_NOTIFY:
929  ret = leave_handler (item, event, RegionViewName);
930  break;
931 
932  default:
933  break;
934  }
935 
936  return ret;
937 }
938 
939 bool
940 Editor::canvas_feature_line_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView*)
941 {
942  bool ret = false;
943 
944  switch (event->type) {
945  case GDK_BUTTON_PRESS:
946  case GDK_2BUTTON_PRESS:
947  case GDK_3BUTTON_PRESS:
948  clicked_regionview = 0;
949  clicked_control_point = 0;
950  clicked_axisview = 0;
951  clicked_routeview = 0; //dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
952  ret = button_press_handler (item, event, FeatureLineItem);
953  break;
954 
955  case GDK_BUTTON_RELEASE:
956  ret = button_release_handler (item, event, FeatureLineItem);
957  break;
958 
959  case GDK_MOTION_NOTIFY:
960  ret = motion_handler (item, event);
961  break;
962 
963  case GDK_ENTER_NOTIFY:
964  ret = enter_handler (item, event, FeatureLineItem);
965  break;
966 
967  case GDK_LEAVE_NOTIFY:
968  ret = leave_handler (item, event, FeatureLineItem);
969  break;
970 
971  default:
972  break;
973  }
974 
975  return ret;
976 }
977 
978 bool
979 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* /*marker*/)
980 {
981  return typed_event (item, event, MarkerItem);
982 }
983 
984 bool
985 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
986 {
987  return typed_event (item, event, MarkerBarItem);
988 }
989 
990 bool
991 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
992 {
993  return typed_event (item, event, RangeMarkerBarItem);
994 }
995 
996 bool
997 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
998 {
999  return typed_event (item, event, TransportMarkerBarItem);
1000 }
1001 
1002 bool
1003 Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1004 {
1005  return typed_event (item, event, CdMarkerBarItem);
1006 }
1007 
1008 bool
1009 Editor::canvas_videotl_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1010 {
1011  return typed_event (item, event, VideoBarItem);
1012 }
1013 
1014 bool
1015 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* /*marker*/)
1016 {
1017  return typed_event (item, event, TempoMarkerItem);
1018 }
1019 
1020 bool
1021 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* /*marker*/)
1022 {
1023  return typed_event (item, event, MeterMarkerItem);
1024 }
1025 
1026 bool
1027 Editor::canvas_ruler_event (GdkEvent *event, ArdourCanvas::Item* item, ItemType type)
1028 {
1029  framepos_t xdelta;
1030  bool handled = false;
1031 
1032  if (event->type == GDK_SCROLL) {
1033 
1034  /* scroll events in the rulers are handled a little differently from
1035  scrolling elsewhere in the canvas.
1036  */
1037 
1038  switch (event->scroll.direction) {
1039  case GDK_SCROLL_UP:
1040 
1041  if (Profile->get_mixbus()) {
1042  //for mouse-wheel zoom, force zoom-focus to mouse
1043  Editing::ZoomFocus temp_focus = zoom_focus;
1044  zoom_focus = Editing::ZoomFocusMouse;
1045  temporal_zoom_step (false);
1046  zoom_focus = temp_focus;
1047  } else {
1048  temporal_zoom_step (false);
1049  }
1050  handled = true;
1051  break;
1052 
1053  case GDK_SCROLL_DOWN:
1054  if (Profile->get_mixbus()) {
1055  //for mouse-wheel zoom, force zoom-focus to mouse
1056  Editing::ZoomFocus temp_focus = zoom_focus;
1057  zoom_focus = Editing::ZoomFocusMouse;
1058  temporal_zoom_step (true);
1059  zoom_focus = temp_focus;
1060  } else {
1061  temporal_zoom_step (true);
1062  }
1063  handled = true;
1064  break;
1065 
1066  case GDK_SCROLL_LEFT:
1067  xdelta = (current_page_samples() / 2);
1068  if (leftmost_frame > xdelta) {
1069  reset_x_origin (leftmost_frame - xdelta);
1070  } else {
1071  reset_x_origin (0);
1072  }
1073  handled = true;
1074  break;
1075 
1076  case GDK_SCROLL_RIGHT:
1077  xdelta = (current_page_samples() / 2);
1078  if (max_framepos - xdelta > leftmost_frame) {
1079  reset_x_origin (leftmost_frame + xdelta);
1080  } else {
1081  reset_x_origin (max_framepos - current_page_samples());
1082  }
1083  handled = true;
1084  break;
1085 
1086  default:
1087  /* what? */
1088  break;
1089  }
1090  return handled;
1091  }
1092 
1093  return typed_event (item, event, type);
1094 }
1095 
1096 bool
1097 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1098 {
1099  return typed_event (item, event, TempoBarItem);
1100 }
1101 
1102 bool
1103 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
1104 {
1105  return typed_event (item, event, MeterBarItem);
1106 }
1107 
1108 bool
1109 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
1110 {
1111  return typed_event (item, event, PlayheadCursorItem);
1112 }
1113 
1114 bool
1115 Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
1116 {
1117  if (!internal_editing()) {
1118  return false;
1119  }
1120 
1121  return typed_event (item, event, NoteItem);
1122 }
1123 
1124 bool
1126 {
1127  GdkEventScroll scroll;
1128  ArdourCanvas::Duple winpos;
1129 
1130  switch (event->type) {
1131  case GDK_BUTTON_RELEASE:
1132  if (event->button.button == 1) {
1133  begin_reversible_selection_op (X_("Nowhere Click"));
1134  selection->clear_objects ();
1135  selection->clear_tracks ();
1136  commit_reversible_selection_op ();
1137  }
1138  break;
1139 
1140  case GDK_SCROLL:
1141  /* convert coordinates back into window space so that
1142  we can just call canvas_scroll_event().
1143  */
1144  winpos = _track_canvas->canvas_to_window (Duple (event->scroll.x, event->scroll.y));
1145  scroll = event->scroll;
1146  scroll.x = winpos.x;
1147  scroll.y = winpos.y;
1148  return canvas_scroll_event (&scroll, true);
1149  break;
1150 
1151  case GDK_ENTER_NOTIFY:
1152  return typed_event (_canvas_drop_zone, event, DropZoneItem);
1153 
1154  case GDK_LEAVE_NOTIFY:
1155  return typed_event (_canvas_drop_zone, event, DropZoneItem);
1156 
1157  default:
1158  break;
1159  }
1160 
1161  return true;
1162 }
1163 
1164 bool
1165 Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const& context, int x, int y, guint time)
1166 {
1169  RouteTimeAxisView* rtav;
1170  GdkEvent event;
1171  double px;
1172  double py;
1173 
1174  string target = _track_canvas->drag_dest_find_target (context, _track_canvas->drag_dest_get_target_list());
1175 
1176  if (target.empty()) {
1177  return false;
1178  }
1179 
1180  event.type = GDK_MOTION_NOTIFY;
1181  event.button.x = x;
1182  event.button.y = y;
1183  /* assume we're dragging with button 1 */
1184  event.motion.state = Gdk::BUTTON1_MASK;
1185 
1186  (void) window_event_sample (&event, &px, &py);
1187 
1188  std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py, false);
1189  bool can_drop = false;
1190 
1191  if (tv.first != 0) {
1192 
1193  /* over a time axis view of some kind */
1194 
1195  rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1196 
1197  if (rtav != 0 && rtav->is_track ()) {
1198  /* over a track, not a bus */
1199  can_drop = true;
1200  }
1201 
1202 
1203  } else {
1204  /* not over a time axis view, so drop is possible */
1205  can_drop = true;
1206  }
1207 
1208  if (can_drop) {
1209  region = _regions->get_dragged_region ();
1210 
1211  if (region) {
1212 
1213  if (tv.first == 0
1214  && (
1215  boost::dynamic_pointer_cast<AudioRegion> (region) != 0 ||
1216  boost::dynamic_pointer_cast<MidiRegion> (region) != 0
1217  )
1218  )
1219  {
1220  /* drop to drop-zone */
1221  context->drag_status (context->get_suggested_action(), time);
1222  return true;
1223  }
1224 
1225  if ((boost::dynamic_pointer_cast<AudioRegion> (region) != 0 &&
1226  dynamic_cast<AudioTimeAxisView*> (tv.first) != 0) ||
1227  (boost::dynamic_pointer_cast<MidiRegion> (region) != 0 &&
1228  dynamic_cast<MidiTimeAxisView*> (tv.first) != 0)) {
1229 
1230  /* audio to audio
1231  OR
1232  midi to midi
1233  */
1234 
1235  context->drag_status (context->get_suggested_action(), time);
1236  return true;
1237  }
1238  } else {
1239  /* DND originating from outside ardour
1240  *
1241  * TODO: check if file is audio/midi, allow drops on same track-type only,
1242  * currently: if audio is dropped on a midi-track, it is only added to the region-list
1243  */
1244  if (Profile->get_sae() || ARDOUR_UI::config()->get_only_copy_imported_files()) {
1245  context->drag_status(Gdk::ACTION_COPY, time);
1246  } else {
1247  if ((context->get_actions() & (Gdk::ACTION_COPY | Gdk::ACTION_LINK | Gdk::ACTION_MOVE)) == Gdk::ACTION_COPY) {
1248  context->drag_status(Gdk::ACTION_COPY, time);
1249  } else {
1250  context->drag_status(Gdk::ACTION_LINK, time);
1251  }
1252  }
1253  return true;
1254  }
1255  }
1256 
1257  /* no drop here */
1258  context->drag_status (Gdk::DragAction (0), time);
1259  return false;
1260 }
1261 
1262 void
1263 Editor::drop_regions (const Glib::RefPtr<Gdk::DragContext>& /*context*/,
1264  int x, int y,
1265  const SelectionData& /*data*/,
1266  guint /*info*/, guint /*time*/)
1267 {
1268  GdkEvent event;
1269  double px;
1270  double py;
1271 
1272  event.type = GDK_MOTION_NOTIFY;
1273  event.button.x = x;
1274  event.button.y = y;
1275  /* assume we're dragging with button 1 */
1276  event.motion.state = Gdk::BUTTON1_MASK;
1277  framepos_t const pos = window_event_sample (&event, &px, &py);
1278 
1279  boost::shared_ptr<Region> region = _regions->get_dragged_region ();
1280  if (!region) { return; }
1281 
1282  RouteTimeAxisView* rtav = 0;
1283  std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py, false);
1284 
1285  if (tv.first != 0) {
1286  rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
1287  } else {
1288  try {
1289  if (boost::dynamic_pointer_cast<AudioRegion> (region)) {
1290  uint32_t output_chan = region->n_channels();
1291  if ((Config->get_output_auto_connect() & AutoConnectMaster) && session()->master_out()) {
1292  output_chan = session()->master_out()->n_inputs().n_audio();
1293  }
1294  list<boost::shared_ptr<AudioTrack> > audio_tracks;
1295  audio_tracks = session()->new_audio_track (region->n_channels(), output_chan, ARDOUR::Normal, 0, 1, region->name());
1296  rtav = axis_view_from_route (audio_tracks.front());
1297  } else if (boost::dynamic_pointer_cast<MidiRegion> (region)) {
1298  ChanCount one_midi_port (DataType::MIDI, 1);
1299  list<boost::shared_ptr<MidiTrack> > midi_tracks;
1300  midi_tracks = session()->new_midi_track (one_midi_port, one_midi_port, boost::shared_ptr<ARDOUR::PluginInfo>(), ARDOUR::Normal, 0, 1, region->name());
1301  rtav = axis_view_from_route (midi_tracks.front());
1302  } else {
1303  return;
1304  }
1305  } catch (...) {
1306  error << _("Could not create new track after region placed in the drop zone") << endmsg;
1307  return;
1308  }
1309  }
1310 
1311  if (rtav != 0 && rtav->is_track ()) {
1312  boost::shared_ptr<Region> region_copy = RegionFactory::create (region, true);
1313 
1314  if ((boost::dynamic_pointer_cast<AudioRegion> (region_copy) != 0 && dynamic_cast<AudioTimeAxisView*> (rtav) != 0) ||
1315  (boost::dynamic_pointer_cast<MidiRegion> (region_copy) != 0 && dynamic_cast<MidiTimeAxisView*> (rtav) != 0)) {
1316  _drags->set (new RegionInsertDrag (this, region_copy, rtav, pos), &event);
1317  _drags->end_grab (0);
1318  }
1319  }
1320 }
1321 
1322 bool
1323 Editor::key_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType)
1324 {
1325  return false;
1326 }
1327 
1328 bool
1329 Editor::key_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType type)
1330 {
1331 
1332  bool handled = false;
1333 
1334  switch (type) {
1335  case TempoMarkerItem:
1336  switch (event->key.keyval) {
1337  case GDK_Delete:
1338  remove_tempo_marker (item);
1339  handled = true;
1340  break;
1341  default:
1342  break;
1343  }
1344  break;
1345 
1346  case MeterMarkerItem:
1347  switch (event->key.keyval) {
1348  case GDK_Delete:
1349  remove_meter_marker (item);
1350  handled = true;
1351  break;
1352  default:
1353  break;
1354  }
1355  break;
1356 
1357  default:
1358  break;
1359  }
1360 
1361  return handled;
1362 }
1363 
bool canvas_fade_in_handle_event(GdkEvent *event, ArdourCanvas::Item *, AudioRegionView *, bool trim=false)
bool get_mixbus() const
Definition: profile.h:53
ArdourCanvas::Item * get_canvas_group()
bool operator()(boost::shared_ptr< Region > a, boost::shared_ptr< Region > b)
bool typed_event(ArdourCanvas::Item *, GdkEvent *, ItemType)
TimeAxisView & get_time_axis_view() const
bool get_sae() const
Definition: profile.h:48
bool canvas_control_point_event(GdkEvent *event, ArdourCanvas::Item *, ControlPoint *)
bool canvas_ruler_event(GdkEvent *event, ArdourCanvas::Item *, ItemType)
ItemType
Definition: editor_items.h:23
bool canvas_scroll_event(GdkEventScroll *event, bool from_canvas)
bool canvas_wave_view_event(GdkEvent *event, ArdourCanvas::Item *, RegionView *)
bool track_canvas_motion_notify_event(GdkEventMotion *event)
gint track_height_step_timeout()
bool canvas_stream_view_event(GdkEvent *event, ArdourCanvas::Item *, RouteTimeAxisView *)
bool canvas_cd_marker_bar_event(GdkEvent *event, ArdourCanvas::Item *)
bool canvas_fade_in_event(GdkEvent *event, ArdourCanvas::Item *, AudioRegionView *)
Definition: ardour_ui.h:130
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
AutomationLine & line() const
Definition: control_point.h:81
bool canvas_selection_end_trim_event(GdkEvent *event, ArdourCanvas::Item *, SelectionRect *)
Definition: marker.h:41
Definition: Beats.hpp:239
LIBPBD_API Transmitter error
bool canvas_range_marker_bar_event(GdkEvent *event, ArdourCanvas::Item *)
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
ZoomFocus
Definition: editing.h:119
bool canvas_drop_zone_event(GdkEvent *event)
bool track_canvas_drag_motion(Glib::RefPtr< Gdk::DragContext > const &, int, int, guint)
bool canvas_region_view_name_event(GdkEvent *event, ArdourCanvas::Item *, RegionView *)
bool track_canvas_button_release_event(GdkEventButton *event)
bool canvas_line_event(GdkEvent *event, ArdourCanvas::Item *, AutomationLine *)
bool canvas_meter_bar_event(GdkEvent *event, ArdourCanvas::Item *)
bool canvas_marker_bar_event(GdkEvent *event, ArdourCanvas::Item *)
bool canvas_videotl_bar_event(GdkEvent *event, ArdourCanvas::Item *)
LIBARDOUR_API microseconds_t get_microseconds()
Definition: globals.cc:728
#define _(Text)
Definition: i18n.h:11
bool canvas_region_view_event(GdkEvent *event, ArdourCanvas::Item *, RegionView *)
LIBGTKMM2EXT_API uint64_t Keyboard
Definition: debug.cc:23
bool key_release_handler(ArdourCanvas::Item *, GdkEvent *, ItemType)
#define X_(Text)
Definition: i18n.h:13
bool canvas_start_xfade_event(GdkEvent *event, ArdourCanvas::Item *, AudioRegionView *)
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
framepos_t get_fade_out_shape_width()
boost::shared_ptr< ARDOUR::Region > region() const
Definition: region_view.h:66
bool track_canvas_button_press_event(GdkEventButton *event)
Definition: amp.h:29
bool canvas_tempo_bar_event(GdkEvent *event, ArdourCanvas::Item *)
bool sensitive() const
TimeAxisView & trackview
bool canvas_selection_start_trim_event(GdkEvent *event, ArdourCanvas::Item *, SelectionRect *)
int64_t framepos_t
Definition: types.h:66
bool canvas_region_view_name_highlight_event(GdkEvent *event, ArdourCanvas::Item *, RegionView *)
bool canvas_end_xfade_event(GdkEvent *event, ArdourCanvas::Item *, AudioRegionView *)
layer_t layer() const
Definition: region.h:115
bool canvas_meter_marker_event(GdkEvent *event, ArdourCanvas::Item *, MeterMarker *)
LIBARDOUR_API RuntimeProfile * Profile
Definition: globals.cc:120
bool is_track() const
Definition: route_ui.cc:1732
bool canvas_automation_track_event(GdkEvent *event, ArdourCanvas::Item *, AutomationTimeAxisView *)
void drop_regions(const Glib::RefPtr< Gdk::DragContext > &context, gint x, gint y, const Gtk::SelectionData &data, guint info, guint time)
framepos_t position() const
Definition: region.h:112
bool canvas_transport_marker_bar_event(GdkEvent *event, ArdourCanvas::Item *)
bool key_press_handler(ArdourCanvas::Item *, GdkEvent *, ItemType)
bool canvas_note_event(GdkEvent *event, ArdourCanvas::Item *)
bool canvas_playhead_cursor_event(GdkEvent *event, ArdourCanvas::Item *)
uint32_t n_channels() const
Definition: region.h:259
bool canvas_selection_rect_event(GdkEvent *event, ArdourCanvas::Item *, SelectionRect *)
std::string name() const
static UIConfiguration * config()
Definition: ardour_ui.h:188
uint32_t id
Definition: enums.h:44
Definition: debug.h:30
bool canvas_marker_event(GdkEvent *event, ArdourCanvas::Item *, Marker *)
bool canvas_feature_line_event(GdkEvent *event, ArdourCanvas::Item *, RegionView *)
bool canvas_fade_out_event(GdkEvent *event, ArdourCanvas::Item *, AudioRegionView *)
static const framepos_t max_framepos
Definition: types.h:78
bool track_canvas_scroll(GdkEventScroll *event)
LIBARDOUR_API GQuark region_copy
Definition: operations.cc:35
bool canvas_frame_handle_event(GdkEvent *event, ArdourCanvas::Item *, RegionView *)
framepos_t last_frame() const
Definition: region.h:142
bool canvas_tempo_marker_event(GdkEvent *event, ArdourCanvas::Item *, TempoMarker *)
bool canvas_fade_out_handle_event(GdkEvent *event, ArdourCanvas::Item *, AudioRegionView *, bool trim=false)