Fix f6d5c01: Delay deletion when closing windows

pull/332/head
glx22 3 years ago committed by Loïc Guilloux
parent ef991b1772
commit 994bf19aef

@ -196,7 +196,7 @@ struct AIListWindow : public Window {
this->SetDirty(); this->SetDirty();
if (click_count > 1) { if (click_count > 1) {
this->ChangeAI(); this->ChangeAI();
delete this; this->Close();
} }
} }
break; break;
@ -204,12 +204,12 @@ struct AIListWindow : public Window {
case WID_AIL_ACCEPT: { case WID_AIL_ACCEPT: {
this->ChangeAI(); this->ChangeAI();
delete this; this->Close();
break; break;
} }
case WID_AIL_CANCEL: case WID_AIL_CANCEL:
delete this; this->Close();
break; break;
} }
} }
@ -227,7 +227,7 @@ struct AIListWindow : public Window {
void OnInvalidateData(int data = 0, bool gui_scope = true) override void OnInvalidateData(int data = 0, bool gui_scope = true) override
{ {
if (_game_mode == GM_NORMAL && Company::IsValidID(this->slot)) { if (_game_mode == GM_NORMAL && Company::IsValidID(this->slot)) {
delete this; this->Close();
return; return;
} }
@ -518,7 +518,7 @@ struct AISettingsWindow : public Window {
} }
case WID_AIS_ACCEPT: case WID_AIS_ACCEPT:
delete this; this->Close();
break; break;
case WID_AIS_RESET: case WID_AIS_RESET:
@ -655,7 +655,7 @@ struct ScriptTextfileWindow : public TextfileWindow {
{ {
const char *textfile = GetConfig(slot)->GetTextfile(file_type, slot); const char *textfile = GetConfig(slot)->GetTextfile(file_type, slot);
if (textfile == nullptr) { if (textfile == nullptr) {
delete this; this->Close();
} else { } else {
this->LoadTextfile(textfile, (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR); this->LoadTextfile(textfile, (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR);
} }
@ -744,10 +744,11 @@ struct AIConfigWindow : public Window {
this->OnInvalidateData(0); this->OnInvalidateData(0);
} }
~AIConfigWindow() void Close() override
{ {
DeleteWindowByClass(WC_AI_LIST); DeleteWindowByClass(WC_AI_LIST);
DeleteWindowByClass(WC_AI_SETTINGS); DeleteWindowByClass(WC_AI_SETTINGS);
this->Window::Close();
} }
void SetStringParameters(int widget) const override void SetStringParameters(int widget) const override
@ -929,7 +930,7 @@ struct AIConfigWindow : public Window {
break; break;
case WID_AIC_CLOSE: case WID_AIC_CLOSE:
delete this; this->Close();
break; break;
case WID_AIC_CONTENT_DOWNLOAD: case WID_AIC_CONTENT_DOWNLOAD:

@ -76,10 +76,11 @@ struct BuildAirToolbarWindow : Window {
this->last_user_action = WIDGET_LIST_END; this->last_user_action = WIDGET_LIST_END;
} }
~BuildAirToolbarWindow() void Close() override
{ {
if (this->IsWidgetLowered(WID_AT_AIRPORT)) SetViewportCatchmentStation(nullptr, true); if (this->IsWidgetLowered(WID_AT_AIRPORT)) SetViewportCatchmentStation(nullptr, true);
if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
this->Window::Close();
} }
/** /**
@ -276,9 +277,10 @@ public:
if (selectFirstAirport) this->SelectFirstAvailableAirport(true); if (selectFirstAirport) this->SelectFirstAvailableAirport(true);
} }
virtual ~BuildAirportWindow() void Close() override
{ {
DeleteWindowById(WC_SELECT_STATION, 0); DeleteWindowById(WC_SELECT_STATION, 0);
this->PickerWindowBase::Close();
} }
void SetStringParameters(int widget) const override void SetStringParameters(int widget) const override

@ -91,9 +91,10 @@ public:
this->InitNested(1); this->InitNested(1);
} }
~BootstrapErrorWindow() void Close() override
{ {
_exit_game = true; _exit_game = true;
this->Window::Close();
} }
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
@ -144,12 +145,13 @@ public:
{ {
} }
~BootstrapContentDownloadStatusWindow() void Close() override
{ {
/* If we are not set to exit the game, it means the bootstrap failed. */ /* If we are not set to exit the game, it means the bootstrap failed. */
if (!_exit_game) { if (!_exit_game) {
new BootstrapErrorWindow(); new BootstrapErrorWindow();
} }
this->BaseNetworkContentDownloadStatusWindow::Close();
} }
void OnDownloadComplete(ContentID cid) override void OnDownloadComplete(ContentID cid) override
@ -162,7 +164,7 @@ public:
/* _exit_game is used to break out of the outer video driver's MainLoop. */ /* _exit_game is used to break out of the outer video driver's MainLoop. */
_exit_game = true; _exit_game = true;
delete this; this->Close();
} }
}; };
@ -201,9 +203,10 @@ public:
} }
/** Stop listening to the content client events. */ /** Stop listening to the content client events. */
~BootstrapAskForDownloadWindow() void Close() override
{ {
_network_content_client.RemoveCallback(this); _network_content_client.RemoveCallback(this);
this->Window::Close();
} }
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
@ -264,7 +267,7 @@ public:
/* And once the meta data is received, start downloading it. */ /* And once the meta data is received, start downloading it. */
_network_content_client.Select(ci->id); _network_content_client.Select(ci->id);
new BootstrapContentDownloadStatusWindow(); new BootstrapContentDownloadStatusWindow();
delete this; this->Close();
} }
}; };

@ -249,7 +249,7 @@ public:
if (i < 9 && i < this->bridges->size()) { if (i < 9 && i < this->bridges->size()) {
/* Build the requested bridge */ /* Build the requested bridge */
this->BuildBridge(i); this->BuildBridge(i);
delete this; this->Close();
return ES_HANDLED; return ES_HANDLED;
} }
return ES_NOT_HANDLED; return ES_NOT_HANDLED;
@ -263,7 +263,7 @@ public:
uint i = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_BBS_BRIDGE_LIST); uint i = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_BBS_BRIDGE_LIST);
if (i < this->bridges->size()) { if (i < this->bridges->size()) {
this->BuildBridge(i); this->BuildBridge(i);
delete this; this->Close();
} }
break; break;
} }

