Coalesce visual changes to canvas/items and allow canvas to render
authorTim Mayberry <mojofunk@gmail.com>
Sat, 1 Apr 2017 11:33:59 +0000 (21:33 +1000)
committerTim Mayberry <mojofunk@gmail.com>
Sun, 25 Jun 2017 22:40:47 +0000 (08:40 +1000)
First visual change will be processed as normal and then blocked until the
canvas renders the change. If further visual changes need processing then
Editor::pre_render callback will schedule another expose/redraw/render.

This prevents an issue where idle_visual_changer is called many times in
response to events(keys/motion/etc) but the canvas does not get a chance to
render any but the last one which results in a big pause/jump.

This results in a more responsive canvas and in particular a smoother and more
predictable zooming experience.

gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_canvas.cc

index 248c4713fe99adf50e658e0f9fbd091e5c5e40c2..37e55aded040b106ae37dea2e54f4464f659dd23 100644 (file)
@@ -345,6 +345,7 @@ Editor::Editor ()
        , _full_canvas_height (0)
        , edit_controls_left_menu (0)
        , edit_controls_right_menu (0)
+       , visual_change_queued(false)
        , _last_update_time (0)
        , _err_screen_engine (0)
        , cut_buffer_start (0)
@@ -4578,9 +4579,23 @@ Editor::_idle_visual_changer (void* arg)
        return static_cast<Editor*>(arg)->idle_visual_changer ();
 }
 
+void
+Editor::pre_render ()
+{
+       visual_change_queued = false;
+
+       if (pending_visual_change.pending != 0) {
+               ensure_visual_change_idle_handler();
+       }
+}
+
 int
 Editor::idle_visual_changer ()
 {
+       if (pending_visual_change.pending == 0) {
+               return 0;
+       }
+
        /* set_horizontal_position() below (and maybe other calls) call
           gtk_main_iteration(), so it's possible that a signal will be handled
           half-way through this method.  If this signal wants an
@@ -4592,6 +4607,11 @@ Editor::idle_visual_changer ()
        */
 
        pending_visual_change.idle_handler_id = -1;
+
+       if (visual_change_queued) {
+               return 0;
+       }
+
        pending_visual_change.being_handled = true;
 
        VisualChange vc = pending_visual_change;
@@ -4602,6 +4622,8 @@ Editor::idle_visual_changer ()
 
        pending_visual_change.being_handled = false;
 
+       visual_change_queued = true;
+
        return 0; /* this is always a one-shot call */
 }
 
index 60bf93494d83e5f5d7f3e2f47ef737b78f9f7e8f..bce6caa912f9ae9072fb5416a5f6b289ce919c96 100644 (file)
@@ -1148,6 +1148,9 @@ private:
        };
 
        VisualChange pending_visual_change;
+       bool visual_change_queued;
+
+       void pre_render ();
 
        static int _idle_visual_changer (void *arg);
        int idle_visual_changer ();
index 72d0c2b0632cde721ade62394885f8e229fd1ad7..3b38f12df04b5b5602952ef798adf4dc2662e4b8 100644 (file)
@@ -241,6 +241,8 @@ Editor::initialize_canvas ()
        _track_canvas->signal_enter_notify_event().connect (sigc::mem_fun(*this, &Editor::entered_track_canvas), false);
        _track_canvas->set_flags (CAN_FOCUS);
 
+       _track_canvas->PreRender.connect (sigc::mem_fun(*this, &Editor::pre_render));
+
        /* set up drag-n-drop */
 
        vector<TargetEntry> target_table;