From d3c673e20b3a0b189ea75bb0e03b44b4de3c6757 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sat, 27 Jan 2024 18:44:27 +0000 Subject: [PATCH] Fix #11894: Defer window OnResize event to avoid processing multiple times per input tick. (#11900) --- src/window.cpp | 29 +++++++++++++++++++++++++---- src/window_gui.h | 3 +++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/window.cpp b/src/window.cpp index 3287159da1..a33c3c0177 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1447,8 +1447,8 @@ void Window::FindWindowPlacementAndResize(int def_width, int def_height) ResizeWindow(this, enlarge_x, enlarge_y); /* ResizeWindow() calls this->OnResize(). */ } else { - /* Always call OnResize; that way the scrollbars and matrices get initialized. */ - this->OnResize(); + /* Schedule OnResize; that way the scrollbars and matrices get initialized. */ + this->ScheduleResize(); } int nx = this->left; @@ -2050,8 +2050,8 @@ void ResizeWindow(Window *w, int delta_x, int delta_y, bool clamp_to_screen) EnsureVisibleCaption(w, w->left, w->top); - /* Always call OnResize to make sure everything is initialised correctly if it needs to be. */ - w->OnResize(); + /* Schedule OnResize to make sure everything is initialised correctly if it needs to be. */ + w->ScheduleResize(); w->SetDirty(); } @@ -3054,6 +3054,7 @@ void UpdateWindows() /* Process invalidations before anything else. */ for (Window *w : Window::Iterate()) { + w->ProcessScheduledResize(); w->ProcessScheduledInvalidations(); w->ProcessHighlightedInvalidations(); } @@ -3111,6 +3112,26 @@ void SetWindowClassesDirty(WindowClass cls) } } +/** + * Mark this window as resized and in need of OnResize() event. + */ +void Window::ScheduleResize() +{ + this->scheduled_resize = true; +} + +/** + * Process scheduled OnResize() event. + */ +void Window::ProcessScheduledResize() +{ + /* Sometimes OnResize() resizes the window again, in which case we can reprocess immediately. */ + while (this->scheduled_resize) { + this->scheduled_resize = false; + this->OnResize(); + } +} + /** * Mark this window's data as invalid (in need of re-computing) * @param data The data to invalidate with diff --git a/src/window_gui.h b/src/window_gui.h index a6a94496e2..d4171070cf 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -274,6 +274,7 @@ protected: virtual void FindWindowPlacementAndResize(int def_width, int def_height); std::vector scheduled_invalidation_data; ///< Data of scheduled OnInvalidateData() calls. + bool scheduled_resize; ///< Set if window has been resized. /* Protected to prevent deletion anywhere outside Window::DeleteClosedWindows(). */ virtual ~Window(); @@ -559,6 +560,8 @@ public: void SetShaded(bool make_shaded); + void ScheduleResize(); + void ProcessScheduledResize(); void InvalidateData(int data = 0, bool gui_scope = true); void ProcessScheduledInvalidations(); void ProcessHighlightedInvalidations();