@ -1586,7 +1586,7 @@ public:
/* Cancel button */ /* Cancel button */
case WID_SCMF_CANCEL: case WID_SCMF_CANCEL:
delete this; this->Close();
break; break;
/* Load button */ /* Load button */
@ -2767,7 +2767,7 @@ struct BuyCompanyWindow : Window {
{ {
switch (widget) { switch (widget) {
case WID_BC_NO: case WID_BC_NO:
delete this; this->Close();
break; break;
case WID_BC_YES: case WID_BC_YES:

@ -185,10 +185,11 @@ struct IConsoleWindow : Window
ResizeWindow(this, _screen.width, _screen.height / 3); ResizeWindow(this, _screen.width, _screen.height / 3);
} }
~IConsoleWindow() void Close() override
{ {
_iconsole_mode = ICONSOLE_CLOSED; _iconsole_mode = ICONSOLE_CLOSED;
VideoDriver::GetInstance()->EditBoxLostFocus(); VideoDriver::GetInstance()->EditBoxLostFocus();
this->Window::Close();
} }
/** /**

@ -147,7 +147,7 @@ struct SetDateWindow : Window {
case WID_SD_SET_DATE: case WID_SD_SET_DATE:
if (this->callback != nullptr) this->callback(this, ConvertYMDToDate(this->date.year, this->date.month, this->date.day)); if (this->callback != nullptr) this->callback(this, ConvertYMDToDate(this->date.year, this->date.month, this->date.day));
delete this; this->Close();
break; break;
} }
} }

@ -291,11 +291,12 @@ struct DepotWindow : Window {
OrderBackup::Reset(); OrderBackup::Reset();
} }
~DepotWindow() void Close() override
{ {
DeleteWindowById(WC_BUILD_VEHICLE, this->window_number); DeleteWindowById(WC_BUILD_VEHICLE, this->window_number);
DeleteWindowById(GetWindowClassForVehicleType(this->type), VehicleListIdentifier(VL_DEPOT_LIST, this->type, this->owner, this->GetDepotIndex()).Pack(), false); DeleteWindowById(GetWindowClassForVehicleType(this->type), VehicleListIdentifier(VL_DEPOT_LIST, this->type, this->owner, this->GetDepotIndex()).Pack(), false);
OrderBackup::Reset(this->window_number); OrderBackup::Reset(this->window_number);
this->Window::Close();
} }
/** /**

@ -101,10 +101,11 @@ struct BuildDocksToolbarWindow : Window {
if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this); if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
} }
~BuildDocksToolbarWindow() void Close() override
{ {
if (_game_mode == GM_NORMAL && this->IsWidgetLowered(WID_DT_STATION)) SetViewportCatchmentStation(nullptr, true); if (_game_mode == GM_NORMAL && this->IsWidgetLowered(WID_DT_STATION)) SetViewportCatchmentStation(nullptr, true);
if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
this->Window::Close();
} }
/** /**
@ -416,9 +417,10 @@ public:
this->LowerWidget(_settings_client.gui.station_show_coverage + BDSW_LT_OFF); this->LowerWidget(_settings_client.gui.station_show_coverage + BDSW_LT_OFF);
} }
virtual ~BuildDocksStationWindow() void Close() override
{ {
DeleteWindowById(WC_SELECT_STATION, 0); DeleteWindowById(WC_SELECT_STATION, 0);
this->PickerWindowBase::Close();
} }
void OnPaint() override void OnPaint() override

@ -128,7 +128,7 @@ struct EnginePreviewWindow : Window {
DoCommandP(0, this->window_number, 0, CMD_WANT_ENGINE_PREVIEW); DoCommandP(0, this->window_number, 0, CMD_WANT_ENGINE_PREVIEW);
FALLTHROUGH; FALLTHROUGH;
case WID_EP_NO: case WID_EP_NO:
if (!_shift_pressed) delete this; if (!_shift_pressed) this->Close();
break; break;
} }
} }
@ -138,7 +138,7 @@ struct EnginePreviewWindow : Window {
if (!gui_scope) return; if (!gui_scope) return;
EngineID engine = this->window_number; EngineID engine = this->window_number;
if (Engine::Get(engine)->preview_company != _local_company) delete this; if (Engine::Get(engine)->preview_company != _local_company) this->Close();
} }
}; };

@ -250,7 +250,7 @@ public:
void OnInvalidateData(int data = 0, bool gui_scope = true) override void OnInvalidateData(int data = 0, bool gui_scope = true) override
{ {
/* If company gets shut down, while displaying an error about it, remove the error message. */ /* If company gets shut down, while displaying an error about it, remove the error message. */
if (this->face != INVALID_COMPANY && !Company::IsValidID(this->face)) delete this; if (this->face != INVALID_COMPANY && !Company::IsValidID(this->face)) this->Close();
} }
void SetStringParameters(int widget) const override void SetStringParameters(int widget) const override
@ -298,20 +298,21 @@ public:
void OnMouseLoop() override void OnMouseLoop() override
{ {
/* Disallow closing the window too easily, if timeout is disabled */ /* Disallow closing the window too easily, if timeout is disabled */
if (_right_button_down && !this->display_timer.HasElapsed()) delete this; if (_right_button_down && !this->display_timer.HasElapsed()) this->Close();
} }
void OnRealtimeTick(uint delta_ms) override void OnRealtimeTick(uint delta_ms) override
{ {
if (this->display_timer.CountElapsed(delta_ms) == 0) return; if (this->display_timer.CountElapsed(delta_ms) == 0) return;
delete this; this->Close();
} }
~ErrmsgWindow() void Close() override
{ {
SetRedErrorSquare(INVALID_TILE); SetRedErrorSquare(INVALID_TILE);
if (_window_system_initialized) ShowFirstError(); if (_window_system_initialized) ShowFirstError();
this->Window::Close();
} }
/** /**
@ -354,7 +355,7 @@ void UnshowCriticalError()
if (_window_system_initialized && w != nullptr) { if (_window_system_initialized && w != nullptr) {
if (w->IsCritical()) _error_list.push_front(*w); if (w->IsCritical()) _error_list.push_front(*w);
_window_system_initialized = false; _window_system_initialized = false;
delete w; w->Close();
} }
} }
@ -403,18 +404,20 @@ void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel
data.CopyOutDParams(); data.CopyOutDParams();
ErrmsgWindow *w = (ErrmsgWindow*)FindWindowById(WC_ERRMSG, 0); ErrmsgWindow *w = (ErrmsgWindow*)FindWindowById(WC_ERRMSG, 0);
if (w != nullptr && w->IsCritical()) { if (w != nullptr) {
/* A critical error is currently shown. */ if (w->IsCritical()) {
if (wl == WL_CRITICAL) { /* A critical error is currently shown. */
/* Push another critical error in the queue of errors, if (wl == WL_CRITICAL) {
* but do not put other errors in the queue. */ /* Push another critical error in the queue of errors,
_error_list.push_back(data); * but do not put other errors in the queue. */
_error_list.push_back(data);
}
return;
} }
} else { /* A non-critical error was shown. */
/* Nothing or a non-critical error was shown. */ w->Close();
delete w;
new ErrmsgWindow(data);
} }
new ErrmsgWindow(data);
} }
@ -425,7 +428,7 @@ void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel
bool HideActiveErrorMessage() { bool HideActiveErrorMessage() {
ErrmsgWindow *w = (ErrmsgWindow*)FindWindowById(WC_ERRMSG, 0); ErrmsgWindow *w = (ErrmsgWindow*)FindWindowById(WC_ERRMSG, 0);
if (w == nullptr) return false; if (w == nullptr) return false;
delete w; w->Close();
return true; return true;
} }

