use a different approach for indicating expose rects (from robin gareus). #ifdef...
[ardour.git] / gtk2_ardour / editor_canvas.cc
index f69cb4b4200cc1c191bd18b387ad5f97a26ce771..8ad2abdfad3ca77f82c10887b189d96d4fb28472 100644 (file)
@@ -21,8 +21,6 @@
 #include "gtk2ardour-config.h"
 #endif
 
-#include <jack/types.h>
-
 #include "gtkmm2ext/utils.h"
 
 #include "ardour/profile.h"
@@ -32,6 +30,7 @@
 #include "canvas/canvas.h"
 #include "canvas/rectangle.h"
 #include "canvas/pixbuf.h"
+#include "canvas/scroll_group.h"
 #include "canvas/text.h"
 #include "canvas/debug.h"
 
@@ -62,19 +61,30 @@ using namespace Glib;
 using namespace Gtkmm2ext;
 using namespace Editing;
 
-/* XXX this is a hack. it ought to be the maximum value of an framepos_t */
-
-const double max_canvas_coordinate = (double) JACK_MAX_FRAMES;
-
 void
 Editor::initialize_canvas ()
 {
        _track_canvas_viewport = new ArdourCanvas::GtkCanvasViewport (horizontal_adjustment, vertical_adjustment);
        _track_canvas = _track_canvas_viewport->canvas ();
 
-       _time_bars_canvas_viewport = new ArdourCanvas::GtkCanvasViewport (horizontal_adjustment, unused_adjustment);
-       _time_bars_canvas = _time_bars_canvas_viewport->canvas ();
-       
+       ArdourCanvas::ScrollGroup* hsg; 
+       ArdourCanvas::ScrollGroup* hg;
+       ArdourCanvas::ScrollGroup* vg;
+
+       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);
+
        _verbose_cursor = new VerboseCursor (this);
 
        /* on the bottom, an image */
@@ -86,11 +96,11 @@ Editor::initialize_canvas ()
                // logo_item->property_width_in_pixels() = true;
                // logo_item->property_height_set() = true;
                // logo_item->property_width_set() = true;
-               logo_item->show ();
+               // logo_item->show ();
        }
-       
+
        /*a group to hold global rects like punch/loop indicators */
-       global_rect_group = new ArdourCanvas::Group (_track_canvas->root());
+       global_rect_group = new ArdourCanvas::Group (hv_scroll_group);
        CANVAS_DEBUG_NAME (global_rect_group, "global rect group");
 
         transport_loop_range_rect = new ArdourCanvas::Rectangle (global_rect_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, ArdourCanvas::COORD_MAX));
@@ -102,45 +112,31 @@ Editor::initialize_canvas ()
        transport_punch_range_rect->hide();
 
        /*a group to hold time (measure) lines */
-       time_line_group = new ArdourCanvas::Group (_track_canvas->root());
+       time_line_group = new ArdourCanvas::Group (hv_scroll_group);
        CANVAS_DEBUG_NAME (time_line_group, "time line group");
 
-       _trackview_group = new ArdourCanvas::Group (_track_canvas->root());
+       _trackview_group = new ArdourCanvas::Group (hv_scroll_group);
        CANVAS_DEBUG_NAME (_trackview_group, "Canvas TrackViews");
-       _region_motion_group = new ArdourCanvas::Group (_trackview_group);
-       CANVAS_DEBUG_NAME (_region_motion_group, "Canvas Region Motion");
-
-       meter_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
-       meter_bar = new ArdourCanvas::Rectangle (meter_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height));
-       CANVAS_DEBUG_NAME (meter_bar, "meter Bar");
-       meter_bar->set_outline_what (ArdourCanvas::Rectangle::BOTTOM);
-
-       tempo_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
-       tempo_bar = new ArdourCanvas::Rectangle (tempo_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height));
-       CANVAS_DEBUG_NAME (tempo_bar, "Tempo  Bar");
-       tempo_bar->set_outline_what (ArdourCanvas::Rectangle::BOTTOM);
-
-       range_marker_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
-       range_marker_bar = new ArdourCanvas::Rectangle (range_marker_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height));
-       CANVAS_DEBUG_NAME (range_marker_bar, "Range Marker Bar");
-       range_marker_bar->set_outline_what (ArdourCanvas::Rectangle::BOTTOM);
+       
+       // used to show zoom mode active zooming
+       zoom_rect = new ArdourCanvas::Rectangle (hv_scroll_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
+       zoom_rect->hide();
+       zoom_rect->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_zoom_rect_event), (ArdourCanvas::Item*) 0));
 
