remove all trace of SAE from source code.
[ardour.git] / gtk2_ardour / editor_canvas.cc
index 49f317188ef1dd2b4e7b22f1cc61cf368a42d50b..152a8046c4aae6bb8bb38a15c11789d6ad75da43 100644 (file)
@@ -39,7 +39,6 @@
 #include "ardour_ui.h"
 #include "automation_time_axis.h"
 #include "editor.h"
-#include "global_signals.h"
 #include "editing.h"
 #include "rgb_macros.h"
 #include "utils.h"
@@ -52,6 +51,7 @@
 #include "keyboard.h"
 #include "editor_cursors.h"
 #include "mouse_cursors.h"
+#include "ui_config.h"
 #include "verbose_cursor.h"
 
 #include "i18n.h"
@@ -71,45 +71,33 @@ Editor::initialize_canvas ()
        _track_canvas_viewport = new ArdourCanvas::GtkCanvasViewport (horizontal_adjustment, vertical_adjustment);
        _track_canvas = _track_canvas_viewport->canvas ();
 
-       _track_canvas->set_background_color (ARDOUR_UI::config()->color ("arrange base"));
+       _track_canvas->set_background_color (UIConfiguration::instance().color ("arrange base"));
 
        /* scroll group for items that should not automatically scroll
         *  (e.g verbose cursor). It shares the canvas coordinate space.
        */
        no_scroll_group = new ArdourCanvas::Container (_track_canvas->root());
 
-       ArdourCanvas::ScrollGroup* hsg; 
+       ArdourCanvas::ScrollGroup* hsg;
        ArdourCanvas::ScrollGroup* hg;
-       ArdourCanvas::ScrollGroup* vg;
+       ArdourCanvas::ScrollGroup* cg;
 