@ -398,12 +398,13 @@ public:
} }
} }
virtual ~SaveLoadWindow() void Close() override
{ {
/* pause is only used in single-player, non-editor mode, non menu mode */ /* pause is only used in single-player, non-editor mode, non menu mode */
if (!_networking && _game_mode != GM_EDITOR && _game_mode != GM_MENU) { if (!_networking && _game_mode != GM_EDITOR && _game_mode != GM_MENU) {
DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE); DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE);
} }
this->Window::Close();
} }
void DrawWidget(const Rect &r, int widget) const override void DrawWidget(const Rect &r, int widget) const override
@ -617,12 +618,12 @@ public:
_file_to_saveload.SetTitle(this->selected->title); _file_to_saveload.SetTitle(this->selected->title);
if (this->abstract_filetype == FT_HEIGHTMAP) { if (this->abstract_filetype == FT_HEIGHTMAP) {
delete this; this->Close();
ShowHeightmapLoad(); ShowHeightmapLoad();
} else if (!_load_check_data.HasNewGrfs() || _load_check_data.grf_compatibility != GLC_NOT_FOUND || _settings_client.gui.UserIsAllowedToChangeNewGRFs()) { } else if (!_load_check_data.HasNewGrfs() || _load_check_data.grf_compatibility != GLC_NOT_FOUND || _settings_client.gui.UserIsAllowedToChangeNewGRFs()) {
_switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_SCENARIO : SM_LOAD_GAME; _switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_SCENARIO : SM_LOAD_GAME;
ClearErrorMessages(); ClearErrorMessages();
delete this; this->Close();
} }
break; break;
} }
@ -688,7 +689,7 @@ public:
_file_to_saveload.SetName(name); _file_to_saveload.SetName(name);
_file_to_saveload.SetTitle(file->title); _file_to_saveload.SetTitle(file->title);
delete this; this->Close();
ShowHeightmapLoad(); ShowHeightmapLoad();
} }
} }
@ -749,7 +750,7 @@ public:
EventState OnKeyPress(WChar key, uint16 keycode) override EventState OnKeyPress(WChar key, uint16 keycode) override
{ {
if (keycode == WKC_ESC) { if (keycode == WKC_ESC) {
delete this; this->Close();
return ES_HANDLED; return ES_HANDLED;
} }

@ -384,17 +384,17 @@ struct GoalQuestionWindow : public Window {
switch (widget) { switch (widget) {
case WID_GQ_BUTTON_1: case WID_GQ_BUTTON_1:
DoCommandP(0, this->window_number, this->button[0], CMD_GOAL_QUESTION_ANSWER); DoCommandP(0, this->window_number, this->button[0], CMD_GOAL_QUESTION_ANSWER);
delete this; this->Close();
break; break;
case WID_GQ_BUTTON_2: case WID_GQ_BUTTON_2:
DoCommandP(0, this->window_number, this->button[1], CMD_GOAL_QUESTION_ANSWER); DoCommandP(0, this->window_number, this->button[1], CMD_GOAL_QUESTION_ANSWER);
delete this; this->Close();
break; break;
case WID_GQ_BUTTON_3: case WID_GQ_BUTTON_3:
DoCommandP(0, this->window_number, this->button[2], CMD_GOAL_QUESTION_ANSWER); DoCommandP(0, this->window_number, this->button[2], CMD_GOAL_QUESTION_ANSWER);
delete this; this->Close();
break; break;
} }
} }

@ -64,7 +64,7 @@ struct EndGameHighScoreBaseWindow : Window {
void OnClick(Point pt, int widget, int click_count) override void OnClick(Point pt, int widget, int click_count) override
{ {
delete this; this->Close();
} }
EventState OnKeyPress(WChar key, uint16 keycode) override EventState OnKeyPress(WChar key, uint16 keycode) override
@ -79,7 +79,7 @@ struct EndGameHighScoreBaseWindow : Window {
case WKC_RETURN: case WKC_RETURN:
case WKC_ESC: case WKC_ESC:
case WKC_SPACE: case WKC_SPACE:
delete this; this->Close();
return ES_HANDLED; return ES_HANDLED;
default: default:
@ -122,10 +122,11 @@ struct EndGameWindow : EndGameHighScoreBaseWindow {
MarkWholeScreenDirty(); MarkWholeScreenDirty();
} }
~EndGameWindow() void Close() override
{ {
if (!_networking) DoCommandP(0, PM_PAUSED_NORMAL, 0, CMD_PAUSE); // unpause if (!_networking) DoCommandP(0, PM_PAUSED_NORMAL, 0, CMD_PAUSE); // unpause
ShowHighscoreTable(this->window_number, this->rank); ShowHighscoreTable(this->window_number, this->rank);
this->EndGameHighScoreBaseWindow::Close();
} }
void OnPaint() override void OnPaint() override
@ -169,11 +170,13 @@ struct HighScoreWindow : EndGameHighScoreBaseWindow {
this->rank = ranking; this->rank = ranking;
} }
~HighScoreWindow() void Close() override
{ {
if (_game_mode != GM_MENU) ShowVitalWindows(); if (_game_mode != GM_MENU) ShowVitalWindows();
if (!_networking && !this->game_paused_by_player) DoCommandP(0, PM_PAUSED_NORMAL, 0, CMD_PAUSE); // unpause if (!_networking && !this->game_paused_by_player) DoCommandP(0, PM_PAUSED_NORMAL, 0, CMD_PAUSE); // unpause
this->EndGameHighScoreBaseWindow::Close();
} }
void OnPaint() override void OnPaint() override

@ -759,20 +759,20 @@ struct TooltipsWindow : public Window
{ {
/* Always close tooltips when the cursor is not in our window. */ /* Always close tooltips when the cursor is not in our window. */
if (!_cursor.in_window) { if (!_cursor.in_window) {
delete this; this->Close();
return; return;
} }
/* We can show tooltips while dragging tools. These are shown as long as /* We can show tooltips while dragging tools. These are shown as long as
* we are dragging the tool. Normal tooltips work with hover or rmb. */ * we are dragging the tool. Normal tooltips work with hover or rmb. */
switch (this->close_cond) { switch (this->close_cond) {
case TCC_RIGHT_CLICK: if (!_right_button_down) delete this; break; case TCC_RIGHT_CLICK: if (!_right_button_down) this->Close(); break;
case TCC_HOVER: if (!_mouse_hovering) delete this; break; case TCC_HOVER: if (!_mouse_hovering) this->Close(); break;
case TCC_NONE: break; case TCC_NONE: break;
case TCC_EXIT_VIEWPORT: { case TCC_EXIT_VIEWPORT: {
Window *w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y); Window *w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y);
if (w == nullptr || IsPtInWindowViewport(w, _cursor.pos.x, _cursor.pos.y) == nullptr) delete this; if (w == nullptr || IsPtInWindowViewport(w, _cursor.pos.x, _cursor.pos.y) == nullptr) this->Close();
break; break;
} }
} }
@ -1090,18 +1090,19 @@ struct QueryStringWindow : public Window
FALLTHROUGH; FALLTHROUGH;
case WID_QS_CANCEL: case WID_QS_CANCEL:
delete this; this->Close();
break; break;
} }
} }
~QueryStringWindow() void Close() override
{ {
if (!this->editbox.handled && this->parent != nullptr) { if (!this->editbox.handled && this->parent != nullptr) {
Window *parent = this->parent; Window *parent = this->parent;
this->parent = nullptr; // so parent doesn't try to delete us again this->parent = nullptr; // so parent doesn't try to close us again
parent->OnQueryTextFinished(nullptr); parent->OnQueryTextFinished(nullptr);
} }
this->Window::Close();
} }
}; };
@ -1167,9 +1168,10 @@ struct QueryWindow : public Window {
this->InitNested(WN_CONFIRM_POPUP_QUERY); this->InitNested(WN_CONFIRM_POPUP_QUERY);
} }
~QueryWindow() void Close() override
{ {
if (this->proc != nullptr) this->proc(this->parent, false); if (this->proc != nullptr) this->proc(this->parent, false);
this->Window::Close();
} }
void FindWindowPlacementAndResize(int def_width, int def_height) override void FindWindowPlacementAndResize(int def_width, int def_height) override
@ -1222,7 +1224,7 @@ struct QueryWindow : public Window {
Window *parent = this->parent; Window *parent = this->parent;
/* Prevent the destructor calling the callback function */ /* Prevent the destructor calling the callback function */
this->proc = nullptr; this->proc = nullptr;
delete this; this->Close();
if (proc != nullptr) { if (proc != nullptr) {
proc(parent, true); proc(parent, true);
proc = nullptr; proc = nullptr;
@ -1230,7 +1232,7 @@ struct QueryWindow : public Window {
break; break;
} }
case WID_Q_NO: case WID_Q_NO:
delete this; this->Close();
break; break;
} }
} }
@ -1248,7 +1250,7 @@ struct QueryWindow : public Window {
FALLTHROUGH; FALLTHROUGH;
case WKC_ESC: case WKC_ESC:
delete this; this->Close();
return ES_HANDLED; return ES_HANDLED;
} }
return ES_NOT_HANDLED; return ES_NOT_HANDLED;
@ -1289,13 +1291,13 @@ void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallback
{ {
if (parent == nullptr) parent = FindWindowById(WC_MAIN_WINDOW, 0); if (parent == nullptr) parent = FindWindowById(WC_MAIN_WINDOW, 0);
for (const Window *w : Window::Iterate()) { for (Window *w : Window::Iterate()) {
if (w->window_class != WC_CONFIRM_POPUP_QUERY) continue; if (w->window_class != WC_CONFIRM_POPUP_QUERY) continue;
const QueryWindow *qw = (const QueryWindow *)w; QueryWindow *qw = dynamic_cast<QueryWindow *>(w);
if (qw->parent != parent || qw->proc != callback) continue; if (qw->parent != parent || qw->proc != callback) continue;
delete qw; qw->Close();
break; break;
} }

@ -307,9 +307,10 @@ struct NetworkChatWindow : public Window {
PositionNetworkChatWindow(this); PositionNetworkChatWindow(this);
} }
~NetworkChatWindow() void Close() override
{ {
InvalidateWindowData(WC_NEWS_WINDOW, 0, 0); InvalidateWindowData(WC_NEWS_WINDOW, 0, 0);
this->Window::Close();
} }
void FindWindowPlacementAndResize(int def_width, int def_height) override void FindWindowPlacementAndResize(int def_width, int def_height) override
@ -470,7 +471,7 @@ struct NetworkChatWindow : public Window {
FALLTHROUGH; FALLTHROUGH;
case WID_NC_CLOSE: /* Cancel */ case WID_NC_CLOSE: /* Cancel */
delete this; this->Close();
break; break;
} }
} }
@ -497,7 +498,7 @@ struct NetworkChatWindow : public Window {
*/ */
void OnInvalidateData(int data = 0, bool gui_scope = true) override void OnInvalidateData(int data = 0, bool gui_scope = true) override
{ {
if (data == this->dest) delete this; if (data == this->dest) this->Close();
} }
}; };

