diff options
Diffstat (limited to 'gtk2_ardour')
-rw-r--r-- | gtk2_ardour/cursor_context.cc | 62 | ||||
-rw-r--r-- | gtk2_ardour/cursor_context.h | 75 | ||||
-rw-r--r-- | gtk2_ardour/editor.cc | 13 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 32 | ||||
-rw-r--r-- | gtk2_ardour/editor_audio_import.cc | 37 | ||||
-rw-r--r-- | gtk2_ardour/editor_canvas.cc | 77 | ||||
-rw-r--r-- | gtk2_ardour/editor_drag.cc | 4 | ||||
-rw-r--r-- | gtk2_ardour/editor_drag.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/editor_mouse.cc | 32 | ||||
-rw-r--r-- | gtk2_ardour/editor_ops.cc | 18 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.cc | 44 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.h | 6 | ||||
-rw-r--r-- | gtk2_ardour/wscript | 1 |
13 files changed, 254 insertions, 149 deletions
diff --git a/gtk2_ardour/cursor_context.cc b/gtk2_ardour/cursor_context.cc new file mode 100644 index 0000000000..fed9460018 --- /dev/null +++ b/gtk2_ardour/cursor_context.cc @@ -0,0 +1,62 @@ +/* + Copyright (C) 2014 Paul Davis + Author: David Robillard + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <pbd/error.h> + +#include "editor.h" +#include "cursor_context.h" + +CursorContext::CursorContext(Editor& editor, Gdk::Cursor* cursor) + : _editor(editor) + , _index(editor.push_canvas_cursor(cursor)) +{} + +CursorContext::~CursorContext() +{ + if (_index == _editor._cursor_stack.size() - 1) { + _editor.pop_canvas_cursor(); + } else { + _editor._cursor_stack[_index] = NULL; + } +} + +CursorContext::Handle +CursorContext::create(Editor& editor, Gdk::Cursor* cursor) +{ + return CursorContext::Handle(new CursorContext(editor, cursor)); +} + +void +CursorContext::change(Gdk::Cursor* cursor) +{ + _editor._cursor_stack[_index] = cursor; + if (_index == _editor._cursor_stack.size() - 1) { + _editor.set_canvas_cursor(cursor); + } +} + +void +CursorContext::set(Handle* handle, Editor& editor, Gdk::Cursor* cursor) +{ + if (*handle) { + (*handle)->change(cursor); + } else { + *handle = CursorContext::create(editor, cursor); + } +} diff --git a/gtk2_ardour/cursor_context.h b/gtk2_ardour/cursor_context.h new file mode 100644 index 0000000000..9ce086218f --- /dev/null +++ b/gtk2_ardour/cursor_context.h @@ -0,0 +1,75 @@ +/* + Copyright (C) 2014 Paul Davis + Author: David Robillard + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ardour_gtk_cursor_context_h__ +#define __ardour_gtk_cursor_context_h__ + +#include <boost/shared_ptr.hpp> +#include <gdkmm/cursor.h> + +class Editor; + +/** + A scoped handle for changing the editor mouse cursor. + + This is a safe way to change the cursor that ensures it is only modified in + a strict stack-like fashion. Whenever this handle goes out of scope, the + cursor is restored to the previous one. + + This is not quite entirely fool-proof, there is one case to be careful of: + if a cursor context handle exists, to change it, you must first reset that + handle (destroying the context) then set it. Assigning a new context to a + non-NULL handle will create the new context (pushing a cursor), then destroy + the old one, which would attempt to pop a non-top context which is an + error. To account for this, when replacing a possibly existing context, use + set() which will automatically do the right thing. +*/ +class CursorContext +{ +public: + /** A smart handle for a cursor change context. */ + typedef boost::shared_ptr<CursorContext> Handle; + + ~CursorContext(); + + /** Change the editor cursor and return a cursor context handle. + * + * When the returned handle goes out of scope, the cursor will be reset to + * the previous value. + */ + static Handle create(Editor& editor, Gdk::Cursor* cursor); + + /** Change the editor cursor of an existing cursor context. */ + void change(Gdk::Cursor* cursor); + + /** Set a context handle to a new context. + * + * If the handle points to an existing context, it will first be reset + * before the new context is created. + */ + static void set(Handle* handle, Editor& editor, Gdk::Cursor* cursor); + +private: + Editor& _editor; + size_t _index; + + CursorContext(Editor& editor, Gdk::Cursor* cursor); +}; + +#endif /* __ardour_gtk_cursor_context_h__ */ diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 5e5c323f6a..cdc77dcc85 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -313,7 +313,6 @@ Editor::Editor () clicked_routeview = 0; clicked_control_point = 0; last_update_frame = 0; - pre_press_cursor = 0; last_paste_pos = 0; paste_count = 0; _drags = new DragManager (this); @@ -374,6 +373,7 @@ Editor::Editor () current_stepping_trackview = 0; entered_track = 0; entered_regionview = 0; + _entered_item_type = NoItem; entered_marker = 0; clear_entered_track = false; current_timefx = 0; @@ -400,7 +400,6 @@ Editor::Editor () zoom_focus = ZoomFocusLeft; _edit_point = EditAtMouse; - current_canvas_cursor = 0; _visible_track_count = -1; samples_per_pixel = 2048; /* too early to use reset_zoom () */ @@ -520,6 +519,9 @@ Editor::Editor () _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set()); cerr << "Set cursor set to " << ARDOUR_UI::config()->get_icon_set() << endl; + /* Push default cursor to ever-present bottom of cursor stack. */ + push_canvas_cursor(_cursors->grabber); + ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ()); ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root()); @@ -2120,7 +2122,9 @@ Editor::set_edit_point_preference (EditPoint ep, bool force) edit_point_selector.set_text (str); } - reset_canvas_cursor (); + if (_entered_item_type != NoItem) { + choose_canvas_cursor_on_entry (_entered_item_type); + } if (!force && !changed) { return; @@ -5744,9 +5748,10 @@ Editor::ui_parameter_changed (string parameter) { if (parameter == "icon-set") { while (!_cursor_stack.empty()) { - _cursor_stack.pop(); + _cursor_stack.pop_back(); } _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set()); + _cursor_stack.push_back(_cursors->grabber); } else if (parameter == "draggable-playhead") { if (_verbose_cursor) { playhead_cursor->set_sensitive (ARDOUR_UI::config()->get_draggable_playhead()); diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index d1639d819e..b511bd0dde 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -20,13 +20,14 @@ #ifndef __ardour_editor_h__ #define __ardour_editor_h__ +#include <sys/time.h> + +#include <cmath> #include <list> #include <map> #include <set> -#include <stack> #include <string> -#include <sys/time.h> -#include <cmath> +#include <vector> #include <boost/optional.hpp> @@ -97,6 +98,7 @@ class AutomationTimeAxisView; class BundleManager; class ButtonJoiner; class ControlPoint; +class CursorContext; class DragManager; class EditNoteDialog; class EditorCursor; @@ -439,11 +441,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD void maybe_autoscroll (bool, bool, bool); bool autoscroll_active() const; - Gdk::Cursor* get_canvas_cursor () const { return current_canvas_cursor; } - void set_canvas_cursor (Gdk::Cursor*, bool save=false); - - void push_canvas_cursor (Gdk::Cursor*); - void pop_canvas_cursor (); + Gdk::Cursor* get_canvas_cursor () const; void set_current_trimmable (boost::shared_ptr<ARDOUR::Trimmable>); void set_current_movable (boost::shared_ptr<ARDOUR::Movable>); @@ -726,14 +724,18 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD Gtk::VBox global_vpacker; Gtk::VBox vpacker; - std::stack<Gdk::Cursor*> _cursor_stack; - Gdk::Cursor* current_canvas_cursor; + /* Cursor stuff. Do not use directly, use via CursorContext. */ + friend class CursorContext; + std::vector<Gdk::Cursor*> _cursor_stack; + void set_canvas_cursor (Gdk::Cursor*); + size_t push_canvas_cursor (Gdk::Cursor*); + void pop_canvas_cursor (); + Gdk::Cursor* which_grabber_cursor () const; Gdk::Cursor* which_track_cursor () const; Gdk::Cursor* which_mode_cursor () const; Gdk::Cursor* which_trim_cursor (bool left_side) const; - bool reset_canvas_cursor (); - void choose_canvas_cursor_on_entry (GdkEventCrossing*, ItemType); + void choose_canvas_cursor_on_entry (ItemType); ArdourCanvas::GtkCanvas* _track_canvas; ArdourCanvas::GtkCanvasViewport* _track_canvas_viewport; @@ -1095,7 +1097,9 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD framepos_t cut_buffer_start; framecnt_t cut_buffer_length; - Gdk::Cursor* pre_press_cursor; + boost::shared_ptr<CursorContext> _press_cursor_ctx; ///< Button press cursor context + boost::shared_ptr<CursorContext> _enter_cursor_ctx; ///< Entered item cursor context + boost::weak_ptr<ARDOUR::Trimmable> _trimmable; boost::weak_ptr<ARDOUR::Movable> _movable; @@ -1978,6 +1982,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD */ RegionView* entered_regionview; + ItemType _entered_item_type; + bool clear_entered_track; bool left_track_canvas (GdkEventCrossing*); bool entered_track_canvas (GdkEventCrossing*); diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc index bb4d8c2283..7d9c2d4c8d 100644 --- a/gtk2_ardour/editor_audio_import.cc +++ b/gtk2_ardour/editor_audio_import.cc @@ -46,6 +46,7 @@ #include "pbd/memento_command.h" #include "ardour_ui.h" +#include "cursor_context.h" #include "editor.h" #include "sfdb_ui.h" #include "editing.h" @@ -475,7 +476,7 @@ Editor::import_sndfiles (vector<string> paths, ImportDisposition disposition, Im import_status.track = track; import_status.replace = replace; - set_canvas_cursor (_cursors->wait); + CursorContext::Handle cursor_ctx = CursorContext::create(*this, _cursors->wait); gdk_flush (); /* start import thread for this spec. this will ultimately call Session::import_files() @@ -512,7 +513,6 @@ Editor::import_sndfiles (vector<string> paths, ImportDisposition disposition, Im } import_status.sources.clear(); - set_canvas_cursor (current_canvas_cursor); return result; } @@ -526,9 +526,8 @@ Editor::embed_sndfiles (vector<string> paths, bool multifile, SourceList sources; string linked_path; SoundFileInfo finfo; - int ret = 0; - push_canvas_cursor (_cursors->wait); + CursorContext::Handle cursor_ctx = CursorContext::create(*this, _cursors->wait); gdk_flush (); for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) { @@ -540,7 +539,7 @@ Editor::embed_sndfiles (vector<string> paths, bool multifile, if (!AudioFileSource::get_soundfile_info (path, finfo, error_msg)) { error << string_compose(_("Editor: cannot open file \"%1\", (%2)"), path, error_msg ) << endmsg; - goto out; + return -3; } if (check_sample_rate && (finfo.samplerate != (int) _session->frame_rate())) { @@ -562,19 +561,16 @@ Editor::embed_sndfiles (vector<string> paths, bool multifile, switch (resx) { case 0: /* stop a multi-file import */ - ret = -2; - goto out; + return -2; case 1: /* don't embed this one */ - ret = -1; - goto out; + return -1; case 2: /* do it, and the rest without asking */ check_sample_rate = false; break; case 3: /* do it */ break; default: - ret = -2; - goto out; + return -2; } } else { choices.push_back (_("Cancel")); @@ -590,13 +586,11 @@ Editor::embed_sndfiles (vector<string> paths, bool multifile, switch (resx) { case 0: /* don't import */ - ret = -1; - goto out; + return -1; case 1: /* do it */ break; default: - ret = -2; - goto out; + return -2; } } } @@ -627,23 +621,18 @@ Editor::embed_sndfiles (vector<string> paths, bool multifile, catch (failed_constructor& err) { error << string_compose(_("could not open %1"), path) << endmsg; - goto out; + return -3; } gtk_main_iteration(); } } - if (sources.empty()) { - goto out; + if (!sources.empty()) { + return add_sources (paths, sources, pos, disposition, mode, target_regions, target_tracks, track, true); } - - ret = add_sources (paths, sources, pos, disposition, mode, target_regions, target_tracks, track, true); - - out: - pop_canvas_cursor (); - return ret; + return 0; } int diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index d923489d7c..2476cdaf0c 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -27,6 +27,8 @@ #include "ardour/rc_configuration.h" #include "ardour/smf_source.h" +#include "pbd/error.h" + #include "canvas/canvas.h" #include "canvas/rectangle.h" #include "canvas/pixbuf.h" @@ -367,8 +369,10 @@ Editor::reset_controls_layout_height (int32_t h) bool Editor::track_canvas_map_handler (GdkEventAny* /*ev*/) { - if (current_canvas_cursor) { - set_canvas_cursor (current_canvas_cursor); + if (!_cursor_stack.empty()) { + set_canvas_cursor (get_canvas_cursor()); + } else { + PBD::error << "cursor stack is empty" << endmsg; } return false; } @@ -985,13 +989,16 @@ Editor::get_track_canvas() const return _track_canvas_viewport; } -void -Editor::set_canvas_cursor (Gdk::Cursor* cursor, bool save) +Gdk::Cursor* +Editor::get_canvas_cursor () const { - if (save) { - current_canvas_cursor = cursor; - } + /* The top of the cursor stack is always the currently visible cursor. */ + return _cursor_stack.back(); +} +void +Editor::set_canvas_cursor (Gdk::Cursor* cursor) +{ Glib::RefPtr<Gdk::Window> win = _track_canvas->get_window(); if (win && cursor) { @@ -999,22 +1006,32 @@ Editor::set_canvas_cursor (Gdk::Cursor* cursor, bool save) } } -void +size_t Editor::push_canvas_cursor (Gdk::Cursor* cursor) { if (cursor) { - _cursor_stack.push (cursor); - set_canvas_cursor (cursor, false); + _cursor_stack.push_back (cursor); + set_canvas_cursor (cursor); } + return _cursor_stack.size() - 1; } void Editor::pop_canvas_cursor () { - if (!_cursor_stack.empty()) { - Gdk::Cursor* cursor = _cursor_stack.top (); - _cursor_stack.pop (); - set_canvas_cursor (cursor, false); + while (true) { + if (_cursor_stack.size() <= 1) { + PBD::error << "attempt to pop default cursor" << endmsg; + return; + } + + _cursor_stack.pop_back(); + if (_cursor_stack.back()) { + /* Popped to an existing cursor, we're done. Otherwise, the + context that created this cursor has been destroyed, so we need + to skip to the next down the stack. */ + return; + } } } @@ -1147,29 +1164,8 @@ Editor::which_track_cursor () const return cursor; } -bool -Editor::reset_canvas_cursor () -{ - if (!is_drawable()) { - return false; - } - - Gdk::Cursor* cursor = which_mode_cursor (); - - if (!cursor) { - cursor = which_grabber_cursor (); - } - - if (cursor) { - set_canvas_cursor (cursor); - return true; - } - - return false; -} - void -Editor::choose_canvas_cursor_on_entry (GdkEventCrossing* /*event*/, ItemType type) +Editor::choose_canvas_cursor_on_entry (ItemType type) { Gdk::Cursor* cursor = 0; @@ -1179,7 +1175,8 @@ Editor::choose_canvas_cursor_on_entry (GdkEventCrossing* /*event*/, ItemType typ cursor = which_mode_cursor (); - if (mouse_mode == MouseObject || get_smart_mode ()) { + if ((mouse_mode == MouseObject || get_smart_mode ()) || + mouse_mode == MouseContent) { /* find correct cursor to use in object/smart mode */ @@ -1238,9 +1235,6 @@ Editor::choose_canvas_cursor_on_entry (GdkEventCrossing* /*event*/, ItemType typ case FadeOutTrimHandleItem: cursor = _cursors->fade_out; break; - case NoteItem: - cursor = which_grabber_cursor(); - break; case FeatureLineItem: cursor = _cursors->cross_hair; break; @@ -1313,7 +1307,8 @@ Editor::choose_canvas_cursor_on_entry (GdkEventCrossing* /*event*/, ItemType typ } if (cursor) { - set_canvas_cursor (cursor, true); + CursorContext::set(&_enter_cursor_ctx, *this, cursor); + _entered_item_type = type; } } diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 73a6e4dad6..2470580436 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -274,7 +274,7 @@ Drag::start_grab (GdkEvent* event, Gdk::Cursor *cursor) } else { /* CAIROCANVAS need a variant here that passes *cursor */ _item->grab (); - _editor->push_canvas_cursor (cursor); + _cursor_ctx = CursorContext::create(*_editor, cursor); } if (_editor->session() && _editor->session()->transport_rolling()) { @@ -311,7 +311,7 @@ Drag::end_grab (GdkEvent* event) finished (event, _move_threshold_passed); _editor->verbose_cursor()->hide (); - _editor->pop_canvas_cursor (); + _cursor_ctx.reset(); return _move_threshold_passed; } diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index 78b541d4f5..260a333ce9 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -27,6 +27,7 @@ #include "ardour/types.h" +#include "cursor_context.h" #include "editor_items.h" namespace ARDOUR { @@ -240,6 +241,7 @@ private: ARDOUR::framepos_t _raw_grab_frame; ///< unsnapped frame that the mouse was at when start_grab was called, or 0 ARDOUR::framepos_t _grab_frame; ///< adjusted_frame that the mouse was at when start_grab was called, or 0 ARDOUR::framepos_t _last_pointer_frame; ///< adjusted_frame the last time a motion occurred + CursorContext::Handle _cursor_ctx; ///< cursor change context }; class RegionDrag; diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index dc84a6ea45..038eea5747 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -705,7 +705,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT case RegionViewName: case StreamItem: case AutomationTrackItem: - _drags->set (new RegionCutDrag (this, item, canvas_event_sample (event)), event, current_canvas_cursor); + _drags->set (new RegionCutDrag (this, item, canvas_event_sample (event)), event, get_canvas_cursor()); return true; break; default: @@ -719,7 +719,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT /* Existing note: allow trimming/motion */ if ((note = reinterpret_cast<NoteBase*> (item->get_data ("notebase")))) { if (note->big_enough_to_trim() && note->mouse_near_ends()) { - _drags->set (new NoteResizeDrag (this, item), event, current_canvas_cursor); + _drags->set (new NoteResizeDrag (this, item), event, get_canvas_cursor()); } else { _drags->set (new NoteDrag (this, item), event); } @@ -938,7 +938,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT if ((note = reinterpret_cast<NoteBase*>(item->get_data ("notebase")))) { if (note->big_enough_to_trim() && note->mouse_near_ends()) { /* Note is big and pointer is near the end, trim */ - _drags->set (new NoteResizeDrag (this, item), event, current_canvas_cursor); + _drags->set (new NoteResizeDrag (this, item), event, get_canvas_cursor()); } else { /* Drag note */ _drags->set (new NoteDrag (this, item), event); @@ -964,7 +964,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT /* resize-drag notes */ if ((note = reinterpret_cast<NoteBase*>(item->get_data ("notebase")))) { if (note->big_enough_to_trim()) { - _drags->set (new NoteResizeDrag (this, item), event, current_canvas_cursor); + _drags->set (new NoteResizeDrag (this, item), event, get_canvas_cursor()); } } return true; @@ -976,12 +976,11 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT break; case MouseAudition: - _drags->set (new ScrubDrag (this, item), event); + _drags->set (new ScrubDrag (this, item), event, _cursors->transparent); scrub_reversals = 0; scrub_reverse_distance = 0; last_scrub_x = event->button.x; scrubbing_direction = 0; - push_canvas_cursor (_cursors->transparent); return true; break; @@ -1068,8 +1067,6 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp return false; } - pre_press_cursor = current_canvas_cursor; - _track_canvas->grab_focus(); if (_session && _session->actively_recording()) { @@ -1141,10 +1138,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT framepos_t where = canvas_event_sample (event); AutomationTimeAxisView* atv = 0; - if (pre_press_cursor) { - set_canvas_cursor (pre_press_cursor); - pre_press_cursor = 0; - } + _press_cursor_ctx.reset(); /* no action if we're recording */ @@ -1441,7 +1435,6 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT break; case MouseAudition: - pop_canvas_cursor (); if (scrubbing_direction == 0) { /* no drag, just a click */ switch (item_type) { @@ -1529,7 +1522,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ * (e.g. the actual entered regionview) */ - choose_canvas_cursor_on_entry (&event->crossing, item_type); + choose_canvas_cursor_on_entry (item_type); switch (item_type) { case ControlPointItem: @@ -1649,7 +1642,8 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent*, ItemType item_type) bool is_start; bool ret = true; - reset_canvas_cursor (); + _enter_cursor_ctx.reset(); + _entered_item_type = NoItem; switch (item_type) { case ControlPointItem: @@ -2321,8 +2315,8 @@ Editor::update_join_object_range_location (double y) _join_object_range_state = c <= 0.5 ? JOIN_OBJECT_RANGE_RANGE : JOIN_OBJECT_RANGE_OBJECT; - if (_join_object_range_state != old) { - set_canvas_cursor (which_track_cursor ()); + if (_join_object_range_state != old && _enter_cursor_ctx) { + _enter_cursor_ctx->change(which_track_cursor()); } } else if (entered_track) { @@ -2354,8 +2348,8 @@ Editor::update_join_object_range_location (double y) _join_object_range_state = JOIN_OBJECT_RANGE_OBJECT; } - if (_join_object_range_state != old) { - set_canvas_cursor (which_track_cursor ()); + if (_join_object_range_state != old && _enter_cursor_ctx) { + _enter_cursor_ctx->change(which_track_cursor()); } } } diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 221a1f7254..692ef93c7f 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -3689,14 +3689,13 @@ Editor::freeze_route () pthread_create_and_store (X_("freezer"), &itt.thread, _freeze_thread, this); - set_canvas_cursor (_cursors->wait); + CursorContext::Handle cursor_ctx = CursorContext::create(*this, _cursors->wait); while (!itt.done && !itt.cancel) { gtk_main_iteration (); } current_interthread_info = 0; - set_canvas_cursor (current_canvas_cursor); } void @@ -4734,7 +4733,7 @@ Editor::normalize_region () return; } - set_canvas_cursor (_cursors->wait); + CursorContext::Handle cursor_ctx = CursorContext::create(*this, _cursors->wait); gdk_flush (); /* XXX: should really only count audio regions here */ @@ -4753,7 +4752,6 @@ Editor::normalize_region () if (a == -1) { /* the user cancelled the operation */ - set_canvas_cursor (current_canvas_cursor); return; } @@ -4784,7 +4782,6 @@ Editor::normalize_region () } commit_reversible_command (); - set_canvas_cursor (current_canvas_cursor); } @@ -4955,7 +4952,7 @@ Editor::fork_region () begin_reversible_command (_("Fork Region(s)")); - set_canvas_cursor (_cursors->wait); + CursorContext::Handle cursor_ctx = CursorContext::create(*this, _cursors->wait); gdk_flush (); for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ) { @@ -4982,8 +4979,6 @@ Editor::fork_region () } commit_reversible_command (); - - set_canvas_cursor (current_canvas_cursor); } void @@ -5102,7 +5097,7 @@ Editor::apply_filter (Filter& filter, string command, ProgressReporter* progress begin_reversible_command (command); - set_canvas_cursor (_cursors->wait); + CursorContext::Handle cursor_ctx = CursorContext::create(*this, _cursors->wait); gdk_flush (); int n = 0; @@ -5155,7 +5150,7 @@ Editor::apply_filter (Filter& filter, string command, ProgressReporter* progress _session->add_command(new StatefulDiffCommand (playlist)); } else { - goto out; + return; } if (progress) { @@ -5168,9 +5163,6 @@ Editor::apply_filter (Filter& filter, string command, ProgressReporter* progress } commit_reversible_command (); - - out: - set_canvas_cursor (current_canvas_cursor); } void diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index d88a1efb22..f7d0cc41f8 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -122,9 +122,6 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent, , _last_event_y (0) , _grabbed_keyboard (false) , _entered (false) - , pre_enter_cursor (0) - , pre_press_cursor (0) - , pre_note_enter_cursor (0) , _note_player (0) { CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name())); @@ -171,9 +168,6 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent, , _last_event_y (0) , _grabbed_keyboard (false) , _entered (false) - , pre_enter_cursor (0) - , pre_press_cursor (0) - , pre_note_enter_cursor (0) , _note_player (0) { CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name())); @@ -225,9 +219,6 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other) , _last_event_y (0) , _grabbed_keyboard (false) , _entered (false) - , pre_enter_cursor (0) - , pre_press_cursor (0) - , pre_note_enter_cursor (0) , _note_player (0) { init (false); @@ -258,9 +249,6 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptr<M , _last_event_y (0) , _grabbed_keyboard (false) , _entered (false) - , pre_enter_cursor (0) - , pre_press_cursor (0) - , pre_note_enter_cursor (0) , _note_player (0) { init (true); @@ -427,6 +415,8 @@ bool MidiRegionView::leave_notify (GdkEventCrossing*) { leave_internal(); + _note_cursor_ctx.reset(); + _press_cursor_ctx.reset(); _entered = false; return false; @@ -487,8 +477,7 @@ MidiRegionView::button_press (GdkEventButton* ev) MouseMode m = editor->current_mouse_mode(); if (m == MouseContent && Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier())) { - pre_press_cursor = editor->get_canvas_cursor (); - editor->set_canvas_cursor (editor->cursors()->midi_pencil); + _press_cursor_ctx = CursorContext::create(*editor, editor->cursors()->midi_pencil); } if (_mouse_state != SelectTouchDragging) { @@ -521,10 +510,7 @@ MidiRegionView::button_release (GdkEventButton* ev) PublicEditor& editor = trackview.editor (); - if (pre_press_cursor) { - dynamic_cast<Editor*>(&editor)->set_canvas_cursor (pre_press_cursor, false); - pre_press_cursor = 0; - } + _press_cursor_ctx.reset(); switch (_mouse_state) { case Pressed: // Clicked @@ -3154,13 +3140,14 @@ MidiRegionView::note_entered(NoteBase* ev) { Editor* editor = dynamic_cast<Editor*>(&trackview.editor()); - pre_note_enter_cursor = editor->get_canvas_cursor (); - if (_mouse_state == SelectTouchDragging) { note_selected (ev, true); + } else if (editor->current_mouse_mode() == MouseContent) { + CursorContext::set(&_note_cursor_ctx, *editor, editor->cursors()->grabber_note); + show_verbose_cursor (ev->note ()); + } else if (editor->current_mouse_mode() == MouseDraw) { + show_verbose_cursor (ev->note ()); } - - show_verbose_cursor (ev->note ()); } void @@ -3174,10 +3161,7 @@ MidiRegionView::note_left (NoteBase*) editor->verbose_cursor()->hide (); - if (pre_note_enter_cursor) { - editor->set_canvas_cursor (pre_note_enter_cursor); - pre_note_enter_cursor = 0; - } + _note_cursor_ctx.reset(); } void @@ -3230,11 +3214,11 @@ MidiRegionView::note_mouse_position (float x_fraction, float /*y_fraction*/, boo if (can_set_cursor) { if (trimmable && x_fraction > 0.0 && x_fraction < 0.2) { - editor->set_canvas_cursor (editor->cursors()->left_side_trim); + CursorContext::set(&_note_cursor_ctx, *editor, editor->cursors()->left_side_trim); } else if (trimmable && x_fraction >= 0.8 && x_fraction < 1.0) { - editor->set_canvas_cursor (editor->cursors()->right_side_trim); - } else if (pre_note_enter_cursor) { - editor->set_canvas_cursor (pre_note_enter_cursor); + CursorContext::set(&_note_cursor_ctx, *editor, editor->cursors()->right_side_trim); + } else { + CursorContext::set(&_note_cursor_ctx, *editor, editor->cursors()->grabber_note); } } } diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index d7c8c29058..2c81f51122 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -61,6 +61,7 @@ class EditNoteDialog; class NotePlayer; class PatchChange; class ItemCounts; +class CursorContext; class MidiRegionView : public RegionView { @@ -496,9 +497,8 @@ private: PBD::ScopedConnection _mouse_mode_connection; - Gdk::Cursor* pre_enter_cursor; - Gdk::Cursor* pre_press_cursor; - Gdk::Cursor* pre_note_enter_cursor; + boost::shared_ptr<CursorContext> _note_cursor_ctx; + boost::shared_ptr<CursorContext> _press_cursor_ctx; NotePlayer* _note_player; diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index 165cd2f82b..390ebfbba6 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -55,6 +55,7 @@ gtk2_ardour_sources = [ 'configinfo.cc', 'control_point.cc', 'control_point_dialog.cc', + 'cursor_context.cc', 'curvetest.cc', 'debug.cc', 'edit_note_dialog.cc', |