-       transport_marker_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
-       transport_marker_bar = new ArdourCanvas::Rectangle (transport_marker_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height));
-       CANVAS_DEBUG_NAME (transport_marker_bar, "transport Marker Bar");
-       transport_marker_bar->set_outline_what (ArdourCanvas::Rectangle::BOTTOM);
+       // 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();
 
-       marker_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
-       marker_bar = new ArdourCanvas::Rectangle (marker_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height));
-       CANVAS_DEBUG_NAME (marker_bar, "Marker Bar");
-       marker_bar->set_outline_what (ArdourCanvas::Rectangle::BOTTOM);
+       /* 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::Group (hv_scroll_group);                                                                                                                                     
+        CANVAS_DEBUG_NAME (_drag_motion_group, "Canvas Drag Motion");
 
-       cd_marker_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
-       cd_marker_bar = new ArdourCanvas::Rectangle (cd_marker_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height));
-       CANVAS_DEBUG_NAME (cd_marker_bar, "CD Marker Bar");
-       cd_marker_bar->set_outline_what (ArdourCanvas::Rectangle::BOTTOM);
+       /* TIME BAR CANVAS */
        
-       _time_markers_group = new ArdourCanvas::Group (_time_bars_canvas->root());
+       _time_markers_group = new ArdourCanvas::Group (h_scroll_group);
+       CANVAS_DEBUG_NAME (_time_markers_group, "time bars");
 
        cd_marker_group = new ArdourCanvas::Group (_time_markers_group, ArdourCanvas::Duple (0.0, 0.0));
        CANVAS_DEBUG_NAME (cd_marker_group, "cd marker group");
@@ -160,8 +156,32 @@ Editor::initialize_canvas ()
        meter_group = new ArdourCanvas::Group (_time_markers_group, ArdourCanvas::Duple (0.0, (timebar_height * 5.0) + 1.0));
        CANVAS_DEBUG_NAME (meter_group, "meter group");
 
-       ARDOUR_UI::instance()->video_timeline = new VideoTimeLine(this, videotl_group, (timebar_height * videotl_bar_height));
+       meter_bar = new ArdourCanvas::Rectangle (meter_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height));
+       CANVAS_DEBUG_NAME (meter_bar, "meter Bar");
+       meter_bar->set_outline_what (ArdourCanvas::Rectangle::BOTTOM);
+
+       tempo_bar = new ArdourCanvas::Rectangle (tempo_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height));
+       CANVAS_DEBUG_NAME (tempo_bar, "Tempo  Bar");
+       tempo_bar->set_outline_what (ArdourCanvas::Rectangle::BOTTOM);
 
+       range_marker_bar = new ArdourCanvas::Rectangle (range_marker_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height));
+       CANVAS_DEBUG_NAME (range_marker_bar, "Range Marker Bar");
+       range_marker_bar->set_outline_what (ArdourCanvas::Rectangle::BOTTOM);
+
+       transport_marker_bar = new ArdourCanvas::Rectangle (transport_marker_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height));
+       CANVAS_DEBUG_NAME (transport_marker_bar, "transport Marker Bar");
+       transport_marker_bar->set_outline_what (ArdourCanvas::Rectangle::BOTTOM);
+
+       marker_bar = new ArdourCanvas::Rectangle (marker_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height));
+       CANVAS_DEBUG_NAME (marker_bar, "Marker Bar");
+       marker_bar->set_outline_what (ArdourCanvas::Rectangle::BOTTOM);
+
+       cd_marker_bar = new ArdourCanvas::Rectangle (cd_marker_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height));
+       CANVAS_DEBUG_NAME (cd_marker_bar, "CD Marker Bar");
+       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);
@@ -177,29 +197,20 @@ Editor::initialize_canvas ()
        transport_bar_drag_rect->set_outline (false);
        transport_bar_drag_rect->hide ();
 