@ -109,9 +109,10 @@ BaseNetworkContentDownloadStatusWindow::BaseNetworkContentDownloadStatusWindow(W
this->InitNested(WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD); this->InitNested(WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD);
} }
BaseNetworkContentDownloadStatusWindow::~BaseNetworkContentDownloadStatusWindow() void BaseNetworkContentDownloadStatusWindow::Close()
{ {
_network_content_client.RemoveCallback(this); _network_content_client.RemoveCallback(this);
this->Window::Close();
} }
void BaseNetworkContentDownloadStatusWindow::DrawWidget(const Rect &r, int widget) const void BaseNetworkContentDownloadStatusWindow::DrawWidget(const Rect &r, int widget) const
@ -171,8 +172,7 @@ public:
this->parent = FindWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_CONTENT_LIST); this->parent = FindWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_CONTENT_LIST);
} }
/** Free whatever we've allocated */ void Close() override
~NetworkContentDownloadStatusWindow()
{ {
TarScanner::Mode mode = TarScanner::NONE; TarScanner::Mode mode = TarScanner::NONE;
for (auto ctype : this->receivedTypes) { for (auto ctype : this->receivedTypes) {
@ -254,6 +254,8 @@ public:
/* Always invalidate the download window; tell it we are going to be gone */ /* Always invalidate the download window; tell it we are going to be gone */
InvalidateWindowData(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_CONTENT_LIST, 2); InvalidateWindowData(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_CONTENT_LIST, 2);
this->BaseNetworkContentDownloadStatusWindow::Close();
} }
void OnClick(Point pt, int widget, int click_count) override void OnClick(Point pt, int widget, int click_count) override
@ -261,7 +263,7 @@ public:
if (widget == WID_NCDS_CANCELOK) { if (widget == WID_NCDS_CANCELOK) {
if (this->downloaded_bytes != this->total_bytes) { if (this->downloaded_bytes != this->total_bytes) {
_network_content_client.CloseConnection(); _network_content_client.CloseConnection();
delete this; this->Close();
} else { } else {
/* If downloading succeeded, close the online content window. This will close /* If downloading succeeded, close the online content window. This will close
* the current window as well. */ * the current window as well. */
@ -549,10 +551,10 @@ public:
this->InvalidateData(); this->InvalidateData();
} }
/** Free everything we allocated */ void Close() override
~NetworkContentListWindow()
{ {
_network_content_client.RemoveCallback(this); _network_content_client.RemoveCallback(this);
this->Window::Close();
} }
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
@ -837,7 +839,7 @@ public:
break; break;
case WID_NCL_CANCEL: case WID_NCL_CANCEL:
delete this; this->Close();
break; break;
case WID_NCL_OPEN_URL: case WID_NCL_OPEN_URL:
@ -941,7 +943,7 @@ public:
{ {
if (!success) { if (!success) {
ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_CONNECT, INVALID_STRING_ID, WL_ERROR); ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_CONNECT, INVALID_STRING_ID, WL_ERROR);
delete this; this->Close();
return; return;
} }

@ -32,11 +32,7 @@ public:
*/ */
BaseNetworkContentDownloadStatusWindow(WindowDesc *desc); BaseNetworkContentDownloadStatusWindow(WindowDesc *desc);
/** void Close() override;
* Free everything associated with this window.
*/
~BaseNetworkContentDownloadStatusWindow();
void DrawWidget(const Rect &r, int widget) const override; void DrawWidget(const Rect &r, int widget) const override;
void OnDownloadProgress(const ContentInfo *ci, int bytes) override; void OnDownloadProgress(const ContentInfo *ci, int bytes) override;
}; };

@ -2597,7 +2597,7 @@ struct NetworkCompanyPasswordWindow : public Window {
FALLTHROUGH; FALLTHROUGH;
case WID_NCP_CANCEL: case WID_NCP_CANCEL:
delete this; this->Close();
break; break;
case WID_NCP_SAVE_AS_DEFAULT_PASSWORD: case WID_NCP_SAVE_AS_DEFAULT_PASSWORD:

@ -424,7 +424,7 @@ struct NewGRFParametersWindow : public Window {
break; break;
case WID_NP_ACCEPT: case WID_NP_ACCEPT:
delete this; this->Close();
break; break;
} }
} }
@ -662,7 +662,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback {
this->OnInvalidateData(GOID_NEWGRF_CURRENT_LOADED); this->OnInvalidateData(GOID_NEWGRF_CURRENT_LOADED);
} }
~NewGRFWindow() void Close() override
{ {
DeleteWindowByClass(WC_GRF_PARAMETERS); DeleteWindowByClass(WC_GRF_PARAMETERS);
DeleteWindowByClass(WC_TEXTFILE); DeleteWindowByClass(WC_TEXTFILE);
@ -674,6 +674,11 @@ struct NewGRFWindow : public Window, NewGRFScanCallback {
ReloadNewGRFData(); ReloadNewGRFData();
} }
this->Window::Close();
}
~NewGRFWindow()
{
/* Remove the temporary copy of grf-list used in window */ /* Remove the temporary copy of grf-list used in window */
ClearGRFConfigList(&this->actives); ClearGRFConfigList(&this->actives);
} }
@ -2121,13 +2126,13 @@ struct SavePresetWindow : public Window {
} }
case WID_SVP_CANCEL: case WID_SVP_CANCEL:
delete this; this->Close();
break; break;
case WID_SVP_SAVE: { case WID_SVP_SAVE: {
Window *w = FindWindowById(WC_GAME_OPTIONS, WN_GAME_OPTIONS_NEWGRF_STATE); Window *w = FindWindowById(WC_GAME_OPTIONS, WN_GAME_OPTIONS_NEWGRF_STATE);
if (w != nullptr && !StrEmpty(this->presetname_editbox.text.buf)) w->OnQueryTextFinished(this->presetname_editbox.text.buf); if (w != nullptr && !StrEmpty(this->presetname_editbox.text.buf)) w->OnQueryTextFinished(this->presetname_editbox.text.buf);
delete this; this->Close();
break; break;
} }
} }

