From e481d033cbf4ffec105f17c84cb43480fc554ffd Mon Sep 17 00:00:00 2001 From: wangqr Date: Fri, 5 Jun 2020 22:34:06 -0400 Subject: [PATCH] Prevent event queue flooded by wxEVT_PAINT by moving some repaint request to OnIdle --- src/base_grid.cpp | 16 ++++++++++++++-- src/base_grid.h | 3 +++ src/video_display.cpp | 4 ++-- src/video_display.h | 2 +- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/base_grid.cpp b/src/base_grid.cpp index 8c8e1689f..d73f20a39 100644 --- a/src/base_grid.cpp +++ b/src/base_grid.cpp @@ -125,6 +125,7 @@ BEGIN_EVENT_TABLE(BaseGrid,wxWindow) EVT_KEY_DOWN(BaseGrid::OnKeyDown) EVT_CHAR_HOOK(BaseGrid::OnCharHook) EVT_MENU_RANGE(MENU_SHOW_COL,MENU_SHOW_COL+15,BaseGrid::OnShowColMenu) + EVT_IDLE(BaseGrid::OnIdle) END_EVENT_TABLE() void BaseGrid::OnSubtitlesCommit(int type) { @@ -136,8 +137,12 @@ void BaseGrid::OnSubtitlesCommit(int type) { Refresh(false); return; } - if (type & AssFile::COMMIT_DIAG_TIME) - Refresh(false); + if (type & AssFile::COMMIT_DIAG_TIME) { + // Dragging start / end time in audio display can generate lots of commit in a short period of time. + // On the other hand, GDI painting time depends on area, and BaseGrid typically is very large. Therefore repainting BaseGrid can be expensive. + // To prevent GUI lag / FPS drop caused by frequent repaint of BaseGrid, we do not call Refresh(false) here. Instead, we set the refresh_on_idle flag, and only repaint BaseGrid when idle. + refresh_on_idle = true; + } else if (type & AssFile::COMMIT_DIAG_TEXT) { for (auto const& rect : text_refresh_rects) RefreshRect(rect, false); @@ -263,6 +268,13 @@ void BaseGrid::OnSeek() { Refresh(false); } +void BaseGrid::OnIdle(wxIdleEvent&) { + if (refresh_on_idle) { + refresh_on_idle = false; + Refresh(false); + } +} + void BaseGrid::OnPaint(wxPaintEvent &) { // Find which columns need to be repainted std::vector paint_columns; diff --git a/src/base_grid.h b/src/base_grid.h index 366189588..809d88a41 100644 --- a/src/base_grid.h +++ b/src/base_grid.h @@ -71,6 +71,8 @@ class BaseGrid final : public wxWindow { std::vector text_refresh_rects; + bool refresh_on_idle = false; + /// Cached brushes used for row backgrounds struct { wxBrush Default; @@ -93,6 +95,7 @@ class BaseGrid final : public wxWindow { void OnContextMenu(wxContextMenuEvent &evt); void OnHighlightVisibleChange(agi::OptionValue const& opt); + void OnIdle(wxIdleEvent&); void OnKeyDown(wxKeyEvent &event); void OnCharHook(wxKeyEvent &event); void OnMouseEvent(wxMouseEvent &event); diff --git a/src/video_display.cpp b/src/video_display.cpp index 578e3ae01..2fe52c28e 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -105,7 +105,7 @@ VideoDisplay::VideoDisplay(wxToolBar *toolbar, bool freeSize, wxComboBox *zoomBo }); Bind(wxEVT_PAINT, std::bind(&VideoDisplay::Render, this)); - Bind(wxEVT_UPDATE_UI, &VideoDisplay::OnUpdateUIEvent, this); + Bind(wxEVT_IDLE, &VideoDisplay::OnIdle, this); Bind(wxEVT_SIZE, &VideoDisplay::OnSizeEvent, this); Bind(wxEVT_CONTEXT_MENU, &VideoDisplay::OnContextMenu, this); Bind(wxEVT_ENTER_WINDOW, &VideoDisplay::OnMouseEvent, this); @@ -158,7 +158,7 @@ void VideoDisplay::Render() { render_requested = true; } -void VideoDisplay::OnUpdateUIEvent(wxUpdateUIEvent&) { +void VideoDisplay::OnIdle(wxIdleEvent&) { if (render_requested) DoRender(); } diff --git a/src/video_display.h b/src/video_display.h index 653188480..62113e553 100644 --- a/src/video_display.h +++ b/src/video_display.h @@ -142,7 +142,7 @@ class VideoDisplay final : public wxGLCanvas { /// @brief Recalculate video positioning and scaling when the available area or zoom changes void OnSizeEvent(wxSizeEvent &event); void OnContextMenu(wxContextMenuEvent&); - void OnUpdateUIEvent(wxUpdateUIEvent& event); + void OnIdle(wxIdleEvent&); void DoRender(); public: