Coalesce visual changes to canvas/items and allow canvas to render

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.
This commit is contained in:
Tim Mayberry 2017-04-01 21:33:59 +10:00
parent dac25b8db9
commit 265f52535a
3 changed files with 27 additions and 0 deletions

View 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 */
}

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

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