@ -479,7 +479,7 @@ struct NewsWindow : Window {
switch (widget) { switch (widget) {
case WID_N_CLOSEBOX: case WID_N_CLOSEBOX:
NewsWindow::duration = 0; NewsWindow::duration = 0;
delete this; this->Close();
_forced_news = nullptr; _forced_news = nullptr;
break; break;
@ -1028,7 +1028,7 @@ static void ShowNewsMessage(const NewsItem *ni)
bool HideActiveNewsMessage() { bool HideActiveNewsMessage() {
NewsWindow *w = (NewsWindow*)FindWindowById(WC_NEWS_WINDOW, 0); NewsWindow *w = (NewsWindow*)FindWindowById(WC_NEWS_WINDOW, 0);
if (w == nullptr) return false; if (w == nullptr) return false;
delete w; w->Close();
return true; return true;
} }

@ -170,7 +170,7 @@ struct OskWindow : public Window {
return; return;
} }
} }
delete this; this->Close();
break; break;
case WID_OSK_CANCEL: case WID_OSK_CANCEL:
@ -182,7 +182,7 @@ struct OskWindow : public Window {
qs->text.Assign(this->orig_str_buf); qs->text.Assign(this->orig_str_buf);
qs->text.MovePos(WKC_END); qs->text.MovePos(WKC_END);
this->OnEditboxChanged(WID_OSK_TEXT); this->OnEditboxChanged(WID_OSK_TEXT);
delete this; this->Close();
} }
break; break;
} }
@ -205,7 +205,7 @@ struct OskWindow : public Window {
void OnFocusLost() override void OnFocusLost() override
{ {
VideoDriver::GetInstance()->EditBoxLostFocus(); VideoDriver::GetInstance()->EditBoxLostFocus();
delete this; this->Close();
} }
}; };

@ -434,10 +434,11 @@ struct BuildRailToolbarWindow : Window {
if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this); if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
} }
~BuildRailToolbarWindow() void Close() override
{ {
if (this->IsWidgetLowered(WID_RAT_BUILD_STATION)) SetViewportCatchmentStation(nullptr, true); if (this->IsWidgetLowered(WID_RAT_BUILD_STATION)) SetViewportCatchmentStation(nullptr, true);
if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
this->Window::Close();
} }
/** /**
@ -1028,9 +1029,10 @@ public:
this->InvalidateData(); this->InvalidateData();
} }
virtual ~BuildRailStationWindow() void Close() override
{ {
DeleteWindowById(WC_SELECT_STATION, 0); DeleteWindowById(WC_SELECT_STATION, 0);
this->PickerWindowBase::Close();
} }
/** Sort station classes by StationClassID. */ /** Sort station classes by StationClassID. */
@ -1695,9 +1697,10 @@ public:
this->OnInvalidateData(); this->OnInvalidateData();
} }
~BuildSignalWindow() void Close() override
{ {
_convert_signal_button = false; _convert_signal_button = false;
this->PickerWindowBase::Close();
} }
void OnInit() override void OnInit() override