-       transport_punchin_line = new ArdourCanvas::Line (_track_canvas->root());
+       transport_punchin_line = new ArdourCanvas::Line (hv_scroll_group);
        transport_punchin_line->set_x0 (0);
        transport_punchin_line->set_y0 (0);
        transport_punchin_line->set_x1 (0);
        transport_punchin_line->set_y1 (ArdourCanvas::COORD_MAX);
        transport_punchin_line->hide ();
 
-       transport_punchout_line  = new ArdourCanvas::Line (_track_canvas->root());
+       transport_punchout_line  = new ArdourCanvas::Line (hv_scroll_group);
        transport_punchout_line->set_x0 (0);
        transport_punchout_line->set_y0 (0);
        transport_punchout_line->set_x1 (0);
        transport_punchout_line->set_y1 (ArdourCanvas::COORD_MAX);
        transport_punchout_line->hide();
 
-       // used to show zoom mode active zooming
-       zoom_rect = new ArdourCanvas::Rectangle (_track_canvas->root(), ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
-       zoom_rect->hide();
-       zoom_rect->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_zoom_rect_event), (ArdourCanvas::Item*) 0));
-
-       // used as rubberband rect
-       rubberband_rect = new ArdourCanvas::Rectangle (_trackview_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
-       rubberband_rect->hide();
-
        tempo_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_tempo_bar_event), tempo_bar));
        meter_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_meter_bar_event), meter_bar));
        marker_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_marker_bar_event), marker_bar));
@@ -214,11 +225,18 @@ Editor::initialize_canvas ()
                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);
+       _canvas_drop_zone->set_outline (false);
+       _canvas_drop_zone->Event.connect (sigc::mem_fun (*this, &Editor::canvas_drop_zone_event));
+
        /* these signals will initially be delivered to the canvas itself, but if they end up remaining unhandled, they are passed to Editor-level
           handlers.
        */
 
-       _track_canvas->signal_scroll_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_scroll_event));
+       _track_canvas->signal_scroll_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_scroll_event), true));
        _track_canvas->signal_motion_notify_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_motion_notify_event));
        _track_canvas->signal_button_press_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_button_press_event));
        _track_canvas->signal_button_release_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_button_release_event));
@@ -248,6 +266,8 @@ Editor::initialize_canvas ()
 
        _track_canvas_viewport->signal_size_allocate().connect (sigc::mem_fun(*this, &Editor::track_canvas_viewport_allocate));
 
+       initialize_rulers ();
+
        ColorsChanged.connect (sigc::mem_fun (*this, &Editor::color_handler));
        color_handler();
 
@@ -260,7 +280,7 @@ Editor::track_canvas_viewport_allocate (Gtk::Allocation alloc)
        track_canvas_viewport_size_allocated ();
 }
 