-       hv_scroll_group = hsg = new ArdourCanvas::ScrollGroup (_track_canvas->root(), 
+       h_scroll_group = hg = new ArdourCanvas::ScrollGroup (_track_canvas->root(), ArdourCanvas::ScrollGroup::ScrollsHorizontally);
+       CANVAS_DEBUG_NAME (h_scroll_group, "canvas h scroll");
+       _track_canvas->add_scroller (*hg);
+
+       hv_scroll_group = hsg = new ArdourCanvas::ScrollGroup (_track_canvas->root(),
                                                               ArdourCanvas::ScrollGroup::ScrollSensitivity (ArdourCanvas::ScrollGroup::ScrollsVertically|
                                                                                                             ArdourCanvas::ScrollGroup::ScrollsHorizontally));
        CANVAS_DEBUG_NAME (hv_scroll_group, "canvas hv scroll");
        _track_canvas->add_scroller (*hsg);
 
-       v_scroll_group = vg = new ArdourCanvas::ScrollGroup (_track_canvas->root(), ArdourCanvas::ScrollGroup::ScrollsVertically);
-       CANVAS_DEBUG_NAME (v_scroll_group, "canvas v scroll");
-       _track_canvas->add_scroller (*vg);
-
-       h_scroll_group = hg = new ArdourCanvas::ScrollGroup (_track_canvas->root(), ArdourCanvas::ScrollGroup::ScrollsHorizontally);
-       CANVAS_DEBUG_NAME (h_scroll_group, "canvas h scroll");
-       _track_canvas->add_scroller (*hg);
+       cursor_scroll_group = cg = new ArdourCanvas::ScrollGroup (_track_canvas->root(), ArdourCanvas::ScrollGroup::ScrollsHorizontally);
+       CANVAS_DEBUG_NAME (cursor_scroll_group, "canvas cursor scroll");
+       _track_canvas->add_scroller (*cg);
 
        _verbose_cursor = new VerboseCursor (this);
 
-       /* on the bottom, an image */
-
-       if (Profile->get_sae()) {
-               Image img (::get_icon (X_("saelogo")));
-               // logo_item = new ArdourCanvas::Pixbuf (_track_canvas->root(), 0.0, 0.0, img.get_pixbuf());
-               // logo_item->property_height_in_pixels() = true;
-               // logo_item->property_width_in_pixels() = true;
-               // logo_item->property_height_set() = true;
-               // logo_item->property_width_set() = true;
-               // logo_item->show ();
-       }
-
        /*a group to hold global rects like punch/loop indicators */
        global_rect_group = new ArdourCanvas::Container (hv_scroll_group);
        CANVAS_DEBUG_NAME (global_rect_group, "global rect group");
@@ -123,12 +111,12 @@ Editor::initialize_canvas ()
        transport_punch_range_rect->hide();
 
        /*a group to hold time (measure) lines */
-       time_line_group = new ArdourCanvas::Container (hv_scroll_group);
+       time_line_group = new ArdourCanvas::Container (h_scroll_group);
        CANVAS_DEBUG_NAME (time_line_group, "time line group");
 
        _trackview_group = new ArdourCanvas::Container (hv_scroll_group);
        CANVAS_DEBUG_NAME (_trackview_group, "Canvas TrackViews");
-       
+
        // used as rubberband rect
        rubberband_rect = new ArdourCanvas::Rectangle (hv_scroll_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
        rubberband_rect->hide();
@@ -136,11 +124,11 @@ Editor::initialize_canvas ()
        /* a group to hold stuff while it gets dragged around. Must be the
         * uppermost (last) group with hv_scroll_group as a parent
         */
-       _drag_motion_group = new ArdourCanvas::Container (hv_scroll_group);                                                                                                                                     
+       _drag_motion_group = new ArdourCanvas::Container (hv_scroll_group);
         CANVAS_DEBUG_NAME (_drag_motion_group, "Canvas Drag Motion");
 
        /* TIME BAR CANVAS */
-       
+
        _time_markers_group = new ArdourCanvas::Container (h_scroll_group);
        CANVAS_DEBUG_NAME (_time_markers_group, "time bars");
 
@@ -187,7 +175,7 @@ Editor::initialize_canvas ()
        cd_marker_bar->set_outline_what (ArdourCanvas::Rectangle::BOTTOM);
 
        ARDOUR_UI::instance()->video_timeline = new VideoTimeLine(this, videotl_group, (timebar_height * videotl_bar_height));
-       
+
        cd_marker_bar_drag_rect = new ArdourCanvas::Rectangle (cd_marker_group, ArdourCanvas::Rect (0.0, 0.0, 100, timebar_height));
        CANVAS_DEBUG_NAME (cd_marker_bar_drag_rect, "cd marker drag");
        cd_marker_bar_drag_rect->set_outline (false);
@@ -227,11 +215,6 @@ Editor::initialize_canvas ()
 
        playhead_cursor = new EditorCursor (*this, &Editor::canvas_playhead_cursor_event);
 
-       if (logo_item) {
-               logo_item->lower_to_bottom ();
-       }
-
-
        _canvas_drop_zone = new ArdourCanvas::Rectangle (hv_scroll_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, 0.0));
        /* this thing is transparent */
        _canvas_drop_zone->set_fill (false);
@@ -274,7 +257,7 @@ Editor::initialize_canvas ()
 
        initialize_rulers ();
 
-       ColorsChanged.connect (sigc::mem_fun (*this, &Editor::color_handler));
+       UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &Editor::color_handler));
        color_handler();
 
 }