@ -289,10 +289,11 @@ struct BuildRoadToolbarWindow : Window {
if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this); if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
} }
~BuildRoadToolbarWindow() void Close() override
{ {
if (_game_mode == GM_NORMAL && (this->IsWidgetLowered(WID_ROT_BUS_STATION) || this->IsWidgetLowered(WID_ROT_TRUCK_STATION))) SetViewportCatchmentStation(nullptr, true); if (_game_mode == GM_NORMAL && (this->IsWidgetLowered(WID_ROT_BUS_STATION) || this->IsWidgetLowered(WID_ROT_TRUCK_STATION))) SetViewportCatchmentStation(nullptr, true);
if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
this->Window::Close();
} }
/** /**
@ -1095,9 +1096,10 @@ struct BuildRoadStationWindow : public PickerWindowBase {
this->window_class = (rs == ROADSTOP_BUS) ? WC_BUS_STATION : WC_TRUCK_STATION; this->window_class = (rs == ROADSTOP_BUS) ? WC_BUS_STATION : WC_TRUCK_STATION;
} }
virtual ~BuildRoadStationWindow() void Close() override
{ {
DeleteWindowById(WC_SELECT_STATION, 0); DeleteWindowById(WC_SELECT_STATION, 0);
this->PickerWindowBase::Close();
} }
void OnPaint() override void OnPaint() override

@ -172,11 +172,12 @@ struct GameOptionsWindow : Window {
this->OnInvalidateData(0); this->OnInvalidateData(0);
} }
~GameOptionsWindow() void Close() override
{ {
DeleteWindowById(WC_CUSTOM_CURRENCY, 0); DeleteWindowById(WC_CUSTOM_CURRENCY, 0);
DeleteWindowByClass(WC_TEXTFILE); DeleteWindowByClass(WC_TEXTFILE);
if (this->reload) _switch_mode = SM_MENU; if (this->reload) _switch_mode = SM_MENU;
this->Window::Close();
} }
/** /**

@ -527,7 +527,7 @@ struct SignWindow : Window, SignList {
FALLTHROUGH; FALLTHROUGH;
case WID_QES_CANCEL: case WID_QES_CANCEL:
delete this; this->Close();
break; break;
} }
} }
@ -592,5 +592,5 @@ void DeleteRenameSignWindow(SignID sign)
{ {
SignWindow *w = dynamic_cast<SignWindow *>(FindWindowById(WC_QUERY_STRING, WN_QUERY_STRING_SIGN)); SignWindow *w = dynamic_cast<SignWindow *>(FindWindowById(WC_QUERY_STRING, WN_QUERY_STRING_SIGN));
if (w != nullptr && w->cur_sign == sign) delete w; if (w != nullptr && w->cur_sign == sign) w->Close();
} }

@ -1095,7 +1095,12 @@ SmallMapWindow::SmallMapWindow(WindowDesc *desc, int window_number) : Window(des
SmallMapWindow::~SmallMapWindow() SmallMapWindow::~SmallMapWindow()
{ {
delete this->overlay; delete this->overlay;
}
/* virtual */ void SmallMapWindow::Close()
{
this->BreakIndustryChainLink(); this->BreakIndustryChainLink();
this->Window::Close();
} }
/** /**

@ -178,6 +178,7 @@ public:
void SmallMapCenterOnCurrentPos(); void SmallMapCenterOnCurrentPos();
Point GetStationMiddle(const Station *st) const; Point GetStationMiddle(const Station *st) const;
void Close() override;
void SetStringParameters(int widget) const override; void SetStringParameters(int widget) const override;
void OnInit() override; void OnInit() override;
void OnPaint() override; void OnPaint() override;

@ -1334,7 +1334,7 @@ struct StationViewWindow : public Window {
this->owner = Station::Get(window_number)->owner; this->owner = Station::Get(window_number)->owner;
} }
~StationViewWindow() void Close() override
{ {
DeleteWindowById(WC_TRAINS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_TRAIN, this->owner, this->window_number).Pack(), false); DeleteWindowById(WC_TRAINS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_TRAIN, this->owner, this->window_number).Pack(), false);
DeleteWindowById(WC_ROADVEH_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_ROAD, this->owner, this->window_number).Pack(), false); DeleteWindowById(WC_ROADVEH_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_ROAD, this->owner, this->window_number).Pack(), false);
@ -1342,6 +1342,7 @@ struct StationViewWindow : public Window {
DeleteWindowById(WC_AIRCRAFT_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_AIRCRAFT, this->owner, this->window_number).Pack(), false); DeleteWindowById(WC_AIRCRAFT_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_AIRCRAFT, this->owner, this->window_number).Pack(), false);
SetViewportCatchmentStation(Station::Get(this->window_number), false); SetViewportCatchmentStation(Station::Get(this->window_number), false);
this->Window::Close();
} }
/** /**
@ -2285,11 +2286,12 @@ struct SelectStationWindow : Window {
_thd.freeze = true; _thd.freeze = true;
} }
~SelectStationWindow() void Close() override
{ {
if (_settings_client.gui.station_show_coverage) SetViewportCatchmentStation(nullptr, true); if (_settings_client.gui.station_show_coverage) SetViewportCatchmentStation(nullptr, true);
_thd.freeze = false; _thd.freeze = false;
this->Window::Close();
} }
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
@ -2424,7 +2426,7 @@ static bool StationJoinerNeeded(const CommandContainer &cmd, TileArea ta)
Window *selection_window = FindWindowById(WC_SELECT_STATION, 0); Window *selection_window = FindWindowById(WC_SELECT_STATION, 0);
if (selection_window != nullptr) { if (selection_window != nullptr) {
/* Abort current distant-join and start new one */ /* Abort current distant-join and start new one */
delete selection_window; selection_window->Close();
UpdateTileSelection(); UpdateTileSelection();
} }

@ -336,9 +336,10 @@ public:
this->SetWidgetDisabledState(WID_TV_CHANGE_NAME, _networking && !_network_server); this->SetWidgetDisabledState(WID_TV_CHANGE_NAME, _networking && !_network_server);
} }
~TownViewWindow() void Close() override
{ {
SetViewportCatchmentTown(Town::Get(this->window_number), false); SetViewportCatchmentTown(Town::Get(this->window_number), false);
this->Window::Close();
} }
void SetStringParameters(int widget) const override void SetStringParameters(int widget) const override

@ -1033,9 +1033,9 @@ struct RefitWindow : public Window {
if (this->order == INVALID_VEH_ORDER_ID) { if (this->order == INVALID_VEH_ORDER_ID) {
bool delete_window = this->selected_vehicle == v->index && this->num_vehicles == UINT8_MAX; bool delete_window = this->selected_vehicle == v->index && this->num_vehicles == UINT8_MAX;
if (DoCommandP(v->tile, this->selected_vehicle, this->cargo->cargo | this->cargo->subtype << 8 | this->num_vehicles << 16, GetCmdRefitVeh(v)) && delete_window) delete this; if (DoCommandP(v->tile, this->selected_vehicle, this->cargo->cargo | this->cargo->subtype << 8 | this->num_vehicles << 16, GetCmdRefitVeh(v)) && delete_window) this->Close();
} else { } else {
if (DoCommandP(v->tile, v->index, this->cargo->cargo | this->order << 16, CMD_ORDER_REFIT)) delete this; if (DoCommandP(v->tile, v->index, this->cargo->cargo | this->order << 16, CMD_ORDER_REFIT)) this->Close();
} }
} }
break; break;
@ -2718,12 +2718,13 @@ public:
this->UpdateButtonStatus(); this->UpdateButtonStatus();
} }
~VehicleViewWindow() void Close() override
{ {
DeleteWindowById(WC_VEHICLE_ORDERS, this->window_number, false); DeleteWindowById(WC_VEHICLE_ORDERS, this->window_number, false);
DeleteWindowById(WC_VEHICLE_REFIT, this->window_number, false); DeleteWindowById(WC_VEHICLE_REFIT, this->window_number, false);
DeleteWindowById(WC_VEHICLE_DETAILS, this->window_number, false); DeleteWindowById(WC_VEHICLE_DETAILS, this->window_number, false);
DeleteWindowById(WC_VEHICLE_TIMETABLE, this->window_number, false); DeleteWindowById(WC_VEHICLE_TIMETABLE, this->window_number, false);
this->Window::Close();
} }
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override

@ -74,9 +74,10 @@ public:
this->OnInvalidateData(0); this->OnInvalidateData(0);
} }
~WaypointWindow() void Close() override
{ {
DeleteWindowById(GetWindowClassForVehicleType(this->vt), VehicleListIdentifier(VL_STATION_LIST, this->vt, this->owner, this->window_number).Pack(), false); DeleteWindowById(GetWindowClassForVehicleType(this->vt), VehicleListIdentifier(VL_STATION_LIST, this->vt, this->owner, this->window_number).Pack(), false);
this->Window::Close();
} }
void SetStringParameters(int widget) const override void SetStringParameters(int widget) const override

