1 /*
2  * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
3  * Copyright (C) 2009-2015 David Robillard <d@drobilla.net>
4  * Copyright (C) 2009-2017 Paul Davis <paul@linuxaudiosystems.com>
5  * Copyright (C) 2013-2014 Colin Fletcher <colin.m.fletcher@googlemail.com>
6  * Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org>
7  * Copyright (C) 2015-2017 Nick Mainsbridge <mainsbridge@gmail.com>
8  * Copyright (C) 2015-2018 Ben Loftis <ben@harrisonconsoles.com>
9  * Copyright (C) 2016 Tim Mayberry <mojofunk@gmail.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25 
26 #ifndef __gtk2_ardour_editor_drag_h_
27 #define __gtk2_ardour_editor_drag_h_
28 
29 #include <list>
30 
31 #include <gdk/gdk.h>
32 #include <stdint.h>
33 
34 #include "ardour/tempo.h"
35 #include "ardour/types.h"
36 
37 #include "canvas/types.h"
38 
39 #include "cursor_context.h"
40 #include "editor_items.h"
41 #include "mouse_cursors.h"
42 #include "editing.h"
43 #include "track_selection.h"
44 
45 namespace ARDOUR {
46 	class Location;
47 	class Region;
48 	class TempoSection;
49 }
50 
51 namespace ArdourCanvas {
52 	class Item;
53 	class Line;
54 	class Rectangle;
55 }
56 
57 namespace PBD {
58 	class StatefulDiffCommand;
59 }
60 
61 class PatchChange;
62 class Editor;
63 class EditorCursor;
64 class TimeAxisView;
65 class MidiTimeAxisView;
66 class Drag;
67 class NoteBase;
68 class RegionView;
69 class TimeAxisView;
70 class RouteTimeAxisView;
71 class RegionSelection;
72 class MidiRegionView;
73 class MeterMarker;
74 class ArdourMarker;
75 class TempoMarker;
76 class ControlPoint;
77 class AudioRegionView;
78 class AutomationLine;
79 class AutomationTimeAxisView;
80 
81 /** Class to manage current drags */
82 class DragManager
83 {
84 public:
85 
86 	DragManager (Editor* e);
87 	~DragManager ();
88 
89 	bool motion_handler (GdkEvent *, bool);
90 
91 	void abort ();
92 	void add (Drag *);
93 	void set (Drag *, GdkEvent *, Gdk::Cursor* c = MouseCursors::invalid_cursor());
94 	void start_grab (GdkEvent *, Gdk::Cursor* c = MouseCursors::invalid_cursor());
95 	bool end_grab (GdkEvent *);
96 	bool have_item (ArdourCanvas::Item *) const;
97 
98 	void mark_double_click ();
99 
100 	/** @return true if an end drag or abort is in progress */
ending()101 	bool ending () const {
102 		return _ending;
103 	}
104 
active()105 	bool active () const {
106 		return !_drags.empty ();
107 	}
108 
109 	/** @return current pointer x position in canvas coordinates */
current_pointer_x()110 	double current_pointer_x () const {
111 		return _current_pointer_x;
112 	}
113 
114 	/** @return current pointer y position in canvas coordinates */
current_pointer_y()115 	double current_pointer_y () const {
116 		return _current_pointer_y;
117 	}
118 
119 	/** @return current pointer sample */
current_pointer_sample()120 	ARDOUR::samplepos_t current_pointer_sample () const {
121 		return _current_pointer_sample;
122 	}
123 
124 	/** return drag-motion displays video-frame of drag-location */
125 	bool preview_video () const;
126 
127 private:
128 	Editor* _editor;
129 	std::list<Drag*> _drags;
130 	bool _ending; ///< true if end_grab or abort is in progress, otherwise false
131 	double _current_pointer_x; ///< canvas-coordinate space x of the current pointer
132 	double _current_pointer_y; ///< canvas-coordinate space y of the current pointer
133 	ARDOUR::samplepos_t _current_pointer_sample; ///< sample that the pointer is now at
134 	bool _old_follow_playhead; ///< state of Editor::follow_playhead() before the drags started
135 };
136 
137 /** Abstract base class for dragging of things within the editor */
138 class Drag
139 {
140 public:
141 	Drag (Editor *, ArdourCanvas::Item *, bool trackview_only = true);
~Drag()142 	virtual ~Drag () {}
143 
set_manager(DragManager * m)144 	void set_manager (DragManager* m) {
145 		_drags = m;
146 	}
147 
148 	/** @return the canvas item being dragged */
item()149 	ArdourCanvas::Item* item () const {
150 		return _item;
151 	}
152 
153 	void swap_grab (ArdourCanvas::Item *, Gdk::Cursor *, uint32_t);
154 	bool motion_handler (GdkEvent*, bool);
155 	void abort ();
156 
157 	ARDOUR::MusicSample adjusted_sample (ARDOUR::samplepos_t, GdkEvent const *, bool snap = true) const;
158 	ARDOUR::samplepos_t adjusted_current_sample (GdkEvent const *, bool snap = true) const;
159 
was_double_click()160 	bool was_double_click() const { return _was_double_click; }
set_double_click(bool yn)161 	void set_double_click (bool yn) { _was_double_click = yn; }
162 
163 	/** Called to start a grab of an item.
164 	 *  @param e Event that caused the grab to start.
165 	 *  @param c Cursor to use, or 0.
166 	 */
167 	virtual void start_grab (GdkEvent* e, Gdk::Cursor* c = 0);
168 
169 	virtual bool end_grab (GdkEvent *);
170 
171 	/** Called when a drag motion has occurred.
172 	 *  @param e Event describing the motion.
173 	 *  @param f true if this is the first movement, otherwise false.
174 	 */
175 	virtual void motion (GdkEvent* e, bool f) = 0;
176 
177 	/** Called when a drag has finished.
178 	 *  @param e Event describing the finish.
179 	 *  @param m true if some movement occurred, otherwise false.
180 	 */
181 	virtual void finished (GdkEvent* e, bool m) = 0;
182 
183 	/** Called to abort a drag and return things to how
184 	 *  they were before it started.
185 	 *  @param m true if some movement occurred, otherwise false.
186 	 */
187 	virtual void aborted (bool m) = 0;
188 
189 	/** @param m Mouse mode.
190 	 *  @return true if this drag should happen in this mouse mode.
191 	 */
active(Editing::MouseMode m)192 	virtual bool active (Editing::MouseMode m) {
193 		return true;
194 	}
195 
preview_video()196 	bool preview_video () const {
197 		return _preview_video;
198 	}
199 
200 	/** @return minimum number of pixels (x, y) that should be considered a movement */
move_threshold()201 	virtual std::pair<int, int> move_threshold () const {
202 		return std::make_pair (1, 1);
203 	}
204 
allow_vertical_autoscroll()205 	virtual bool allow_vertical_autoscroll () const {
206 		return true;
207 	}
208 
209 	/** @return true if x movement matters to this drag */
x_movement_matters()210 	virtual bool x_movement_matters () const {
211 		return true;
212 	}
213 
214 	/** @return true if y movement matters to this drag */
y_movement_matters()215 	virtual bool y_movement_matters () const {
216 		return true;
217 	}
218 
initially_vertical()219 	bool initially_vertical() const {
220 		return _initially_vertical;
221 	}
222 
223 	/** Set up the _pointer_sample_offset */
setup_pointer_sample_offset()224 	virtual void setup_pointer_sample_offset () {
225 		_pointer_sample_offset = 0;
226 	}
227 
228 	/** Set up the _video_sample_offset - relative to _current_pointer_sample */
setup_video_sample_offset()229 	virtual void setup_video_sample_offset () {
230 		_video_sample_offset = 0;
231 		_preview_video = false;
232 	}
233 
grab_button()234 	int grab_button() const { return _grab_button; }
235 
236 protected:
237 
grab_x()238 	double grab_x () const {
239 		return _grab_x;
240 	}
241 
grab_y()242 	double grab_y () const {
243 		return _grab_y;
244 	}
245 
raw_grab_sample()246 	ARDOUR::samplepos_t raw_grab_sample () const {
247 		return _raw_grab_sample;
248 	}
249 
grab_sample()250 	ARDOUR::samplepos_t grab_sample () const {
251 		return _grab_sample;
252 	}
253 
last_pointer_x()254 	double last_pointer_x () const {
255 		return _last_pointer_x;
256 	}
257 
last_pointer_y()258 	double last_pointer_y () const {
259 		return _last_pointer_y;
260 	}
261 
last_pointer_sample()262 	ARDOUR::samplepos_t last_pointer_sample () const {
263 		return _last_pointer_sample;
264 	}
265 
266 	ARDOUR::sampleoffset_t snap_delta (guint const) const;
267 	double  snap_delta_music (guint const) const;
268 
269 	double current_pointer_x () const;
270 	double current_pointer_y () const;
271 
272 	/* sets snap delta from unsnapped pos */
273 	void setup_snap_delta (ARDOUR::MusicSample pos);
274 
275 	boost::shared_ptr<ARDOUR::Region> add_midi_region (MidiTimeAxisView*, bool commit);
276 
277 	void show_verbose_cursor_time (samplepos_t);
278 	void show_verbose_cursor_duration (samplepos_t, samplepos_t, double xoffset = 0);
279 	void show_verbose_cursor_text (std::string const &);
280 	void show_view_preview (samplepos_t);
281 
282 	Editor* _editor; ///< our editor
283 	DragManager* _drags;
284 	ArdourCanvas::Item* _item; ///< our item
285 	/** Offset from the mouse's position for the drag to the start of the thing that is being dragged */
286 	ARDOUR::samplecnt_t _pointer_sample_offset;
287 	ARDOUR::samplecnt_t _video_sample_offset;
288 	bool _preview_video;
289 	bool _x_constrained; ///< true if x motion is constrained, otherwise false
290 	bool _y_constrained; ///< true if y motion is constrained, otherwise false
291 	bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false
292 
293 private:
294 	bool _trackview_only; ///< true if pointer y value should always be relative to the top of the trackview group
295 	bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
296 	bool _starting_point_passed; ///< true if we called move () with first_move flag, otherwise false
297 	bool _initially_vertical; ///< true if after move threshold is passed we appear to be moving vertically; undefined before that
298 	bool _was_double_click; ///< true if drag initiated by a double click event
299 	double _grab_x; ///< trackview x of the grab start position
300 	double _grab_y; ///< y of the grab start position, possibly adjusted if _trackview_only is true
301 	double _last_pointer_x; ///< trackview x of the pointer last time a motion occurred
302 	double _last_pointer_y; ///< trackview y of the pointer last time a motion occurred
303 	ARDOUR::samplepos_t _raw_grab_sample; ///< unsnapped sample that the mouse was at when start_grab was called, or 0
304 	ARDOUR::samplepos_t _grab_sample; ///< adjusted_sample that the mouse was at when start_grab was called, or 0
305 	ARDOUR::samplepos_t _last_pointer_sample; ///< adjusted_sample the last time a motion occurred
306 
307 	/* difference between some key position's snapped and unsnapped
308 	 *  samplepos. used for relative snap.
309 	 */
310 	samplepos_t _snap_delta;
311 	double      _snap_delta_music;
312 	CursorContext::Handle _cursor_ctx; ///< cursor change context
313 	bool _constraint_pressed; ///< if the keyboard indicated constraint modifier was pressed on start_grab()
314 	int _grab_button;
315 };
316 
317 class RegionDrag;
318 
319 /** Container for details about a region being dragged */
320 class DraggingView
321 {
322 public:
323 	DraggingView (RegionView *, RegionDrag *, TimeAxisView* original_tav);
324 
325 	RegionView* view; ///< the view
326 	/** index into RegionDrag::_time_axis_views of the view that this region is currently being displayed on,
327 	 *  or -1 if it is not visible.
328 	 */
329 	int time_axis_view;
330 	/** layer that this region is currently being displayed on.  This is a double
331 	    rather than a layer_t as we use fractional layers during drags to allow the user
332 	    to indicate a new layer to put a region on.
333 	*/
334 	double layer;
335 	double initial_y; ///< the initial y position of the view before any reparenting
336 	samplepos_t initial_position; ///< initial position of the region
337 	samplepos_t initial_end; ///< initial end position of the region
338 	samplepos_t anchored_fade_length; ///< fade_length when anchored during drag
339 	boost::shared_ptr<ARDOUR::Playlist> initial_playlist;
340 	TimeAxisView* initial_time_axis_view;
341 };
342 
343 /** Abstract base class for drags that involve region(s) */
344 class RegionDrag : public Drag, public sigc::trackable
345 {
346 public:
347 	RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
~RegionDrag()348 	virtual ~RegionDrag () {}
349 
350 protected:
351 
352 	RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag
353 	std::list<DraggingView> _views; ///< information about all views that are being dragged
354 
355 	/** a list of the non-hidden TimeAxisViews sorted by editor order key */
356 	std::vector<TimeAxisView*> _time_axis_views;
357 	int find_time_axis_view (TimeAxisView *) const;
358 	int apply_track_delta (const int start, const int delta, const int skip, const bool distance_only = false) const;
359 
360 	int _visible_y_low;
361 	int _visible_y_high;
362 	uint32_t _ntracks;
363 
364 	void setup_video_sample_offset ();
365 
366 	friend class DraggingView;
367 
368 protected:
369 	typedef std::set<boost::shared_ptr<ARDOUR::Playlist> > PlaylistSet;
370 	void add_stateful_diff_commands_for_playlists (PlaylistSet const &);
371 
372 private:
373 
374 	void region_going_away (RegionView *);
375 	PBD::ScopedConnection death_connection;
376 };
377 
378 /** Drag the Contents rather than the bounds of a region (i.e. Slip) */
379 class RegionSlipContentsDrag : public RegionDrag
380 {
381 public:
382 
383 	RegionSlipContentsDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
~RegionSlipContentsDrag()384 	virtual ~RegionSlipContentsDrag () {}
385 
386 	virtual void start_grab (GdkEvent *, Gdk::Cursor *);
387 	virtual void motion (GdkEvent *, bool);
388 	virtual void finished (GdkEvent *, bool);
389 	virtual void aborted (bool);
390 };
391 
392 /** Brush on a region to repeat it */
393 class RegionBrushDrag : public RegionDrag
394 {
395 public:
396 	RegionBrushDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
~RegionBrushDrag()397 	virtual ~RegionBrushDrag () {}
398 
399 	virtual void start_grab (GdkEvent *, Gdk::Cursor *);
400 	virtual void motion (GdkEvent *, bool);
401 	virtual void finished (GdkEvent *, bool);
402 	virtual void aborted (bool);
403 private:
404 	typedef std::set<samplepos_t> SamplePositionSet;
405 	SamplePositionSet _already_pasted;
406 };
407 
408 /** Drags involving region motion from somewhere */
409 class RegionMotionDrag : public RegionDrag
410 {
411 public:
412 
413 	RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
~RegionMotionDrag()414 	virtual ~RegionMotionDrag () {}
415 
416 	virtual void start_grab (GdkEvent *, Gdk::Cursor *);
417 	virtual void motion (GdkEvent *, bool);
418 	virtual void finished (GdkEvent *, bool);
419 	virtual void aborted (bool);
420 
421 	/** @return true if the regions being `moved' came from somewhere on the canvas;
422 	 *  false if they came from outside (e.g. from the region list).
423 	 */
424 	virtual bool regions_came_from_canvas () const = 0;
425 
426 protected:
427 
428 	double compute_x_delta (GdkEvent const *, ARDOUR::MusicSample *);
429 	virtual bool y_movement_allowed (int, double, int skip_invisible = 0) const;
430 
431 	bool _ignore_video_lock;
432 	ARDOUR::MusicSample _last_position; ///< last position of the thing being dragged
433 	double _total_x_delta;
434 	int _last_pointer_time_axis_view;
435 	double _last_pointer_layer;
436 private:
437 	uint32_t _ndropzone;
438 	uint32_t _pdropzone;
439 	uint32_t _ddropzone;
440 };
441 
442 
443 /** Drags to move (or copy) regions that are already shown in the GUI to
444  *  somewhere different.
445  */
446 class RegionMoveDrag : public RegionMotionDrag
447 {
448 public:
449 	RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool);
~RegionMoveDrag()450 	virtual ~RegionMoveDrag () {}
451 
452 	void motion (GdkEvent *, bool);
453 	void finished (GdkEvent *, bool);
454 	void aborted (bool);
455 
456 	void clear_draggingview_list ();
457 
regions_came_from_canvas()458 	bool regions_came_from_canvas () const {
459 		return true;
460 	}
461 
move_threshold()462 	std::pair<int, int> move_threshold () const {
463 		if (_copy) {
464 			return std::make_pair (6, 4);
465 		} else {
466 			return std::make_pair (2, 4);
467 		}
468 	}
469 
470 	void setup_pointer_sample_offset ();
471 
472 private:
473 	void finished_no_copy (
474 		bool const,
475 		bool const,
476 		ARDOUR::MusicSample,
477 		int32_t const ev_state
478 		);
479 
480 	void finished_copy (
481 		bool const,
482 		bool const,
483 		ARDOUR::MusicSample,
484 		int32_t const ev_state
485 		);
486 
487 	RegionView* insert_region_into_playlist (
488 		boost::shared_ptr<ARDOUR::Region>,
489 		RouteTimeAxisView*,
490 		ARDOUR::layer_t,
491 		ARDOUR::MusicSample,
492 		double quarter_note,
493 		PlaylistSet&,
494 		bool for_music = false
495 		);
496 
497 	void remove_region_from_playlist (
498 		boost::shared_ptr<ARDOUR::Region>,
499 		boost::shared_ptr<ARDOUR::Playlist>,
500 		PlaylistSet& modified_playlists
501 		);
502 
503 
504 	void collect_new_region_view (RegionView *);
505 	RouteTimeAxisView* create_destination_time_axis (boost::shared_ptr<ARDOUR::Region>, TimeAxisView* original);
506 
507 	bool _copy;
508 	RegionView* _new_region_view;
509 };
510 
511 /** Drag to insert a region from somewhere */
512 class RegionInsertDrag : public RegionMotionDrag
513 {
514 public:
515 	RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, ARDOUR::samplepos_t);
516 
517 	void finished (GdkEvent *, bool);
518 	void aborted (bool);
519 
regions_came_from_canvas()520 	bool regions_came_from_canvas () const {
521 		return false;
522 	}
523 };
524 
525 /** Region drag in splice mode */
526 class RegionSpliceDrag : public RegionMoveDrag
527 {
528 public:
529 	RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
530 
531 	void motion (GdkEvent *, bool);
532 	void finished (GdkEvent *, bool);
533 	void aborted (bool);
534 };
535 
536 /** Region drag in ripple mode */
537 
538 class RegionRippleDrag : public RegionMoveDrag
539 {
540 public:
541 	RegionRippleDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
~RegionRippleDrag()542 	~RegionRippleDrag () { delete exclude; }
543 
544 	void motion (GdkEvent *, bool);
545 	void finished (GdkEvent *, bool);
546 	void aborted (bool);
547 protected:
548 	bool y_movement_allowed (int delta_track, double delta_layer, int skip_invisible = 0) const;
549 
550 private:
551 	TimeAxisView *prev_tav; // where regions were most recently dragged from
552 	TimeAxisView *orig_tav; // where drag started
553 	ARDOUR::samplecnt_t prev_amount;
554 	ARDOUR::samplepos_t prev_position;
555 	ARDOUR::samplecnt_t selection_length;
556 	bool allow_moves_across_tracks; // only if all selected regions are on one track
557 	ARDOUR::RegionList *exclude;
558 	void add_all_after_to_views (TimeAxisView *tav, ARDOUR::samplepos_t where, const RegionSelection &exclude, bool drag_in_progress);
559 	void remove_unselected_from_views (ARDOUR::samplecnt_t amount, bool move_regions);
560 
561 	std::list<boost::shared_ptr<ARDOUR::Region> > _orig_tav_ripples;
562 };
563 
564 /** "Drag" to cut a region (action only on button release) */
565 class RegionCutDrag : public Drag
566 {
567 public:
568 	RegionCutDrag (Editor*, ArdourCanvas::Item*, samplepos_t);
569 	~RegionCutDrag ();
570 
571 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
572 	void motion (GdkEvent*, bool);
573 	void finished (GdkEvent*, bool);
574 	void aborted (bool);
575 
576 private:
577 };
578 
579 /** Drags to create regions */
580 class RegionCreateDrag : public Drag
581 {
582 public:
583 	RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *);
584 
585 	void motion (GdkEvent *, bool);
586 	void finished (GdkEvent *, bool);
587 	void aborted (bool);
588 
589 private:
590 	MidiTimeAxisView* _view;
591 	boost::shared_ptr<ARDOUR::Region> _region;
592 };
593 
594 /** Drags to resize MIDI notes */
595 class NoteResizeDrag : public Drag
596 {
597 public:
598 	NoteResizeDrag (Editor *, ArdourCanvas::Item *);
599 
600 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
601 	void motion (GdkEvent *, bool);
602 	void finished (GdkEvent *, bool);
603 	void aborted (bool);
604 
allow_vertical_autoscroll()605 	bool allow_vertical_autoscroll () const {
606 		return false;
607 	}
608 
609 private:
610 	MidiRegionView*     region;
611 	bool                relative;
612 	bool                at_front;
613 	bool                _was_selected;
614 	double              _snap_delta;
615 };
616 
617 /** Drags to move MIDI notes */
618 class NoteDrag : public Drag
619 {
620 public:
621 	NoteDrag (Editor*, ArdourCanvas::Item*);
622 
623 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
624 	void motion (GdkEvent *, bool);
625 	void finished (GdkEvent *, bool);
626 	void aborted (bool);
627 
628 	void setup_pointer_sample_offset ();
629 
allow_vertical_autoscroll()630 	bool allow_vertical_autoscroll () const {
631 		return false;
632 	}
633 
634 private:
635 
636 	double total_dx (GdkEvent * event) const; // total movement in quarter notes
637 	int8_t total_dy () const;
638 
639 	MidiRegionView* _region;
640 	NoteBase* _primary;
641 	double _cumulative_dx;
642 	double _cumulative_dy;
643 	double _earliest; // earliest quarter note in note selection
644 	bool   _was_selected;
645 	double _note_height;
646 	bool   _copy;
647 };
648 
649 class NoteCreateDrag : public Drag
650 {
651 public:
652 	NoteCreateDrag (Editor *, ArdourCanvas::Item *, MidiRegionView *);
653 	~NoteCreateDrag ();
654 
655 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
656 	void motion (GdkEvent *, bool);
657 	void finished (GdkEvent *, bool);
658 	void aborted (bool);
659 
active(Editing::MouseMode mode)660 	bool active (Editing::MouseMode mode) {
661 		return mode == Editing::MouseDraw || mode == Editing::MouseContent;
662 	}
663 
allow_vertical_autoscroll()664 	bool allow_vertical_autoscroll () const {
665 		return false;
666 	}
667 
y_movement_matters()668 	bool y_movement_matters () const {
669 		return false;
670 	}
671 
672 private:
673 	double y_to_region (double) const;
674 	ARDOUR::samplecnt_t grid_samples (samplepos_t) const;
675 
676 	/** @return minimum number of pixels (x, y) that should be considered a movement */
move_threshold()677 	virtual std::pair<int, int> move_threshold () const {
678 		return std::make_pair (0, 0);
679 	}
680 
681 	MidiRegionView* _region_view;
682 	ArdourCanvas::Rectangle* _drag_rect;
683 	samplepos_t _note[2];
684 };
685 
686 class HitCreateDrag : public Drag
687 {
688 public:
689 	HitCreateDrag (Editor *, ArdourCanvas::Item *, MidiRegionView *);
690 	~HitCreateDrag ();
691 
692 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
693 	void motion (GdkEvent *, bool);
694 	void finished (GdkEvent *, bool);
695 	void aborted (bool);
696 
active(Editing::MouseMode mode)697 	bool active (Editing::MouseMode mode) {
698 		return mode == Editing::MouseDraw || mode == Editing::MouseContent;
699 	}
700 
y_movement_matters()701 	bool y_movement_matters () const {
702 		return false;
703 	}
704 
705 private:
706 	double y_to_region (double) const;
707 	ARDOUR::samplecnt_t grid_samples (samplepos_t) const;
708 
709 	/** @return minimum number of pixels (x, y) that should be considered a movement */
move_threshold()710 	virtual std::pair<int, int> move_threshold () const {
711 		return std::make_pair (0, 0);
712 	}
713 
714 	MidiRegionView* _region_view;
715 	samplepos_t     _last_pos;
716 	double          _y;
717 
718 };
719 
720 /** Drag to move MIDI patch changes */
721 class PatchChangeDrag : public Drag
722 {
723 public:
724 	PatchChangeDrag (Editor *, PatchChange *, MidiRegionView *);
725 
726 	void motion (GdkEvent *, bool);
727 	void finished (GdkEvent *, bool);
728 	void aborted (bool);
729 
y_movement_matters()730 	bool y_movement_matters () const {
731 		return false;
732 	}
733 
allow_vertical_autoscroll()734 	bool allow_vertical_autoscroll () const {
735 		return false;
736 	}
737 
738 	void setup_pointer_sample_offset ();
739 
740 private:
741 	MidiRegionView* _region_view;
742 	PatchChange* _patch_change;
743 	double _cumulative_dx;
744 };
745 
746 /** Container for details about audio regions being dragged along with video */
747 class AVDraggingView
748 {
749 public:
750 	AVDraggingView (RegionView *);
751 
752 	RegionView* view; ///< the view
753 	samplepos_t initial_position; ///< initial position of the region
754 };
755 
756 /** Drag of video offset */
757 class VideoTimeLineDrag : public Drag
758 {
759 public:
760 	VideoTimeLineDrag (Editor *e, ArdourCanvas::Item *i);
761 
762 	void motion (GdkEvent *, bool);
763 	void finished (GdkEvent *, bool);
764 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
765 
y_movement_matters()766 	bool y_movement_matters () const {
767 		return false;
768 	}
769 
allow_vertical_autoscroll()770 	bool allow_vertical_autoscroll () const {
771 		return false;
772 	}
773 
774 	void aborted (bool);
775 
776 protected:
777 	std::list<AVDraggingView> _views; ///< information about all audio that are being dragged along
778 
779 private:
780 	ARDOUR::sampleoffset_t _startdrag_video_offset;
781 	ARDOUR::sampleoffset_t _max_backwards_drag;
782 	bool _stuck;
783 };
784 
785 /** Drag to trim region(s) */
786 class TrimDrag : public RegionDrag
787 {
788 public:
789 	enum Operation {
790 		StartTrim,
791 		EndTrim
792 	};
793 
794 	TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &, bool preserve_fade_anchor = false);
795 
796 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
797 	void motion (GdkEvent *, bool);
798 	void finished (GdkEvent *, bool);
799 	void aborted (bool);
800 
y_movement_matters()801 	bool y_movement_matters () const {
802 		return false;
803 	}
804 
allow_vertical_autoscroll()805 	bool allow_vertical_autoscroll () const {
806 		return false;
807 	}
808 
809 	void setup_pointer_sample_offset ();
810 
811 private:
812 
813 	Operation _operation;
814 
815 	bool _preserve_fade_anchor;
816 	bool _jump_position_when_done;
817 };
818 
819 /** Meter marker drag */
820 class MeterMarkerDrag : public Drag
821 {
822 public:
823 	MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
824 
825 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
826 	void motion (GdkEvent *, bool);
827 	void finished (GdkEvent *, bool);
828 	void aborted (bool);
829 
allow_vertical_autoscroll()830 	bool allow_vertical_autoscroll () const {
831 		return false;
832 	}
833 
y_movement_matters()834 	bool y_movement_matters () const {
835 		return false;
836 	}
837 
838 	void setup_pointer_sample_offset ();
839 
840 private:
841 	MeterMarker* _marker;
842 	ARDOUR::MeterSection* _real_section;
843 
844 	bool _copy;
845 	Editing::GridType _old_grid_type;
846 	Editing::SnapMode _old_snap_mode;
847 	XMLNode* before_state;
848 };
849 
850 /** Tempo marker drag */
851 class TempoMarkerDrag : public Drag
852 {
853 public:
854 	TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
855 
856 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
857 	void motion (GdkEvent *, bool);
858 	void finished (GdkEvent *, bool);
859 	void aborted (bool);
860 
allow_vertical_autoscroll()861 	bool allow_vertical_autoscroll () const {
862 		return false;
863 	}
864 
y_movement_matters()865 	bool y_movement_matters () const {
866 		return true;
867 	}
868 
869 	void setup_pointer_sample_offset ();
870 
871 private:
872 	TempoMarker* _marker;
873 	ARDOUR::TempoSection* _real_section;
874 
875 	bool _copy;
876 	bool _movable;
877 	ARDOUR::Tempo _grab_bpm;
878 	double _grab_qn;
879 	XMLNode* _before_state;
880 };
881 
882 /** BBT Ruler drag */
883 class BBTRulerDrag : public Drag
884 {
885 public:
886 	BBTRulerDrag (Editor *, ArdourCanvas::Item *);
887 
888 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
889 	void motion (GdkEvent *, bool);
890 	void finished (GdkEvent *, bool);
891 	void aborted (bool);
892 
allow_vertical_autoscroll()893 	bool allow_vertical_autoscroll () const {
894 		return false;
895 	}
896 
y_movement_matters()897 	bool y_movement_matters () const {
898 		return false;
899 	}
900 
901 	void setup_pointer_sample_offset ();
902 
903 private:
904 	double _grab_qn;
905 	ARDOUR::TempoSection* _tempo;
906 	XMLNode* _before_state;
907 	bool     _drag_valid;
908 };
909 
910 /** tempo curve twist drag */
911 class TempoTwistDrag : public Drag
912 {
913 public:
914 	TempoTwistDrag (Editor *, ArdourCanvas::Item *);
915 
916 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
917 	void motion (GdkEvent *, bool);
918 	void finished (GdkEvent *, bool);
919 	void aborted (bool);
920 
allow_vertical_autoscroll()921 	bool allow_vertical_autoscroll () const {
922 		return false;
923 	}
924 
y_movement_matters()925 	bool y_movement_matters () const {
926 		return true;
927 	}
928 
929 	void setup_pointer_sample_offset ();
930 
931 private:
932 	double _grab_qn;
933 	ARDOUR::Tempo  _grab_tempo;
934 	ARDOUR::TempoSection* _tempo;
935 	ARDOUR::TempoSection* _next_tempo;
936 	bool _drag_valid;
937 	XMLNode* _before_state;
938 };
939 
940 
941 /** tempo curve twist drag */
942 class TempoEndDrag : public Drag
943 {
944 public:
945 	TempoEndDrag (Editor *, ArdourCanvas::Item *);
946 
947 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
948 	void motion (GdkEvent *, bool);
949 	void finished (GdkEvent *, bool);
950 	void aborted (bool);
951 
allow_vertical_autoscroll()952 	bool allow_vertical_autoscroll () const {
953 		return false;
954 	}
955 
y_movement_matters()956 	bool y_movement_matters () const {
957 		return true;
958 	}
959 
960 	void setup_pointer_sample_offset ();
961 
962 private:
963 	double _grab_qn;
964 	ARDOUR::TempoSection* _tempo;
965 	XMLNode* _before_state;
966 	bool _drag_valid;
967 };
968 
969 /** Drag of the playhead cursor */
970 class CursorDrag : public Drag
971 {
972 public:
973 	CursorDrag (Editor *, EditorCursor&, bool);
974 
975 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
976 	void motion (GdkEvent *, bool);
977 	void finished (GdkEvent *, bool);
978 	void aborted (bool);
979 
allow_vertical_autoscroll()980 	bool allow_vertical_autoscroll () const {
981 		return false;
982 	}
983 
y_movement_matters()984 	bool y_movement_matters () const {
985 		return true;
986 	}
987 
988 private:
989 	void fake_locate (samplepos_t);
990 
991 	EditorCursor& _cursor;
992 	bool _stop; ///< true to stop the transport on starting the drag, otherwise false
993 	double _grab_zoom; ///< editor samples per unit when our grab started
994 
995 	//used for zooming
996 	int _last_mx;
997 	int _last_my;
998 	int _last_dx;
999 	int _last_y_delta;
1000 };
1001 
1002 /** Region fade-in drag */
1003 class FadeInDrag : public RegionDrag
1004 {
1005 public:
1006 	FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
1007 
1008 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1009 	void motion (GdkEvent *, bool);
1010 	void finished (GdkEvent *, bool);
1011 	void aborted (bool);
1012 
y_movement_matters()1013 	bool y_movement_matters () const {
1014 		return false;
1015 	}
1016 
allow_vertical_autoscroll()1017 	bool allow_vertical_autoscroll () const {
1018 		return false;
1019 	}
1020 
1021 	void setup_pointer_sample_offset ();
1022 };
1023 
1024 /** Region fade-out drag */
1025 class FadeOutDrag : public RegionDrag
1026 {
1027 public:
1028 	FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
1029 
1030 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1031 	void motion (GdkEvent *, bool);
1032 	void finished (GdkEvent *, bool);
1033 	void aborted (bool);
1034 
y_movement_matters()1035 	bool y_movement_matters () const {
1036 		return false;
1037 	}
1038 
allow_vertical_autoscroll()1039 	bool allow_vertical_autoscroll () const {
1040 		return false;
1041 	}
1042 
1043 	void setup_pointer_sample_offset ();
1044 };
1045 
1046 /** Marker drag */
1047 class MarkerDrag : public Drag
1048 {
1049 public:
1050 	MarkerDrag (Editor *, ArdourCanvas::Item *);
1051 	~MarkerDrag ();
1052 
1053 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1054 	void motion (GdkEvent *, bool);
1055 	void finished (GdkEvent *, bool);
1056 	void aborted (bool);
1057 
allow_vertical_autoscroll()1058 	bool allow_vertical_autoscroll () const {
1059 		return false;
1060 	}
1061 
y_movement_matters()1062 	bool y_movement_matters () const {
1063 		return false;
1064 	}
1065 
1066 	void setup_pointer_sample_offset ();
1067 	void setup_video_sample_offset ();
1068 
1069 private:
1070 	void update_item (ARDOUR::Location *);
1071 
1072 	ArdourMarker* _marker; ///< marker being dragged
1073 	bool _selection_changed;
1074 	struct CopiedLocationMarkerInfo {
1075 		ARDOUR::Location* location;
1076 		std::vector<ArdourMarker*> markers;
1077 		bool    move_both;
1078 		CopiedLocationMarkerInfo (ARDOUR::Location* l, ArdourMarker* m);
1079 	};
1080 
1081 	typedef std::list<CopiedLocationMarkerInfo> CopiedLocationInfo;
1082 	CopiedLocationInfo _copied_locations;
1083 	ArdourCanvas::Points _points;
1084 };
1085 
1086 /** Control point drag */
1087 class ControlPointDrag : public Drag
1088 {
1089 public:
1090 	ControlPointDrag (Editor *, ArdourCanvas::Item *);
1091 
1092 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1093 	void motion (GdkEvent *, bool);
1094 	void finished (GdkEvent *, bool);
1095 	void aborted (bool);
1096 
1097 	bool active (Editing::MouseMode m);
1098 
allow_vertical_autoscroll()1099 	bool allow_vertical_autoscroll () const {
1100 		return false;
1101 	}
1102 
1103 
1104 private:
1105 
1106 	ControlPoint* _point;
1107 	double _fixed_grab_x;
1108 	double _fixed_grab_y;
1109 	double _cumulative_x_drag;
1110 	double _cumulative_y_drag;
1111 	bool     _pushing;
1112         uint32_t _final_index;
1113 	static double _zero_gain_fraction;
1114 };
1115 
1116 /** Gain or automation line drag */
1117 class LineDrag : public Drag
1118 {
1119 public:
1120 	LineDrag (Editor *e, ArdourCanvas::Item *i);
1121 
1122 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1123 	void motion (GdkEvent *, bool);
1124 	void finished (GdkEvent *, bool);
1125 	void aborted (bool);
1126 
allow_vertical_autoscroll()1127 	bool allow_vertical_autoscroll () const {
1128 		return false;
1129 	}
1130 
1131 private:
1132 
1133 	AutomationLine* _line;
1134 	double _fixed_grab_x;
1135 	double _fixed_grab_y;
1136 	double _cumulative_y_drag;
1137 	uint32_t _before;
1138 	uint32_t _after;
1139 };
1140 
1141 /** Transient feature line drags*/
1142 class FeatureLineDrag : public Drag
1143 {
1144 public:
1145 	FeatureLineDrag (Editor *e, ArdourCanvas::Item *i);
1146 
1147 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1148 	void motion (GdkEvent *, bool);
1149 	void finished (GdkEvent *, bool);
1150 	void aborted (bool);
1151 
1152 private:
1153 
1154 	ArdourCanvas::Line* _line;
1155 	AudioRegionView* _arv;
1156 
1157 	double _region_view_grab_x;
1158 	double _cumulative_x_drag;
1159 
1160 	float _before;
1161 	uint32_t _max_x;
1162 };
1163 
1164 /** Dragging of a rubberband rectangle for selecting things */
1165 class RubberbandSelectDrag : public Drag
1166 {
1167 public:
1168 	RubberbandSelectDrag (Editor *, ArdourCanvas::Item *);
1169 
1170 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1171 	void motion (GdkEvent *, bool);
1172 	void finished (GdkEvent *, bool);
1173 	void aborted (bool);
1174 
1175 	/** @return minimum number of pixels (x, y) that should be considered a movement */
move_threshold()1176 	std::pair<int, int> move_threshold () const {
1177 		return std::make_pair (1, 1);
1178 	}
1179 
1180 	void do_select_things (GdkEvent *, bool);
1181 
1182 	/** Select some things within a rectangle.
1183 	 *  @param button_state The button state from the GdkEvent.
1184 	 *  @param x1 The left-hand side of the rectangle in session samples.
1185 	 *  @param x2 The right-hand side of the rectangle in session samples.
1186 	 *  @param y1 The top of the rectangle in trackview coordinates.
1187 	 *  @param y2 The bottom of the rectangle in trackview coordinates.
1188 	 *  @param drag_in_progress true if the drag is currently happening.
1189 	 */
1190 	virtual void select_things (int button_state, samplepos_t x1, samplepos_t x2, double y1, double y2, bool drag_in_progress) = 0;
1191 
1192 	virtual void deselect_things () = 0;
1193 
1194   protected:
1195 	bool _vertical_only;
1196 };
1197 
1198 /** A general editor RubberbandSelectDrag (for regions, automation points etc.) */
1199 class EditorRubberbandSelectDrag : public RubberbandSelectDrag
1200 {
1201 public:
1202 	EditorRubberbandSelectDrag (Editor *, ArdourCanvas::Item *);
1203 
1204 	void select_things (int, samplepos_t, samplepos_t, double, double, bool);
1205 	void deselect_things ();
1206 };
1207 
1208 /** A RubberbandSelectDrag for selecting MIDI notes */
1209 class MidiRubberbandSelectDrag : public RubberbandSelectDrag
1210 {
1211 public:
1212 	MidiRubberbandSelectDrag (Editor *, MidiRegionView *);
1213 
1214 	void select_things (int, samplepos_t, samplepos_t, double, double, bool);
1215 	void deselect_things ();
1216 
1217 private:
1218 	MidiRegionView* _region_view;
1219 };
1220 
1221 /** A RubberbandSelectDrag for selecting MIDI notes but with no horizonal component */
1222 class MidiVerticalSelectDrag : public RubberbandSelectDrag
1223 {
1224 public:
1225 	MidiVerticalSelectDrag (Editor *, MidiRegionView *);
1226 
1227 	void select_things (int, samplepos_t, samplepos_t, double, double, bool);
1228 	void deselect_things ();
1229 
1230 private:
1231 	MidiRegionView* _region_view;
1232 };
1233 
1234 /** Region drag in time-FX mode */
1235 class TimeFXDrag : public RegionDrag
1236 {
1237 public:
1238 	TimeFXDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
1239 
1240 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1241 	void motion (GdkEvent *, bool);
1242 	void finished (GdkEvent *, bool);
1243 	void aborted (bool);
1244 };
1245 
1246 /** Scrub drag in audition mode */
1247 class ScrubDrag : public Drag
1248 {
1249 public:
1250 	ScrubDrag (Editor *, ArdourCanvas::Item *);
1251 
1252 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1253 	void motion (GdkEvent *, bool);
1254 	void finished (GdkEvent *, bool);
1255 	void aborted (bool);
1256 };
1257 
1258 /** Drag in range select mode */
1259 class SelectionDrag : public Drag
1260 {
1261 public:
1262 	enum Operation {
1263 		CreateSelection,
1264 		SelectionStartTrim,
1265 		SelectionEndTrim,
1266 		SelectionMove,
1267 		SelectionExtend
1268 	};
1269 
1270 	SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
1271 
1272 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1273 	void motion (GdkEvent *, bool);
1274 	void finished (GdkEvent *, bool);
1275 	void aborted (bool);
1276 
1277 	void setup_pointer_sample_offset ();
1278 
1279 private:
1280 	Operation _operation;
1281 	bool _add;
1282 	TrackSelection _track_selection_at_start;
1283 	bool _time_selection_at_start;
1284 	samplepos_t start_at_start;
1285 	samplepos_t end_at_start;
1286 };
1287 
1288 /** Range marker drag */
1289 class RangeMarkerBarDrag : public Drag
1290 {
1291 public:
1292 	enum Operation {
1293 		CreateSkipMarker,
1294 		CreateRangeMarker,
1295 		CreateTransportMarker,
1296 		CreateCDMarker
1297 	};
1298 
1299 	RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
1300 	~RangeMarkerBarDrag ();
1301 
1302 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1303 	void motion (GdkEvent *, bool);
1304 	void finished (GdkEvent *, bool);
1305 	void aborted (bool);
1306 
allow_vertical_autoscroll()1307 	bool allow_vertical_autoscroll () const {
1308 		return false;
1309 	}
1310 
y_movement_matters()1311 	bool y_movement_matters () const {
1312 		return false;
1313 	}
1314 
1315 private:
1316 	void update_item (ARDOUR::Location *);
1317 
1318 	Operation _operation;
1319 	ArdourCanvas::Rectangle* _drag_rect;
1320 	bool _copy;
1321 };
1322 
1323 /** Drag of rectangle to set zoom */
1324 class MouseZoomDrag : public Drag
1325 {
1326 public:
1327 	MouseZoomDrag (Editor *, ArdourCanvas::Item *);
1328 
1329 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1330 	void motion (GdkEvent *, bool);
1331 	void finished (GdkEvent *, bool);
1332 	void aborted (bool);
1333 
1334 	/** @return minimum number of pixels (x, y) that should be considered a movement */
move_threshold()1335 	std::pair<int, int> move_threshold () const {
1336 		return std::make_pair (4, 4);
1337 	}
1338 
1339 private:
1340 	bool _zoom_out;
1341 };
1342 
1343 /** Drag of a range of automation data (either on an automation track or region gain),
1344  *  changing value but not position.
1345  */
1346 class AutomationRangeDrag : public Drag
1347 {
1348 public:
1349 	AutomationRangeDrag (Editor *, AutomationTimeAxisView *, std::list<ARDOUR::AudioRange> const &);
1350 	AutomationRangeDrag (Editor *, std::list<RegionView*> const &, std::list<ARDOUR::AudioRange> const &, double y_origin, double y_height);
1351 
1352 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1353 	void motion (GdkEvent *, bool);
1354 	void finished (GdkEvent *, bool);
1355 	void aborted (bool);
1356 
x_movement_matters()1357 	bool x_movement_matters () const {
1358 		return false;
1359 	}
1360 
1361 private:
1362 	void setup (std::list<boost::shared_ptr<AutomationLine> > const &);
1363 	double y_fraction (double global_y_position) const;
1364 	double value (boost::shared_ptr<ARDOUR::AutomationList> list, double x) const;
1365 
1366 	std::list<ARDOUR::AudioRange> _ranges;
1367 
1368 	/** A line that is part of the drag */
1369 	struct Line {
1370 		boost::shared_ptr<AutomationLine> line; ///< the line
1371 		std::list<ControlPoint*> points; ///< points to drag on the line
1372 		std::pair<ARDOUR::samplepos_t, ARDOUR::samplepos_t> range; ///< the range of all points on the line, in session samples
1373 		XMLNode* state; ///< the XML state node before the drag
1374 	};
1375 
1376 	std::list<Line> _lines;
1377 	double          _y_origin;
1378 	double          _y_height;
1379 	bool            _nothing_to_drag;
1380 	bool            _integral;
1381 };
1382 
1383 /** Drag of one edge of an xfade
1384  */
1385 class CrossfadeEdgeDrag : public Drag
1386 {
1387 public:
1388 	CrossfadeEdgeDrag (Editor*, AudioRegionView*, ArdourCanvas::Item*, bool start);
1389 
1390 	void start_grab (GdkEvent*, Gdk::Cursor* c = 0);
1391 	void motion (GdkEvent*, bool);
1392 	void finished (GdkEvent*, bool);
1393 	void aborted (bool);
1394 
y_movement_matters()1395 	bool y_movement_matters () const {
1396 		return false;
1397 	}
1398 
move_threshold()1399 	virtual std::pair<int, int> move_threshold () const {
1400 		return std::make_pair (1, 4);
1401 	}
1402 
1403 private:
1404 	AudioRegionView* arv;
1405 	bool start;
1406 };
1407 
1408 class RegionMarkerDrag : public Drag
1409 {
1410   public:
1411 	RegionMarkerDrag (Editor*, RegionView*, ArdourCanvas::Item*);
1412 	~RegionMarkerDrag ();
1413 
1414 	void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
1415 	void motion (GdkEvent *, bool);
1416 	void finished (GdkEvent *, bool);
1417 	void aborted (bool);
1418 
allow_vertical_autoscroll()1419 	bool allow_vertical_autoscroll () const {
1420 		return false;
1421 	}
1422 
y_movement_matters()1423 	bool y_movement_matters () const {
1424 		return false;
1425 	}
1426 
1427 	void setup_pointer_sample_offset ();
1428 
1429   private:
1430 	RegionView* rv;
1431 	ArdourMarker* view;
1432 	ARDOUR::CueMarker model;
1433 	ARDOUR::CueMarker dragging_model;
1434 };
1435 
1436 #endif /* __gtk2_ardour_editor_drag_h_ */
1437