@@ -402,7 +385,7 @@ void
 Editor::drop_paths_part_two (const vector<string>& paths, framepos_t frame, double ypos, bool copy)
 {
        RouteTimeAxisView* tv;
-       
+
        /* MIDI files must always be imported, because we consider them
         * writable. So split paths into two vectors, and follow the import
         * path on the MIDI part.
@@ -426,10 +409,10 @@ Editor::drop_paths_part_two (const vector<string>& paths, framepos_t frame, doub
                /* drop onto canvas background: create new tracks */
 
                frame = 0;
+               InstrumentSelector is; // instantiation builds instrument-list and sets default.
+               do_import (midi_paths, Editing::ImportDistinctFiles, ImportAsTrack, SrcBest, frame, is.selected_instrument());
 
-               do_import (midi_paths, Editing::ImportDistinctFiles, ImportAsTrack, SrcBest, frame);
-               
-               if (Profile->get_sae() || ARDOUR_UI::config()->get_only_copy_imported_files() || copy) {
+               if (UIConfiguration::instance().get_only_copy_imported_files() || copy) {
                        do_import (audio_paths, Editing::ImportDistinctFiles, Editing::ImportAsTrack, SrcBest, frame);
                } else {
                        do_embed (audio_paths, Editing::ImportDistinctFiles, ImportAsTrack, frame);
@@ -445,7 +428,7 @@ Editor::drop_paths_part_two (const vector<string>& paths, framepos_t frame, doub
 
                        do_import (midi_paths, Editing::ImportSerializeFiles, ImportToTrack, SrcBest, frame);
 
-                       if (Profile->get_sae() || ARDOUR_UI::config()->get_only_copy_imported_files() || copy) {
+                       if (UIConfiguration::instance().get_only_copy_imported_files() || copy) {
                                do_import (audio_paths, Editing::ImportSerializeFiles, Editing::ImportToTrack, SrcBest, frame);
                        } else {
                                do_embed (audio_paths, Editing::ImportSerializeFiles, ImportToTrack, frame);
@@ -501,7 +484,13 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
 void
 Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_headers)
 {
-       if (!ARDOUR_UI::config()->get_autoscroll_editor () || autoscroll_active ()) {
+       Gtk::Window* toplevel = dynamic_cast<Gtk::Window*>(contents().get_toplevel());
+
+       if (!toplevel) {
+               return;
+       }
+
+       if (!UIConfiguration::instance().get_autoscroll_editor () || autoscroll_active ()) {
                return;
        }
 
@@ -521,13 +510,13 @@ Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_headers)
 
        if (from_headers) {
                alloc = controls_layout.get_allocation ();
-       } else {        
+       } else {
                alloc = _track_canvas_viewport->get_allocation ();
 
                /* reduce height by the height of the timebars, which happens
                   to correspond to the position of the hv_scroll_group.
                */
-               
+
                alloc.set_height (alloc.get_height() - hv_scroll_group->position().y);
                alloc.set_y (alloc.get_y() + hv_scroll_group->position().y);
 
@@ -540,25 +529,25 @@ Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_headers)
 
                /* the effective width of the autoscroll boundary so
                   that we start scrolling before we hit the edge.
-                  
+
                   this helps when the window is slammed up against the
                   right edge of the screen, making it hard to scroll
                   effectively.
                */
-               
-               if (alloc.get_width() > 20) { 
+
+               if (alloc.get_width() > 20) {
                        alloc.set_width (alloc.get_width() - 20);
                        alloc.set_x (alloc.get_x() + 10);
-               } 
+               }
 
        }
-       
+
        scrolling_boundary = ArdourCanvas::Rect (alloc.get_x(), alloc.get_y(), alloc.get_x() + alloc.get_width(), alloc.get_y() + alloc.get_height());
-       
+
        int x, y;
        Gdk::ModifierType mask;
 
-       get_window()->get_pointer (x, y, mask);
+       toplevel->get_window()->get_pointer (x, y, mask);
 
        if ((allow_horiz && ((x < scrolling_boundary.x0 && leftmost_frame > 0) || x >= scrolling_boundary.x1)) ||
            (allow_vert && ((y < scrolling_boundary.y0 && vertical_adjustment.get_value() > 0)|| y >= scrolling_boundary.y1))) {
@@ -579,8 +568,13 @@ Editor::autoscroll_canvas ()
        Gdk::ModifierType mask;
        frameoffset_t dx = 0;
        bool no_stop = false;
+       Gtk::Window* toplevel = dynamic_cast<Gtk::Window*>(contents().get_toplevel());
+
+       if (!toplevel) {
+               return false;
+       }
 
-       get_window()->get_pointer (x, y, mask);
+       toplevel->get_window()->get_pointer (x, y, mask);
 
        VisualChange vc;
        bool vertical_motion = false;
@@ -608,7 +602,7 @@ Editor::autoscroll_canvas ()
                        no_stop = true;
 
                } else if (x < autoscroll_boundary.x0) {
-                       
+
                        dx = autoscroll_boundary.x0 - x;
                        dx += 10 + (2 * (autoscroll_cnt/2));
 
@@ -622,7 +616,7 @@ Editor::autoscroll_canvas ()
 
                        no_stop = true;
                }
-               
+
                if (new_frame != leftmost_frame) {
                        vc.time_origin = new_frame;
                        vc.add (VisualChange::TimeOrigin);
@@ -630,12 +624,12 @@ Editor::autoscroll_canvas ()
        }
 
        if (autoscroll_vertical_allowed) {
-               
+
                // const double vertical_pos = vertical_adjustment.get_value();
                const int speed_factor = 10;
 
-               /* vertical */ 
-               
+               /* vertical */
+
                if (y < autoscroll_boundary.y0) {
 
                        /* scroll to make higher tracks visible */
@@ -672,18 +666,18 @@ Editor::autoscroll_canvas ()
 
                ev.type = GDK_MOTION_NOTIFY;
                ev.state = Gdk::BUTTON1_MASK;
-               
+
                /* the motion handler expects events in canvas coordinate space */
 
                /* we asked for the mouse position above (::get_pointer()) via
-                * our own top level window (we being the Editor). Convert into 
+                * our own top level window (we being the Editor). Convert into
                 * coordinates within the canvas window.
                 */
 
                int cx;
                int cy;
 
-               translate_coordinates (*_track_canvas, x, y, cx, cy);
+               toplevel->translate_coordinates (*_track_canvas, x, y, cx, cy);
 
                /* clamp x and y to remain within the autoscroll boundary,
                 * which is defined in window coordinates
@@ -699,20 +693,21 @@ Editor::autoscroll_canvas ()
                ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (cx, cy));
                ev.x = d.x;
                ev.y = d.y;
+               ev.state = mask;
 
                motion_handler (0, (GdkEvent*) &ev, true);
-               
+
        } else if (no_stop) {
 
                /* not changing visual state but pointer is outside the scrolling boundary
-                * so we still need to deliver a fake motion event 
+                * so we still need to deliver a fake motion event
                 */
 
                GdkEventMotion ev;
 
                ev.type = GDK_MOTION_NOTIFY;
                ev.state = Gdk::BUTTON1_MASK;
-               
+
                /* the motion handler expects events in canvas coordinate space */
 
                /* first convert from Editor window coordinates to canvas
@@ -734,14 +729,15 @@ Editor::autoscroll_canvas ()
                }
                y = min (max ((ArdourCanvas::Coord) y, autoscroll_boundary.y0), autoscroll_boundary.y1);
 
-               translate_coordinates (*_track_canvas_viewport, x, y, cx, cy);
+               toplevel->translate_coordinates (*_track_canvas_viewport, x, y, cx, cy);
 
                ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (cx, cy));
                ev.x = d.x;
                ev.y = d.y;
+               ev.state = mask;
 
                motion_handler (0, (GdkEvent*) &ev, true);
-               
+
        } else {
                stop_canvas_autoscroll ();
                return false;
@@ -750,7 +746,7 @@ Editor::autoscroll_canvas ()
        autoscroll_cnt++;
 
        return true; /* call me again */
-}      
+}
 
 void
 Editor::start_canvas_autoscroll (bool allow_horiz, bool allow_vert, const ArdourCanvas::Rect& boundary)
@@ -829,7 +825,7 @@ Editor::ensure_time_axis_view_is_visible (TimeAxisView const & track, bool at_to
        double const track_min_y = track.y_position ();
        double const track_max_y = track.y_position () + track.effective_height ();
 
-       if (!at_top && 
+       if (!at_top &&
            (track_min_y >= current_view_min_y &&
             track_max_y < current_view_max_y)) {
                /* already visible, and caller did not ask to place it at the
@@ -886,8 +882,8 @@ Editor::set_horizontal_position (double p)
 void
 Editor::color_handler()
 {
-       ArdourCanvas::Color base = ARDOUR_UI::config()->color ("ruler base");
-       ArdourCanvas::Color text = ARDOUR_UI::config()->color ("ruler text");
+       ArdourCanvas::Color base = UIConfiguration::instance().color ("ruler base");
+       ArdourCanvas::Color text = UIConfiguration::instance().color ("ruler text");
        timecode_ruler->set_fill_color (base);
        timecode_ruler->set_outline_color (text);
        minsec_ruler->set_fill_color (base);
@@ -896,60 +892,60 @@ Editor::color_handler()
        samples_ruler->set_outline_color (text);
        bbt_ruler->set_fill_color (base);
        bbt_ruler->set_outline_color (text);
-       
-       playhead_cursor->set_color (ARDOUR_UI::config()->color ("play head"));
 
-       meter_bar->set_fill_color (ARDOUR_UI::config()->color ("meter bar"));
-       meter_bar->set_outline_color (ARDOUR_UI::config()->color ("marker bar separator"));
+       playhead_cursor->set_color (UIConfiguration::instance().color ("play head"));
 
-       tempo_bar->set_fill_color (ARDOUR_UI::config()->color ("tempo bar"));
-       tempo_bar->set_outline_color (ARDOUR_UI::config()->color ("marker bar separator"));
+       meter_bar->set_fill_color (UIConfiguration::instance().color_mod ("meter bar", "marker bar"));
+       meter_bar->set_outline_color (UIConfiguration::instance().color ("marker bar separator"));
 
-       marker_bar->set_fill_color (ARDOUR_UI::config()->color ("marker bar"));
-       marker_bar->set_outline_color (ARDOUR_UI::config()->color ("marker bar separator"));
+       tempo_bar->set_fill_color (UIConfiguration::instance().color_mod ("tempo bar", "marker bar"));
+       tempo_bar->set_outline_color (UIConfiguration::instance().color ("marker bar separator"));
 
-       cd_marker_bar->set_fill_color (ARDOUR_UI::config()->color ("cd marker bar"));
-       cd_marker_bar->set_outline_color (ARDOUR_UI::config()->color ("marker bar separator"));
+       marker_bar->set_fill_color (UIConfiguration::instance().color_mod ("marker bar", "marker bar"));
+       marker_bar->set_outline_color (UIConfiguration::instance().color ("marker bar separator"));
 
-       range_marker_bar->set_fill_color (ARDOUR_UI::config()->color ("range marker bar"));
-       range_marker_bar->set_outline_color (ARDOUR_UI::config()->color ("marker bar separator"));
+       cd_marker_bar->set_fill_color (UIConfiguration::instance().color_mod ("cd marker bar", "marker bar"));
+       cd_marker_bar->set_outline_color (UIConfiguration::instance().color ("marker bar separator"));
 
-       transport_marker_bar->set_fill_color (ARDOUR_UI::config()->color ("transport marker bar"));
-       transport_marker_bar->set_outline_color (ARDOUR_UI::config()->color ("marker bar separator"));
+       range_marker_bar->set_fill_color (UIConfiguration::instance().color_mod ("range marker bar", "marker bar"));
+       range_marker_bar->set_outline_color (UIConfiguration::instance().color ("marker bar separator"));
 
-       cd_marker_bar_drag_rect->set_fill_color (ARDOUR_UI::config()->color ("range drag bar rect"));
-       cd_marker_bar_drag_rect->set_outline_color (ARDOUR_UI::config()->color ("range drag bar rect"));
+       transport_marker_bar->set_fill_color (UIConfiguration::instance().color_mod ("transport marker bar", "marker bar"));
+       transport_marker_bar->set_outline_color (UIConfiguration::instance().color ("marker bar separator"));
 
-       range_bar_drag_rect->set_fill_color (ARDOUR_UI::config()->color ("range drag bar rect"));
-       range_bar_drag_rect->set_outline_color (ARDOUR_UI::config()->color ("range drag bar rect"));
+       cd_marker_bar_drag_rect->set_fill_color (UIConfiguration::instance().color ("range drag bar rect"));
+       cd_marker_bar_drag_rect->set_outline_color (UIConfiguration::instance().color ("range drag bar rect"));
 
-       transport_bar_drag_rect->set_fill_color (ARDOUR_UI::config()->color ("transport drag rect"));
-       transport_bar_drag_rect->set_outline_color (ARDOUR_UI::config()->color ("transport drag rect"));
+       range_bar_drag_rect->set_fill_color (UIConfiguration::instance().color ("range drag bar rect"));
+       range_bar_drag_rect->set_outline_color (UIConfiguration::instance().color ("range drag bar rect"));
 
-       transport_loop_range_rect->set_fill_color (ARDOUR_UI::config()->color_mod ("transport loop rect", "loop rectangle"));
-       transport_loop_range_rect->set_outline_color (ARDOUR_UI::config()->color ("transport loop rect"));
+       transport_bar_drag_rect->set_fill_color (UIConfiguration::instance().color ("transport drag rect"));
+       transport_bar_drag_rect->set_outline_color (UIConfiguration::instance().color ("transport drag rect"));
 
-       transport_punch_range_rect->set_fill_color (ARDOUR_UI::config()->color ("transport punch rect"));
-       transport_punch_range_rect->set_outline_color (ARDOUR_UI::config()->color ("transport punch rect"));
+       transport_loop_range_rect->set_fill_color (UIConfiguration::instance().color_mod ("transport loop rect", "loop rectangle"));
+       transport_loop_range_rect->set_outline_color (UIConfiguration::instance().color ("transport loop rect"));
 
-       transport_punchin_line->set_outline_color (ARDOUR_UI::config()->color ("punch line"));
-       transport_punchout_line->set_outline_color (ARDOUR_UI::config()->color ("punch line"));
+       transport_punch_range_rect->set_fill_color (UIConfiguration::instance().color ("transport punch rect"));
+       transport_punch_range_rect->set_outline_color (UIConfiguration::instance().color ("transport punch rect"));
 
-       rubberband_rect->set_outline_color (ARDOUR_UI::config()->color ("rubber band rect"));
-       rubberband_rect->set_fill_color (ARDOUR_UI::config()->color_mod ("rubber band rect", "selection rect"));
+       transport_punchin_line->set_outline_color (UIConfiguration::instance().color ("punch line"));
+       transport_punchout_line->set_outline_color (UIConfiguration::instance().color ("punch line"));
 
-       location_marker_color = ARDOUR_UI::config()->color ("location marker");
-       location_range_color = ARDOUR_UI::config()->color ("location range");
-       location_cd_marker_color = ARDOUR_UI::config()->color ("location cd marker");
-       location_loop_color = ARDOUR_UI::config()->color ("location loop");
-       location_punch_color = ARDOUR_UI::config()->color ("location punch");
+       rubberband_rect->set_outline_color (UIConfiguration::instance().color ("rubber band rect"));
+       rubberband_rect->set_fill_color (UIConfiguration::instance().color_mod ("rubber band rect", "selection rect"));
+
+       location_marker_color = UIConfiguration::instance().color ("location marker");
+       location_range_color = UIConfiguration::instance().color ("location range");
+       location_cd_marker_color = UIConfiguration::instance().color ("location cd marker");
+       location_loop_color = UIConfiguration::instance().color ("location loop");
+       location_punch_color = UIConfiguration::instance().color ("location punch");
 
        refresh_location_display ();
 
        /* redraw the whole thing */
-       _track_canvas->set_background_color (ARDOUR_UI::config()->color ("arrange base"));
+       _track_canvas->set_background_color (UIConfiguration::instance().color ("arrange base"));
        _track_canvas->queue_draw ();
-        
+
 /*
        redisplay_tempo (true);
 
@@ -1013,15 +1009,22 @@ Editor::set_canvas_cursor (Gdk::Cursor* cursor)
 {
        Glib::RefPtr<Gdk::Window> win = _track_canvas->get_window();
 
-       if (win && cursor) {
-               win->set_cursor (*cursor);
+       if (win && !_cursors->is_invalid (cursor)) {
+               /* glibmm 2.4 doesn't allow null cursor pointer because it uses
+                  a Gdk::Cursor& as the argument to Gdk::Window::set_cursor().
+                  But a null pointer just means "use parent window cursor",
+                  and so should be allowed. Gtkmm 3.x has fixed this API.
+
+                  For now, drop down and use C API
+               */
+               gdk_window_set_cursor (win->gobj(), cursor ? cursor->gobj() : 0);
        }
 }
 
 size_t
 Editor::push_canvas_cursor (Gdk::Cursor* cursor)
 {
-       if (cursor) {
+       if (!_cursors->is_invalid (cursor)) {
                _cursor_stack.push_back (cursor);
                set_canvas_cursor (cursor);
        }
@@ -1076,9 +1079,9 @@ Editor::which_trim_cursor (bool left) const
        }
 
        Trimmable::CanTrim ct = entered_regionview->region()->can_trim ();
-               
+
        if (left) {
-               
+
                if (ct & Trimmable::FrontTrimEarlier) {
                        return _cursors->left_side_trim;
                } else {
@@ -1096,7 +1099,7 @@ Editor::which_trim_cursor (bool left) const
 Gdk::Cursor*
 Editor::which_mode_cursor () const
 {
-       Gdk::Cursor* mode_cursor = 0;
+       Gdk::Cursor* mode_cursor = MouseCursors::invalid_cursor ();
 
        switch (mouse_mode) {
        case MouseRange:
@@ -1106,7 +1109,7 @@ Editor::which_mode_cursor () const
        case MouseCut:
                mode_cursor = _cursors->scissors;
                break;
-                       
+
        case MouseObject:
        case MouseContent:
                /* don't use mode cursor, pick a grabber cursor based on the item */
@@ -1132,20 +1135,20 @@ Editor::which_mode_cursor () const
                get_pointer_position (x, y);
 
                if (x >= 0 && y >= 0) {
-                       
+
                        vector<ArdourCanvas::Item const *> items;
 
                        /* Note how we choose a specific scroll group to get
                         * items from. This could be problematic.
                         */
-                       
+
                        hv_scroll_group->add_items_at_point (ArdourCanvas::Duple (x,y), items);
-                       
-                       // first item will be the upper most 
-                       
+
+                       // first item will be the upper most
+
                        if (!items.empty()) {
                                const ArdourCanvas::Item* i = items.front();
-                               
+
                                if (i && i->parent() && i->parent()->get_data (X_("timeselection"))) {
                                        pair<TimeAxisView*, int> tvp = trackview_by_y_position (_last_motion_y);
                                        if (dynamic_cast<AutomationTimeAxisView*> (tvp.first)) {
@@ -1162,7 +1165,7 @@ Editor::which_mode_cursor () const
 Gdk::Cursor*
 Editor::which_track_cursor () const
 {
-       Gdk::Cursor* cursor = 0;
+       Gdk::Cursor* cursor = MouseCursors::invalid_cursor();
 
        switch (_join_object_range_state) {
        case JOIN_OBJECT_RANGE_NONE:
@@ -1182,6 +1185,19 @@ Editor::which_canvas_cursor(ItemType type) const
 {
        Gdk::Cursor* cursor = which_mode_cursor ();
 
+       if (mouse_mode == MouseRange) {
+               switch (type) {
+               case StartSelectionTrimItem:
+                       cursor = _cursors->left_side_trim;
+                       break;
+               case EndSelectionTrimItem:
+                       cursor = _cursors->right_side_trim;
+                       break;
+               default:
+                       break;
+               }
+       }
+
        if ((mouse_mode == MouseObject || get_smart_mode ()) ||
            mouse_mode == MouseContent) {
 
@@ -1217,7 +1233,7 @@ Editor::which_canvas_cursor(ItemType type) const
                        cursor = _cursors->fader;
                        break;
                case GainLineItem:
-                       cursor = which_track_cursor ();
+                       cursor = _cursors->cross_hair;
                        break;
                case AutomationLineItem:
                        cursor = _cursors->cross_hair;
@@ -1250,12 +1266,16 @@ Editor::which_canvas_cursor(ItemType type) const
                        cursor = _cursors->cross_hair;
                        break;
                case LeftFrameHandle:
-                       if ( effective_mouse_mode() == MouseObject )  // (smart mode): if the user is in the top half, override the trim cursor, since they are in the range zone
-                               cursor = which_trim_cursor (true);  //alternatively, one could argue that we _should_ allow trims here, and disallow range selection
+                       if ( effective_mouse_mode() == MouseObject )  // (smart mode): if the user is in the btm half, show the trim cursor
+                               cursor = which_trim_cursor (true);
+                       else
+                               cursor = _cursors->selector;  // (smart mode): in the top half, just show the selection (range) cursor
                        break;
                case RightFrameHandle:
                        if ( effective_mouse_mode() == MouseObject )  //see above
                                cursor = which_trim_cursor (false);
+                       else
+                               cursor = _cursors->selector;
                        break;
                case StartCrossFadeItem:
                        cursor = _cursors->fade_in;
@@ -1273,7 +1293,7 @@ Editor::which_canvas_cursor(ItemType type) const
                }
 
        } else if (mouse_mode == MouseDraw) {
-               
+
                /* ControlPointItem is not really specific to region gain mode
                   but it is the same cursor so don't worry about this for now.
                   The result is that we'll see the fader cursor if we enter
@@ -1333,7 +1353,7 @@ Editor::choose_canvas_cursor_on_entry (ItemType type)
 
        Gdk::Cursor* cursor = which_canvas_cursor(type);
 
-       if (cursor) {
+       if (!_cursors->is_invalid (cursor)) {
                // Push a new enter context
                const EnterContext ctx = { type, CursorContext::create(*this, cursor) };
                _enter_stack.push_back(ctx);