@ -184,12 +184,11 @@ struct DropdownWindow : Window {
this->scrolling_timer = GUITimer(MILLISECONDS_PER_TICK); this->scrolling_timer = GUITimer(MILLISECONDS_PER_TICK);
} }
~DropdownWindow() void Close() override
{ {
/* Make the dropdown "invisible", so it doesn't affect new window placement. /* Finish closing the dropdown, so it doesn't affect new window placement.
* Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */ * Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */
*this->z_position = nullptr; this->Window::Close();
this->SetDirty();
Window *w2 = FindWindowById(this->parent_wnd_class, this->parent_wnd_num); Window *w2 = FindWindowById(this->parent_wnd_class, this->parent_wnd_num);
if (w2 != nullptr) { if (w2 != nullptr) {
@ -200,7 +199,7 @@ struct DropdownWindow : Window {
} }
} }
virtual Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) override
{ {
return this->position; return this->position;
} }
@ -237,7 +236,7 @@ struct DropdownWindow : Window {
return false; return false;
} }
virtual void DrawWidget(const Rect &r, int widget) const void DrawWidget(const Rect &r, int widget) const override
{ {
if (widget != WID_DM_ITEMS) return; if (widget != WID_DM_ITEMS) return;
@ -265,7 +264,7 @@ struct DropdownWindow : Window {
} }
} }
virtual void OnClick(Point pt, int widget, int click_count) void OnClick(Point pt, int widget, int click_count) override
{ {
if (widget != WID_DM_ITEMS) return; if (widget != WID_DM_ITEMS) return;
int item; int item;
@ -276,7 +275,7 @@ struct DropdownWindow : Window {
} }
} }
virtual void OnRealtimeTick(uint delta_ms) void OnRealtimeTick(uint delta_ms) override
{ {
if (!this->scrolling_timer.Elapsed(delta_ms)) return; if (!this->scrolling_timer.Elapsed(delta_ms)) return;
this->scrolling_timer.SetInterval(MILLISECONDS_PER_TICK); this->scrolling_timer.SetInterval(MILLISECONDS_PER_TICK);
@ -293,22 +292,19 @@ struct DropdownWindow : Window {
} }
} }
virtual void OnMouseLoop() void OnMouseLoop() override
{ {
Window *w2 = FindWindowById(this->parent_wnd_class, this->parent_wnd_num); Window *w2 = FindWindowById(this->parent_wnd_class, this->parent_wnd_num);
if (w2 == nullptr) { if (w2 == nullptr) {
delete this; this->Close();
return; return;
} }
if (this->click_delay != 0 && --this->click_delay == 0) { if (this->click_delay != 0 && --this->click_delay == 0) {
/* Make the dropdown "invisible", so it doesn't affect new window placement. /* Close the dropdown, so it doesn't affect new window placement.
* Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */ * Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */
*this->z_position = nullptr; this->Close();
this->SetDirty();
w2->OnDropdownSelect(this->parent_button, this->selected_index); w2->OnDropdownSelect(this->parent_button, this->selected_index);
delete this;
return; return;
} }
@ -318,7 +314,7 @@ struct DropdownWindow : Window {
if (!_left_button_clicked) { if (!_left_button_clicked) {
this->drag_mode = false; this->drag_mode = false;
if (!this->GetDropDownItem(item)) { if (!this->GetDropDownItem(item)) {
if (this->instant_close) delete this; if (this->instant_close) this->Close();
return; return;
} }
this->click_delay = 2; this->click_delay = 2;
@ -509,7 +505,7 @@ int HideDropDownMenu(Window *pw)
if (pw->window_class == dw->parent_wnd_class && if (pw->window_class == dw->parent_wnd_class &&
pw->window_number == dw->parent_wnd_num) { pw->window_number == dw->parent_wnd_num) {
int parent_button = dw->parent_button; int parent_button = dw->parent_button;
delete dw; dw->Close();
return parent_button; return parent_button;
} }
} }

@ -56,6 +56,21 @@ static Window *_last_scroll_window = nullptr; ///< Window of the last scroll eve
/** List of windows opened at the screen sorted from the front to back. */ /** List of windows opened at the screen sorted from the front to back. */
WindowList _z_windows; WindowList _z_windows;
/** List of closed windows to delete. */
/* static */ std::vector<Window *> Window::closed_windows;
/**
* Delete all closed windows.
*/
/* static */ void Window::DeleteClosedWindows()
{
for (Window *w : Window::closed_windows) delete w;
Window::closed_windows.clear();
/* Remove dead entries from the window list */
_z_windows.remove(nullptr);
}
/** If false, highlight is white, otherwise the by the widget defined colour. */ /** If false, highlight is white, otherwise the by the widget defined colour. */
bool _window_highlight_colour = false; bool _window_highlight_colour = false;
@ -705,7 +720,7 @@ static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count)
} }
case WWT_CLOSEBOX: // 'X' case WWT_CLOSEBOX: // 'X'
delete w; w->Close();
return; return;
case WWT_CAPTION: // 'Title bar' case WWT_CAPTION: // 'Title bar'
@ -793,7 +808,7 @@ static void DispatchRightClickEvent(Window *w, int x, int y)
/* Right-click close is enabled and there is a closebox */ /* Right-click close is enabled and there is a closebox */
if (_settings_client.gui.right_mouse_wnd_close && w->nested_root->GetWidgetOfType(WWT_CLOSEBOX)) { if (_settings_client.gui.right_mouse_wnd_close && w->nested_root->GetWidgetOfType(WWT_CLOSEBOX)) {
delete w; w->Close();
} else if (_settings_client.gui.hover_delay_ms == 0 && !w->OnTooltip(pt, wid->index, TCC_RIGHT_CLICK) && wid->tool_tip != 0) { } else if (_settings_client.gui.hover_delay_ms == 0 && !w->OnTooltip(pt, wid->index, TCC_RIGHT_CLICK) && wid->tool_tip != 0) {
GuiShowTooltips(w, wid->tool_tip, 0, nullptr, TCC_RIGHT_CLICK); GuiShowTooltips(w, wid->tool_tip, 0, nullptr, TCC_RIGHT_CLICK);
} }
@ -1068,16 +1083,21 @@ void Window::DeleteChildWindows(WindowClass wc) const
{ {
Window *child = FindChildWindow(this, wc); Window *child = FindChildWindow(this, wc);
while (child != nullptr) { while (child != nullptr) {
delete child; child->Close();
child = FindChildWindow(this, wc); child = FindChildWindow(this, wc);
} }
} }
/** /**
* Remove window and all its child windows from the window stack. * Hide the window and all its child windows, and mark them for a later deletion.
*/ */
Window::~Window() void Window::Close()
{ {
/* Don't close twice. */
if (*this->z_position == nullptr) return;
*this->z_position = nullptr;
if (_thd.window_class == this->window_class && if (_thd.window_class == this->window_class &&
_thd.window_number == this->window_number) { _thd.window_number == this->window_number) {
ResetObjectToPlace(); ResetObjectToPlace();
@ -1094,21 +1114,29 @@ Window::~Window()
/* Make sure we don't try to access this window as the focused window when it doesn't exist anymore. */ /* Make sure we don't try to access this window as the focused window when it doesn't exist anymore. */
if (_focused_window == this) { if (_focused_window == this) {
/* Virtual functions get called statically in destructors, so make it explicit to remove any confusion. */ this->OnFocusLost();
this->Window::OnFocusLost();
_focused_window = nullptr; _focused_window = nullptr;
} }
this->DeleteChildWindows(); this->DeleteChildWindows();
if (this->viewport != nullptr) DeleteWindowViewport(this);
this->SetDirty(); this->SetDirty();
Window::closed_windows.push_back(this);
}
/**
* Remove window and all its child windows from the window stack.
*/
Window::~Window()
{
/* Make sure the window is closed, deletion is allowed only in Window::DeleteClosedWindows(). */
assert(*this->z_position == nullptr);
if (this->viewport != nullptr) DeleteWindowViewport(this);
free(this->nested_array); // Contents is released through deletion of #nested_root. free(this->nested_array); // Contents is released through deletion of #nested_root.
delete this->nested_root; delete this->nested_root;
*this->z_position = nullptr;
} }
/** /**
@ -1151,7 +1179,7 @@ void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
{ {
Window *w = FindWindowById(cls, number); Window *w = FindWindowById(cls, number);
if (w != nullptr && (force || (w->flags & WF_STICKY) == 0)) { if (w != nullptr && (force || (w->flags & WF_STICKY) == 0)) {
delete w; w->Close();
} }
} }
@ -1164,7 +1192,7 @@ void DeleteWindowByClass(WindowClass cls)
/* Note: the container remains stable, even when deleting windows. */ /* Note: the container remains stable, even when deleting windows. */
for (Window *w : Window::Iterate()) { for (Window *w : Window::Iterate()) {
if (w->window_class == cls) { if (w->window_class == cls) {
delete w; w->Close();
} }
} }
} }
@ -1180,7 +1208,7 @@ void DeleteCompanyWindows(CompanyID id)
/* Note: the container remains stable, even when deleting windows. */ /* Note: the container remains stable, even when deleting windows. */
for (Window *w : Window::Iterate()) { for (Window *w : Window::Iterate()) {
if (w->owner == id) { if (w->owner == id) {
delete w; w->Close();
} }
} }
@ -1818,9 +1846,11 @@ void UnInitWindowSystem()
{ {
UnshowCriticalError(); UnshowCriticalError();
for (Window *w : Window::Iterate()) delete w; for (Window *w : Window::Iterate()) w->Close();
_z_windows.clear(); Window::DeleteClosedWindows();
assert(_z_windows.empty());
} }
/** /**
@ -2968,7 +2998,7 @@ static void CheckSoftLimit()
if (deletable_count <= _settings_client.gui.window_soft_limit) break; if (deletable_count <= _settings_client.gui.window_soft_limit) break;
assert(last_deletable != nullptr); assert(last_deletable != nullptr);
delete last_deletable; last_deletable->Close();
} }
} }
@ -2983,14 +3013,8 @@ void InputLoop()
CheckSoftLimit(); CheckSoftLimit();
/* Remove dead entries from the window list */ /* Process scheduled window deletion. */
for (auto it = _z_windows.begin(); it != _z_windows.end(); ) { Window::DeleteClosedWindows();
if (*it == nullptr) {
it = _z_windows.erase(it);
} else {
++it;
}
}
if (_input_events_this_tick != 0) { if (_input_events_this_tick != 0) {
/* The input loop is called only once per GameLoop() - so we can clear the counter here */ /* The input loop is called only once per GameLoop() - so we can clear the counter here */
@ -3237,7 +3261,7 @@ void CallWindowGameTickEvent()
void DeleteNonVitalWindows() void DeleteNonVitalWindows()
{ {
/* Note: the container remains stable, even when deleting windows. */ /* Note: the container remains stable, even when deleting windows. */
for (const Window *w : Window::Iterate()) { for (Window *w : Window::Iterate()) {
if (w->window_class != WC_MAIN_WINDOW && if (w->window_class != WC_MAIN_WINDOW &&
w->window_class != WC_SELECT_GAME && w->window_class != WC_SELECT_GAME &&
w->window_class != WC_MAIN_TOOLBAR && w->window_class != WC_MAIN_TOOLBAR &&
@ -3245,7 +3269,7 @@ void DeleteNonVitalWindows()
w->window_class != WC_TOOLTIPS && w->window_class != WC_TOOLTIPS &&
(w->flags & WF_STICKY) == 0) { // do not delete windows which are 'pinned' (w->flags & WF_STICKY) == 0) { // do not delete windows which are 'pinned'
delete w; w->Close();
} }
} }
} }
@ -3263,9 +3287,9 @@ void DeleteAllNonVitalWindows()
DeleteNonVitalWindows(); DeleteNonVitalWindows();
/* Note: the container remains stable, even when deleting windows. */ /* Note: the container remains stable, even when deleting windows. */
for (const Window *w : Window::Iterate()) { for (Window *w : Window::Iterate()) {
if (w->flags & WF_STICKY) { if (w->flags & WF_STICKY) {
delete w; w->Close();
} }
} }
} }
@ -3288,9 +3312,9 @@ void DeleteAllMessages()
void DeleteConstructionWindows() void DeleteConstructionWindows()
{ {
/* Note: the container remains stable, even when deleting windows. */ /* Note: the container remains stable, even when deleting windows. */
for (const Window *w : Window::Iterate()) { for (Window *w : Window::Iterate()) {
if (w->window_desc->flags & WDF_CONSTRUCTION) { if (w->window_desc->flags & WDF_CONSTRUCTION) {
delete w; w->Close();
} }
} }
@ -3483,12 +3507,11 @@ void RelocateAllWindows(int neww, int newh)
} }
/** /**
* Destructor of the base class PickerWindowBase * Hide the window and all its child windows, and mark them for a later deletion.
* Main utility is to stop the base Window destructor from triggering * Always call ResetObjectToPlace() when closing a PickerWindow.
* a free while the child will already be free, in this case by the ResetObjectToPlace().
*/ */
PickerWindowBase::~PickerWindowBase() void PickerWindowBase::Close()
{ {
*this->z_position = nullptr; // stop the ancestor from freeing the already (to be) child
ResetObjectToPlace(); ResetObjectToPlace();
this->Window::Close();
} }

