Fix various cursor problems.

Add a new scoped cursor system that makes it much harder to screw up and end up
with stick cursors and so on.
This commit is contained in:
David Robillard 2014-12-20 01:11:28 -05:00
parent 5d8021bf44
commit 670938c8c4
13 changed files with 254 additions and 149 deletions

View file

@ -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);
}
}

View file

@ -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__ */

View file

@ -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());

View file

@ -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*);

View file

@ -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

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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());
}
}
}

View file

@ -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

View file

@ -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);
}
}
}

View file

@ -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;

View file

@ -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',