-bool
+void
 Editor::track_canvas_viewport_size_allocated ()
 {
        bool height_changed = _visible_canvas_height != _canvas_viewport_allocation.get_height();
@@ -268,6 +288,8 @@ Editor::track_canvas_viewport_size_allocated ()
        _visible_canvas_width  = _canvas_viewport_allocation.get_width ();
        _visible_canvas_height = _canvas_viewport_allocation.get_height ();
 
+       _canvas_drop_zone->set_y1 (_canvas_drop_zone->y0() + (_visible_canvas_height - 20.0));
+
        // SHOWTRACKS
 
        if (height_changed) {
@@ -291,8 +313,6 @@ Editor::track_canvas_viewport_size_allocated ()
        update_fixed_rulers();
        redisplay_tempo (false);
        _summary->set_overlays_dirty ();
-
-       return false;
 }
 
 void
@@ -320,12 +340,24 @@ Editor::reset_controls_layout_width ()
 void
 Editor::reset_controls_layout_height (int32_t h)
 {
+       /* ensure that the rect that represents the "bottom" of the canvas
+        * (the drag-n-drop zone) is, in fact, at the bottom.
+        */
+
+       _canvas_drop_zone->set_position (ArdourCanvas::Duple (0, h));
+
+       /* track controls layout must span the full height of "h" (all tracks)
+        * plus the bottom rect.
+        */
+
+       h += _canvas_drop_zone->height ();
+
         /* set the height of the scrollable area (i.e. the sum of all contained widgets)
+        * for the controls layout. The size request is set elsewhere.
          */
 
         controls_layout.property_height() = h;
 
-        /* size request is set elsewhere, see ::track_canvas_allocate() */
 }
 
 bool
@@ -427,7 +459,7 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
 
        if (convert_drop_to_paths (paths, context, x, y, data, info, time) == 0) {
 
-               /* D-n-D coordinates are window-relative, so convert to "world" coordinates
+               /* D-n-D coordinates are window-relative, so convert to canvas coordinates
                 */
 
                ev.type = GDK_BUTTON_RELEASE;
@@ -461,19 +493,46 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
 void
 Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_headers)
 {
-       if (!Config->get_autoscroll_editor ()) {
+       if (!Config->get_autoscroll_editor () || autoscroll_active ()) {
                return;
        }
 
+       /* define a rectangular boundary for scrolling. If the mouse moves
+        * outside of this area and/or continue to be outside of this area,
+        * then we will continuously auto-scroll the canvas in the appropriate
+        * direction(s)
+        *
+        * the boundary is defined in coordinates relative to the toplevel
+        * window since that is what we're going to call ::get_pointer() on
+        * during autoscrolling to determine if we're still outside the
+        * boundary or not.
+        */
 
        ArdourCanvas::Rect scrolling_boundary;
        Gtk::Allocation alloc;
-       
+       int cx, cy;
+
        if (from_headers) {
                alloc = controls_layout.get_allocation ();
-       } else {
+       } else {        
                alloc = _track_canvas_viewport->get_allocation ();
+               cx = alloc.get_x();
+               cy = alloc.get_y();
+
+               /* 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);
+
+               /* now reduce it again so that we start autoscrolling before we
+                * move off the top or bottom of the canvas
+                */
+
+               alloc.set_height (alloc.get_height() - 20);
+               alloc.set_y (alloc.get_y() + 10);
+
                /* the effective width of the autoscroll boundary so
                   that we start scrolling before we hit the edge.
                   
@@ -486,19 +545,18 @@ Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_headers)
                        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());
+       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);
 
-       if ((allow_horiz && (x < scrolling_boundary.x0 || x >= scrolling_boundary.x1)) ||
-           (allow_vert && (y < scrolling_boundary.y0 || y >= scrolling_boundary.y1))) {
+       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))) {
                start_canvas_autoscroll (allow_horiz, allow_vert, scrolling_boundary);
        }
 }
@@ -521,6 +579,7 @@ Editor::autoscroll_canvas ()
        get_window()->get_pointer (x, y, mask);
 
        VisualChange vc;
+       bool vertical_motion = false;
 
        if (autoscroll_horizontal_allowed) {
 
@@ -568,34 +627,32 @@ Editor::autoscroll_canvas ()
 
        if (autoscroll_vertical_allowed) {
                
-               const double vertical_pos = vertical_adjustment.get_value();
-               double new_pixel = vertical_pos;
-               const int speed_factor = 20;
+               // const double vertical_pos = vertical_adjustment.get_value();
+               const int speed_factor = 10;
 
                /* vertical */ 
                
-               new_pixel = vertical_pos;
-
                if (y < autoscroll_boundary.y0) {
 
                        /* scroll to make higher tracks visible */
 
                        if (autoscroll_cnt && (autoscroll_cnt % speed_factor == 0)) {
                                y_motion = scroll_up_one_track ();
+                               vertical_motion = true;
                        }
 
                } else if (y > autoscroll_boundary.y1) {
 
                        if (autoscroll_cnt && (autoscroll_cnt % speed_factor == 0)) {
                                y_motion = scroll_down_one_track ();
-                               
+                               vertical_motion = true;
                        }
                }
 
                no_stop = true;
        }
 
-       if (vc.pending) {
+       if (vc.pending || vertical_motion) {
 
                /* change horizontal first */
 
@@ -614,26 +671,33 @@ Editor::autoscroll_canvas ()
                
                /* the motion handler expects events in canvas coordinate space */
 
-               /* first convert from Editor window coordinates to canvas
-                * window coordinates
+               /* we asked for the mouse position above (::get_pointer()) via
+                * our own top level window (we being the Editor). Convert into 
+                * coordinates within the canvas window.
                 */
 
                int cx;
                int cy;
 
-               /* clamp x and y to remain within the visible area */
+               translate_coordinates (*_track_canvas, x, y, cx, cy);
 
-               x = min (max ((ArdourCanvas::Coord) x, autoscroll_boundary.x0), autoscroll_boundary.x1);
-               y = min (max ((ArdourCanvas::Coord) y, autoscroll_boundary.y0), autoscroll_boundary.y1);
+               /* clamp x and y to remain within the autoscroll boundary,
+                * which is defined in window coordinates
+                */
 
-               translate_coordinates (*_track_canvas_viewport, x, y, cx, cy);
+               x = min (max ((ArdourCanvas::Coord) cx, autoscroll_boundary.x0), autoscroll_boundary.x1);
+               y = min (max ((ArdourCanvas::Coord) cy, autoscroll_boundary.y0), autoscroll_boundary.y1);
+
+               /* now convert from Editor window coordinates to canvas
+                * window coordinates
+                */
 
                ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (cx, cy));
                ev.x = d.x;
                ev.y = d.y;
 
                motion_handler (0, (GdkEvent*) &ev, true);
-
+               
        } else if (no_stop) {
 
                /* not changing visual state but pointer is outside the scrolling boundary
@@ -673,7 +737,7 @@ Editor::autoscroll_canvas ()
                ev.y = d.y;
 
                motion_handler (0, (GdkEvent*) &ev, true);
-
+               
        } else {
                stop_canvas_autoscroll ();
                return false;
@@ -785,6 +849,17 @@ Editor::set_horizontal_position (double p)
 void
 Editor::color_handler()
 {
+       ArdourCanvas::Color base = ARDOUR_UI::config()->get_canvasvar_RulerBase();
+       ArdourCanvas::Color text = ARDOUR_UI::config()->get_canvasvar_RulerText();
+       timecode_ruler->set_fill_color (base);
+       timecode_ruler->set_outline_color (text);
+       minsec_ruler->set_fill_color (base);
+       minsec_ruler->set_outline_color (text);
+       samples_ruler->set_fill_color (base);
+       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()->get_canvasvar_PlayHead());
        _verbose_cursor->set_color (ARDOUR_UI::config()->get_canvasvar_VerboseCanvasCursor());
 
@@ -865,6 +940,25 @@ Editor::set_canvas_cursor (Gdk::Cursor* cursor, bool save)
        }
 }
 
+void
+Editor::push_canvas_cursor (Gdk::Cursor* cursor)
+{
+       if (cursor) {
+               _cursor_stack.push (cursor);
+               set_canvas_cursor (cursor, false);
+       }
+}
+
+void
+Editor::pop_canvas_cursor ()
+{
+       if (!_cursor_stack.empty()) {
+               Gdk::Cursor* cursor = _cursor_stack.top ();
+               _cursor_stack.pop ();
+               set_canvas_cursor (cursor, false);
+       }
+}
+
 bool
 Editor::track_canvas_key_press (GdkEventKey*)
 {
@@ -905,24 +999,6 @@ Editor::clamp_verbose_cursor_y (double y)
        return y;
 }
 
-ArdourCanvas::Group*
-Editor::get_time_bars_group () const
-{
-       return _time_bars_canvas->root();
-}
-
-ArdourCanvas::Group*
-Editor::get_track_canvas_group() const
-{
-       return _track_canvas->root();
-}
-
-ArdourCanvas::GtkCanvasViewport*
-Editor::get_time_bars_canvas() const
-{
-       return _time_bars_canvas_viewport;
-}
-
 ArdourCanvas::GtkCanvasViewport*
 Editor::get_track_canvas() const
 {