@ -277,6 +277,9 @@ enum TooltipCloseCondition {
* Data structure for an opened window * Data structure for an opened window
*/ */
struct Window : ZeroedMemoryAllocator { struct Window : ZeroedMemoryAllocator {
private:
static std::vector<Window *> closed_windows;
protected: protected:
void InitializeData(WindowNumber window_number); void InitializeData(WindowNumber window_number);
void InitializePositionSize(int x, int y, int min_width, int min_height); void InitializePositionSize(int x, int y, int min_width, int min_height);
@ -284,11 +287,12 @@ protected:
std::vector<int> scheduled_invalidation_data; ///< Data of scheduled OnInvalidateData() calls. std::vector<int> scheduled_invalidation_data; ///< Data of scheduled OnInvalidateData() calls.
/* Protected to prevent deletion anywhere outside Window::DeleteClosedWindows(). */
virtual ~Window();
public: public:
Window(WindowDesc *desc); Window(WindowDesc *desc);
virtual ~Window();
/** /**
* Helper allocation function to disallow something. * Helper allocation function to disallow something.
* Don't allow arrays; arrays of Windows are pointless as you need * Don't allow arrays; arrays of Windows are pointless as you need
@ -506,6 +510,8 @@ public:
static int SortButtonWidth(); static int SortButtonWidth();
void DeleteChildWindows(WindowClass wc = WC_INVALID) const; void DeleteChildWindows(WindowClass wc = WC_INVALID) const;
virtual void Close();
static void DeleteClosedWindows();
void SetDirty() const; void SetDirty() const;
void ReInit(int rx = 0, int ry = 0); void ReInit(int rx = 0, int ry = 0);
@ -916,7 +922,7 @@ public:
this->parent = parent; this->parent = parent;
} }
virtual ~PickerWindowBase(); void Close() override;
}; };
Window *BringWindowToFrontById(WindowClass cls, WindowNumber number); Window *BringWindowToFrontById(WindowClass cls, WindowNumber number);

Loading…
Cancel
Save