1
0
Fork 0

Fix a4dc7249ee: Changing language or interface scale could hang. (#14087)

A bit of hysteresis caused by OnResize calling ReInit calling OnResize calling ReInit calling OnResize calling ReInit ...
pull/13374/head
Peter Nelson 2025-04-24 00:29:54 +01:00 committed by GitHub
parent 78d3eaf3e2
commit 7846f0f4ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 46 additions and 43 deletions

View File

@ -1882,7 +1882,7 @@ struct CompanyInfrastructureWindow : Window
}
}
void FindWindowPlacementAndResize([[maybe_unused]] int def_width, [[maybe_unused]] int def_height) override
void FindWindowPlacementAndResize(int def_width, int def_height, bool allow_resize) override
{
if (def_height == 0) {
/* Try to open the window with the exact required rows, but clamp to a reasonable limit. */
@ -1891,7 +1891,7 @@ struct CompanyInfrastructureWindow : Window
def_height = this->height + delta * GetCharacterHeight(FS_NORMAL);
}
this->Window::FindWindowPlacementAndResize(def_width, def_height);
this->Window::FindWindowPlacementAndResize(def_width, def_height, allow_resize);
}
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override

View File

@ -1037,7 +1037,7 @@ struct QueryWindow : public Window {
this->Window::Close();
}
void FindWindowPlacementAndResize([[maybe_unused]] int def_width, [[maybe_unused]] int def_height) override
void FindWindowPlacementAndResize(int, int, bool) override
{
/* Position query window over the calling window, ensuring it's within screen bounds. */
this->left = SoftClamp(parent->left + (parent->width / 2) - (this->width / 2), 0, _screen.width - this->width);

View File

@ -330,9 +330,9 @@ struct NetworkChatWindow : public Window {
this->Window::Close();
}
void FindWindowPlacementAndResize([[maybe_unused]] int def_width, [[maybe_unused]] int def_height) override
void FindWindowPlacementAndResize(int, int def_height, bool allow_resize) override
{
Window::FindWindowPlacementAndResize(_toolbar_width, def_height);
Window::FindWindowPlacementAndResize(_toolbar_width, def_height, allow_resize);
}
/**

View File

@ -2216,7 +2216,7 @@ struct NetworkAskRelayWindow : public Window {
}
}
void FindWindowPlacementAndResize([[maybe_unused]] int def_width, [[maybe_unused]] int def_height) override
void FindWindowPlacementAndResize(int, int, bool) override
{
/* Position query window over the calling window, ensuring it's within screen bounds. */
this->left = Clamp(parent->left + (parent->width / 2) - (this->width / 2), 0, _screen.width - this->width);
@ -2309,7 +2309,7 @@ struct NetworkAskSurveyWindow : public Window {
}
}
void FindWindowPlacementAndResize([[maybe_unused]] int def_width, [[maybe_unused]] int def_height) override
void FindWindowPlacementAndResize(int, int, bool) override
{
/* Position query window over the calling window, ensuring it's within screen bounds. */
this->left = Clamp(parent->left + (parent->width / 2) - (this->width / 2), 0, _screen.width - this->width);

View File

@ -74,9 +74,9 @@ struct StatusBarWindow : Window {
return pt;
}
void FindWindowPlacementAndResize([[maybe_unused]] int def_width, [[maybe_unused]] int def_height) override
void FindWindowPlacementAndResize(int, int def_height, bool allow_resize) override
{
Window::FindWindowPlacementAndResize(_toolbar_width, def_height);
Window::FindWindowPlacementAndResize(_toolbar_width, def_height, allow_resize);
}
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override

View File

@ -2001,9 +2001,9 @@ struct MainToolbarWindow : Window {
DoZoomInOutWindow(ZOOM_NONE, this);
}
void FindWindowPlacementAndResize([[maybe_unused]] int def_width, [[maybe_unused]] int def_height) override
void FindWindowPlacementAndResize(int, int def_height, bool allow_resize) override
{
Window::FindWindowPlacementAndResize(_toolbar_width, def_height);
Window::FindWindowPlacementAndResize(_toolbar_width, def_height, allow_resize);
}
void OnPaint() override
@ -2340,9 +2340,9 @@ struct ScenarioEditorToolbarWindow : Window {
DoZoomInOutWindow(ZOOM_NONE, this);
}
void FindWindowPlacementAndResize([[maybe_unused]] int def_width, [[maybe_unused]] int def_height) override
void FindWindowPlacementAndResize(int, int def_height, bool allow_resize) override
{
Window::FindWindowPlacementAndResize(_toolbar_width, def_height);
Window::FindWindowPlacementAndResize(_toolbar_width, def_height, allow_resize);
}
void OnPaint() override

View File

@ -990,7 +990,7 @@ void Window::ReInit(int rx, int ry, bool reposition)
if (reposition) {
Point pt = this->OnInitialPosition(this->nested_root->smallest_x, this->nested_root->smallest_y, window_number);
this->InitializePositionSize(pt.x, pt.y, this->nested_root->smallest_x, this->nested_root->smallest_y);
this->FindWindowPlacementAndResize(this->window_desc.GetDefaultWidth(), this->window_desc.GetDefaultHeight());
this->FindWindowPlacementAndResize(this->window_desc.GetDefaultWidth(), this->window_desc.GetDefaultHeight(), false);
}
ResizeWindow(this, dx, dy, true, false);
@ -1423,39 +1423,42 @@ void Window::InitializePositionSize(int x, int y, int sm_width, int sm_height)
* done here.
* @param def_width default width in pixels of the window
* @param def_height default height in pixels of the window
* @param allow_resize Set if resizing is permitted.
* @see Window::Window(), Window::InitializeData(), Window::InitializePositionSize()
*/
void Window::FindWindowPlacementAndResize(int def_width, int def_height)
void Window::FindWindowPlacementAndResize(int def_width, int def_height, bool allow_resize)
{
def_width = std::max(def_width, this->width); // Don't allow default size to be smaller than smallest size
def_height = std::max(def_height, this->height);
/* Try to make windows smaller when our window is too small.
* w->(width|height) is normally the same as min_(width|height),
* but this way the GUIs can be made a little more dynamic;
* one can use the same spec for multiple windows and those
* can then determine the real minimum size of the window. */
if (this->width != def_width || this->height != def_height) {
/* Think about the overlapping toolbars when determining the minimum window size */
int free_height = _screen.height;
const Window *wt = FindWindowById(WC_STATUS_BAR, 0);
if (wt != nullptr) free_height -= wt->height;
wt = FindWindowById(WC_MAIN_TOOLBAR, 0);
if (wt != nullptr) free_height -= wt->height;
if (allow_resize) {
def_width = std::max(def_width, this->width); // Don't allow default size to be smaller than smallest size
def_height = std::max(def_height, this->height);
/* Try to make windows smaller when our window is too small.
* w->(width|height) is normally the same as min_(width|height),
* but this way the GUIs can be made a little more dynamic;
* one can use the same spec for multiple windows and those
* can then determine the real minimum size of the window. */
if (this->width != def_width || this->height != def_height) {
/* Think about the overlapping toolbars when determining the minimum window size */
int free_height = _screen.height;
const Window *wt = FindWindowById(WC_STATUS_BAR, 0);
if (wt != nullptr) free_height -= wt->height;
wt = FindWindowById(WC_MAIN_TOOLBAR, 0);
if (wt != nullptr) free_height -= wt->height;
int enlarge_x = std::max(std::min(def_width - this->width, _screen.width - this->width), 0);
int enlarge_y = std::max(std::min(def_height - this->height, free_height - this->height), 0);
int enlarge_x = std::max(std::min(def_width - this->width, _screen.width - this->width), 0);
int enlarge_y = std::max(std::min(def_height - this->height, free_height - this->height), 0);
/* X and Y has to go by step.. calculate it.
* The cast to int is necessary else x/y are implicitly casted to
* unsigned int, which won't work. */
if (this->resize.step_width > 1) enlarge_x -= enlarge_x % (int)this->resize.step_width;
if (this->resize.step_height > 1) enlarge_y -= enlarge_y % (int)this->resize.step_height;
/* X and Y has to go by step.. calculate it.
* The cast to int is necessary else x/y are implicitly casted to
* unsigned int, which won't work. */
if (this->resize.step_width > 1) enlarge_x -= enlarge_x % (int)this->resize.step_width;
if (this->resize.step_height > 1) enlarge_y -= enlarge_y % (int)this->resize.step_height;
ResizeWindow(this, enlarge_x, enlarge_y, true, false);
/* ResizeWindow() calls this->OnResize(). */
} else {
/* Always call OnResize; that way the scrollbars and matrices get initialized. */
this->OnResize();
ResizeWindow(this, enlarge_x, enlarge_y, true, false);
/* ResizeWindow() calls this->OnResize(). */
} else {
/* Always call OnResize; that way the scrollbars and matrices get initialized. */
this->OnResize();
}
}
int nx = this->left;
@ -1744,7 +1747,7 @@ void Window::FinishInitNested(WindowNumber window_number)
this->ApplyDefaults();
Point pt = this->OnInitialPosition(this->nested_root->smallest_x, this->nested_root->smallest_y, window_number);
this->InitializePositionSize(pt.x, pt.y, this->nested_root->smallest_x, this->nested_root->smallest_y);
this->FindWindowPlacementAndResize(this->window_desc.GetDefaultWidth(), this->window_desc.GetDefaultHeight());
this->FindWindowPlacementAndResize(this->window_desc.GetDefaultWidth(), this->window_desc.GetDefaultHeight(), true);
}
/**

View File

@ -277,7 +277,7 @@ private:
protected:
void InitializeData(WindowNumber window_number);
void InitializePositionSize(int x, int y, int min_width, int min_height);
virtual void FindWindowPlacementAndResize(int def_width, int def_height);
virtual void FindWindowPlacementAndResize(int def_width, int def_height, bool allow_resize);
std::vector<int> scheduled_invalidation_data{}; ///< Data of scheduled OnInvalidateData() calls.
bool scheduled_resize = false; ///< Set if window has been resized.