diff --git a/src/ai/ai_gui.cpp b/src/ai/ai_gui.cpp index d991a78724..524914c3d0 100644 --- a/src/ai/ai_gui.cpp +++ b/src/ai/ai_gui.cpp @@ -98,10 +98,11 @@ struct AIConfigWindow : public Window { this->OnInvalidateData(0); } - ~AIConfigWindow() + void Close() override { CloseWindowByClass(WC_SCRIPT_LIST); CloseWindowByClass(WC_SCRIPT_SETTINGS); + this->Window::Close(); } void SetStringParameters(int widget) const override @@ -247,7 +248,7 @@ struct AIConfigWindow : public Window { break; case WID_AIC_CLOSE: - delete this; + this->Close(); break; case WID_AIC_CONTENT_DOWNLOAD: diff --git a/src/airport_gui.cpp b/src/airport_gui.cpp index 441797b8d9..660066f800 100644 --- a/src/airport_gui.cpp +++ b/src/airport_gui.cpp @@ -78,10 +78,11 @@ struct BuildAirToolbarWindow : Window { this->last_user_action = WIDGET_LIST_END; } - ~BuildAirToolbarWindow() + void Close() override { if (this->IsWidgetLowered(WID_AT_AIRPORT)) SetViewportCatchmentStation(nullptr, true); if (_settings_client.gui.link_terraform_toolbar) CloseWindowById(WC_SCEN_LAND_GEN, 0, false); + this->Window::Close(); } /** @@ -278,9 +279,10 @@ public: if (selectFirstAirport) this->SelectFirstAvailableAirport(true); } - virtual ~BuildAirportWindow() + void Close() override { CloseWindowById(WC_SELECT_STATION, 0); + this->PickerWindowBase::Close(); } void SetStringParameters(int widget) const override diff --git a/src/bootstrap_gui.cpp b/src/bootstrap_gui.cpp index 43f69642cb..d8f5b8703a 100644 --- a/src/bootstrap_gui.cpp +++ b/src/bootstrap_gui.cpp @@ -91,9 +91,10 @@ public: this->InitNested(1); } - ~BootstrapErrorWindow() + void Close() override { _exit_game = true; + this->Window::Close(); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override @@ -148,12 +149,13 @@ public: { } - ~BootstrapContentDownloadStatusWindow() + void Close() override { /* If we are not set to exit the game, it means the bootstrap failed. */ if (!_exit_game) { new BootstrapErrorWindow(); } + this->BaseNetworkContentDownloadStatusWindow::Close(); } void OnDownloadComplete(ContentID cid) override @@ -166,7 +168,7 @@ public: /* _exit_game is used to break out of the outer video driver's MainLoop. */ _exit_game = true; - delete this; + this->Close(); } }; @@ -205,9 +207,10 @@ public: } /** Stop listening to the content client events. */ - ~BootstrapAskForDownloadWindow() + void Close() override { _network_content_client.RemoveCallback(this); + this->Window::Close(); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override @@ -268,7 +271,7 @@ public: /* And once the meta data is received, start downloading it. */ _network_content_client.Select(ci->id); new BootstrapContentDownloadStatusWindow(); - delete this; + this->Close(); } }; diff --git a/src/bridge_gui.cpp b/src/bridge_gui.cpp index 3f7c6837aa..df03fa186f 100644 --- a/src/bridge_gui.cpp +++ b/src/bridge_gui.cpp @@ -185,11 +185,15 @@ public: ~BuildBridgeWindow() { - this->last_sorting = this->bridges->GetListing(); - delete bridges; } + void Close() override + { + this->last_sorting = this->bridges->GetListing(); + this->Window::Close(); + } + void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override { switch (widget) { @@ -266,7 +270,7 @@ public: if (i < 9 && i < this->bridges->size()) { /* Build the requested bridge */ this->BuildBridge(i); - delete this; + this->Close(); return ES_HANDLED; } return ES_NOT_HANDLED; @@ -280,7 +284,7 @@ public: auto it = this->vscroll->GetScrolledItemFromWidget(*this->bridges, pt.y, this, WID_BBS_BRIDGE_LIST); if (it != this->bridges->end()) { this->BuildBridge(it - this->bridges->begin()); - delete this; + this->Close(); } break; } diff --git a/src/company_gui.cpp b/src/company_gui.cpp index 43dcce1a9d..b612c87c59 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -1689,7 +1689,7 @@ public: /* Cancel button */ case WID_SCMF_CANCEL: - delete this; + this->Close(); break; /* Load button */ @@ -2895,12 +2895,13 @@ struct BuyCompanyWindow : Window { this->company_value = hostile_takeover ? CalculateHostileTakeoverValue(c) : c->bankrupt_value; } - ~BuyCompanyWindow() + void Close() override { const Company *c = Company::GetIfValid((CompanyID)this->window_number); if (!this->hostile_takeover && c != nullptr && HasBit(c->bankrupt_asked, this->owner) && _current_company == this->owner) { EnqueueDoCommandP(NewCommandContainerBasic(0, this->window_number, 0, CMD_DECLINE_BUY_COMPANY | CMD_NO_SHIFT_ESTIMATE)); } + this->Window::Close(); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override @@ -2952,7 +2953,7 @@ struct BuyCompanyWindow : Window { { switch (widget) { case WID_BC_NO: - delete this; + this->Close(); break; case WID_BC_YES: diff --git a/src/console_gui.cpp b/src/console_gui.cpp index 7c41fc9bdd..46370e688d 100644 --- a/src/console_gui.cpp +++ b/src/console_gui.cpp @@ -133,10 +133,11 @@ struct IConsoleWindow : Window this->line_offset = GetStringBoundingBox("] ").width + WidgetDimensions::scaled.frametext.left; } - ~IConsoleWindow() + void Close() override { _iconsole_mode = ICONSOLE_CLOSED; VideoDriver::GetInstance()->EditBoxLostFocus(); + this->Window::Close(); } /** @@ -345,7 +346,7 @@ struct IConsoleWindow : Window VideoDriver::GetInstance()->EditBoxGainedFocus(); } - void OnFocusLost(Window *newly_focused_window) override + void OnFocusLost(bool closing, Window *newly_focused_window) override { VideoDriver::GetInstance()->EditBoxLostFocus(); } diff --git a/src/date_gui.cpp b/src/date_gui.cpp index 3a1f5b3c57..b1abda28cf 100644 --- a/src/date_gui.cpp +++ b/src/date_gui.cpp @@ -155,7 +155,7 @@ struct SetDateWindow : Window { if (this->callback != nullptr) { this->callback(this, DateToScaledDateTicks(ConvertYMDToDate(this->date.year, this->date.month, this->date.day))); } - delete this; + this->Close(); break; } } @@ -271,7 +271,7 @@ struct SetMinutesWindow : SetDateWindow if (this->callback != nullptr) { this->callback(this, ((DateTicks)minutes - _settings_time.clock_offset) * (DateTicksScaled)_settings_time.ticks_per_minute); } - delete this; + this->Close(); break; } } diff --git a/src/departures_gui.cpp b/src/departures_gui.cpp index 0308f4201c..65513c7fa4 100644 --- a/src/departures_gui.cpp +++ b/src/departures_gui.cpp @@ -289,7 +289,7 @@ public: virtual ~DeparturesWindow() { - this->DeleteDeparturesList(departures); + this->DeleteDeparturesList(this->departures); this->DeleteDeparturesList(this->arrivals); } diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp index 3c3245d9a2..762260d03d 100644 --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -296,11 +296,12 @@ struct DepotWindow : Window { OrderBackup::Reset(); } - ~DepotWindow() + void Close() override { CloseWindowById(WC_BUILD_VEHICLE, this->window_number); CloseWindowById(GetWindowClassForVehicleType(this->type), VehicleListIdentifier(VL_DEPOT_LIST, this->type, this->owner, this->GetDepotIndex()).Pack(), false); OrderBackup::Reset(this->window_number); + this->Window::Close(); } /** diff --git a/src/dock_gui.cpp b/src/dock_gui.cpp index 93eaf13660..35ee366d7a 100644 --- a/src/dock_gui.cpp +++ b/src/dock_gui.cpp @@ -106,10 +106,11 @@ struct BuildDocksToolbarWindow : Window { 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 (_settings_client.gui.link_terraform_toolbar) CloseWindowById(WC_SCEN_LAND_GEN, 0, false); + this->Window::Close(); } /** @@ -425,9 +426,10 @@ public: this->LowerWidget(_settings_client.gui.station_show_coverage + BDSW_LT_OFF); } - virtual ~BuildDocksStationWindow() + void Close() override { CloseWindowById(WC_SELECT_STATION, 0); + this->PickerWindowBase::Close(); } void OnPaint() override diff --git a/src/engine_gui.cpp b/src/engine_gui.cpp index afa3b4c978..39ddf69a46 100644 --- a/src/engine_gui.cpp +++ b/src/engine_gui.cpp @@ -128,7 +128,7 @@ struct EnginePreviewWindow : Window { DoCommandP(0, this->window_number, 0, CMD_WANT_ENGINE_PREVIEW); FALLTHROUGH; case WID_EP_NO: - if (!_shift_pressed) delete this; + if (!_shift_pressed) this->Close(); break; } } @@ -138,7 +138,7 @@ struct EnginePreviewWindow : Window { if (!gui_scope) return; 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(); } }; diff --git a/src/error_gui.cpp b/src/error_gui.cpp index 7e9fb405b4..b32c07b29d 100644 --- a/src/error_gui.cpp +++ b/src/error_gui.cpp @@ -262,7 +262,7 @@ public: 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 (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 @@ -316,20 +316,21 @@ public: void OnMouseLoop() override { /* 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 { if (this->display_timer.CountElapsed(delta_ms) == 0) return; - delete this; + this->Close(); } - ~ErrmsgWindow() + void Close() override { SetRedErrorSquare(INVALID_TILE); if (_window_system_initialized) ShowFirstError(); + this->Window::Close(); } /** @@ -372,7 +373,7 @@ void UnshowCriticalError() if (_window_system_initialized && w != nullptr) { if (w->IsCritical()) _error_list.push_front(*w); _window_system_initialized = false; - delete w; + w->Close(); } } @@ -426,18 +427,20 @@ void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel data.CopyOutDParams(); ErrmsgWindow *w = (ErrmsgWindow*)FindWindowById(WC_ERRMSG, 0); - if (w != nullptr && w->IsCritical()) { - /* A critical error is currently shown. */ - if (wl == WL_CRITICAL) { - /* Push another critical error in the queue of errors, - * but do not put other errors in the queue. */ - _error_list.push_back(data); + if (w != nullptr) { + if (w->IsCritical()) { + /* A critical error is currently shown. */ + if (wl == WL_CRITICAL) { + /* Push another critical error in the queue of errors, + * but do not put other errors in the queue. */ + _error_list.push_back(data); + } + return; } - } else { - /* Nothing or a non-critical error was shown. */ - delete w; - new ErrmsgWindow(data); + /* A non-critical error was shown. */ + w->Close(); } + new ErrmsgWindow(data); } @@ -448,7 +451,7 @@ void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel bool HideActiveErrorMessage() { ErrmsgWindow *w = (ErrmsgWindow*)FindWindowById(WC_ERRMSG, 0); if (w == nullptr) return false; - delete w; + w->Close(); return true; } diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp index d2cc0f2c75..df8290239a 100644 --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -408,12 +408,13 @@ public: } } - virtual ~SaveLoadWindow() + void Close() override { /* pause is only used in single-player, non-editor mode, non menu mode */ if (!_networking && _game_mode != GM_EDITOR && _game_mode != GM_MENU) { DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE); } + this->Window::Close(); } void DrawWidget(const Rect &r, int widget) const override @@ -641,12 +642,12 @@ public: _file_to_saveload.Set(*this->selected); if (this->abstract_filetype == FT_HEIGHTMAP) { - delete this; + this->Close(); ShowHeightmapLoad(); } 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; ClearErrorMessages(); - delete this; + this->Close(); } break; } @@ -704,7 +705,7 @@ public: assert(this->abstract_filetype == FT_HEIGHTMAP); _file_to_saveload.Set(*file); - delete this; + this->Close(); ShowHeightmapLoad(); } } @@ -757,7 +758,7 @@ public: EventState OnKeyPress(WChar key, uint16 keycode) override { if (keycode == WKC_ESC) { - delete this; + this->Close(); return ES_HANDLED; } diff --git a/src/game/game_gui.cpp b/src/game/game_gui.cpp index 34f4e4550b..e60658487c 100644 --- a/src/game/game_gui.cpp +++ b/src/game/game_gui.cpp @@ -111,10 +111,11 @@ struct GSConfigWindow : public Window { this->RebuildVisibleSettings(); } - ~GSConfigWindow() + void Close() override { HideDropDownMenu(this); CloseWindowByClass(WC_SCRIPT_LIST); + this->Window::Close(); } /** @@ -354,7 +355,7 @@ struct GSConfigWindow : public Window { } case WID_GSC_ACCEPT: - delete this; + this->Close(); break; case WID_GSC_RESET: diff --git a/src/goal_gui.cpp b/src/goal_gui.cpp index 72eaf3aab1..6b5842fa1e 100644 --- a/src/goal_gui.cpp +++ b/src/goal_gui.cpp @@ -375,17 +375,17 @@ struct GoalQuestionWindow : public Window { switch (widget) { case WID_GQ_BUTTON_1: DoCommandP(0, this->window_number, this->button[0], CMD_GOAL_QUESTION_ANSWER); - delete this; + this->Close(); break; case WID_GQ_BUTTON_2: DoCommandP(0, this->window_number, this->button[1], CMD_GOAL_QUESTION_ANSWER); - delete this; + this->Close(); break; case WID_GQ_BUTTON_3: DoCommandP(0, this->window_number, this->button[2], CMD_GOAL_QUESTION_ANSWER); - delete this; + this->Close(); break; } } diff --git a/src/group_gui.cpp b/src/group_gui.cpp index a74bc6faca..20a4c45e12 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -447,9 +447,10 @@ public: this->owner = vli.company; } - ~VehicleGroupWindow() + void Close() override { *this->sorting = this->vehgroups.GetListing(); + this->Window::Close(); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override diff --git a/src/highscore_gui.cpp b/src/highscore_gui.cpp index a63d32e761..24084ceaef 100644 --- a/src/highscore_gui.cpp +++ b/src/highscore_gui.cpp @@ -64,7 +64,7 @@ struct EndGameHighScoreBaseWindow : Window { void OnClick(Point pt, int widget, int click_count) override { - delete this; + this->Close(); } EventState OnKeyPress(WChar key, uint16 keycode) override @@ -79,7 +79,7 @@ struct EndGameHighScoreBaseWindow : Window { case WKC_RETURN: case WKC_ESC: case WKC_SPACE: - delete this; + this->Close(); return ES_HANDLED; default: @@ -122,10 +122,11 @@ struct EndGameWindow : EndGameHighScoreBaseWindow { MarkWholeScreenDirty(); } - ~EndGameWindow() + void Close() override { if (!_networking) DoCommandP(0, PM_PAUSED_NORMAL, 0, CMD_PAUSE); // unpause if (_game_mode != GM_MENU) ShowHighscoreTable(this->window_number, this->rank); + this->EndGameHighScoreBaseWindow::Close(); } void OnPaint() override @@ -169,11 +170,13 @@ struct HighScoreWindow : EndGameHighScoreBaseWindow { this->rank = ranking; } - ~HighScoreWindow() + void Close() override { if (_game_mode != GM_MENU) ShowVitalWindows(); if (!_networking && !this->game_paused_by_player) DoCommandP(0, PM_PAUSED_NORMAL, 0, CMD_PAUSE); // unpause + + this->EndGameHighScoreBaseWindow::Close(); } void OnPaint() override diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index f4535fde09..7c18eb62f2 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -1638,9 +1638,10 @@ public: this->industry_editbox.cancel_button = QueryString::ACTION_CLEAR; } - ~IndustryDirectoryWindow() + void Close() override { this->last_sorting = this->industries.GetListing(); + this->Window::Close(); } void OnInit() override diff --git a/src/linkgraph/linkgraph_gui.cpp b/src/linkgraph/linkgraph_gui.cpp index cfccf7214f..ad668b0cee 100644 --- a/src/linkgraph/linkgraph_gui.cpp +++ b/src/linkgraph/linkgraph_gui.cpp @@ -903,7 +903,7 @@ void LinkGraphLegendWindow::OnClick(Point pt, int widget, int click_count) void LinkGraphLegendWindow::OnInvalidateData(int data, bool gui_scope) { if (this->num_cargo != _sorted_cargo_specs.size()) { - delete this; + this->Close(); return; } diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 1aa8a838b3..06c6eae7a9 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -799,15 +799,15 @@ struct TooltipsWindow : public Window { /* Always close tooltips when the cursor is not in our window. */ if (!_cursor.in_window || this->delete_next_mouse_loop) { - delete this; + this->Close(); return; } /* 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. */ switch (this->close_cond) { - case TCC_RIGHT_CLICK: if (!_right_button_down) delete this; break; - case TCC_HOVER: if (!_mouse_hovering) delete this; break; + case TCC_RIGHT_CLICK: if (!_right_button_down) this->Close();; break; + case TCC_HOVER: if (!_mouse_hovering) this->Close();; break; case TCC_NONE: break; case TCC_NEXT_LOOP: this->delete_next_mouse_loop = true; break; @@ -815,7 +815,7 @@ struct TooltipsWindow : public Window if (_settings_client.gui.hover_delay_ms == 0) { if (!_right_button_down) this->delete_next_mouse_loop = true; } else if (!_mouse_hovering) { - delete this; + this->Close(); break; } if (this->viewport_virtual_left != this->parent->viewport->virtual_left || @@ -826,7 +826,7 @@ struct TooltipsWindow : public Window case TCC_EXIT_VIEWPORT: { 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; } } @@ -1134,18 +1134,19 @@ struct QueryStringWindow : public Window FALLTHROUGH; case WID_QS_CANCEL: - delete this; + this->Close(); break; } } - ~QueryStringWindow() + void Close() override { if (!this->editbox.handled && this->parent != nullptr) { 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); } + this->Window::Close(); } }; @@ -1227,9 +1228,10 @@ struct QueryWindow : public Window { this->InitNested(WN_CONFIRM_POPUP_QUERY); } - ~QueryWindow() + void Close() override { if (this->proc != nullptr) this->proc(this->parent, false); + this->Window::Close(); } void FindWindowPlacementAndResize(int def_width, int def_height) override @@ -1292,7 +1294,7 @@ struct QueryWindow : public Window { Window *parent = this->parent; /* Prevent the destructor calling the callback function */ this->proc = nullptr; - delete this; + this->Close(); if (proc != nullptr) { proc(parent, true); proc = nullptr; @@ -1300,7 +1302,7 @@ struct QueryWindow : public Window { break; } case WID_Q_NO: - delete this; + this->Close(); break; } } @@ -1318,7 +1320,7 @@ struct QueryWindow : public Window { FALLTHROUGH; case WKC_ESC: - delete this; + this->Close(); return ES_HANDLED; } return ES_NOT_HANDLED; @@ -1350,13 +1352,13 @@ static WindowDesc _query_desc( static void RemoveExistingQueryWindow(Window *parent, QueryCallbackProc *callback) { - for (const Window *w : Window::IterateFromBack()) { + for (Window *w : Window::IterateFromBack()) { if (w->window_class != WC_CONFIRM_POPUP_QUERY) continue; - const QueryWindow *qw = (const QueryWindow *)w; + QueryWindow *qw = (QueryWindow *)w; if (qw->parent != parent || qw->proc != callback) continue; - delete qw; + qw->Close(); break; } } @@ -1424,10 +1426,11 @@ struct ModifierKeyToggleWindow : Window { this->UpdateButtons(); } - ~ModifierKeyToggleWindow() + void Close() override { _invert_shift = false; _invert_ctrl = false; + this->Window::Close(); } void UpdateButtons() diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp index 2877c37093..21fb2e23cd 100644 --- a/src/network/network_chat_gui.cpp +++ b/src/network/network_chat_gui.cpp @@ -314,9 +314,10 @@ struct NetworkChatWindow : public Window { PositionNetworkChatWindow(this); } - ~NetworkChatWindow() + void Close() override { InvalidateWindowData(WC_NEWS_WINDOW, 0, 0); + this->Window::Close(); } void FindWindowPlacementAndResize(int def_width, int def_height) override @@ -470,7 +471,7 @@ struct NetworkChatWindow : public Window { FALLTHROUGH; case WID_NC_CLOSE: /* Cancel */ - delete this; + this->Close(); break; } } @@ -497,7 +498,7 @@ struct NetworkChatWindow : public Window { */ void OnInvalidateData(int data = 0, bool gui_scope = true) override { - if (data == this->dest) delete this; + if (data == this->dest) this->Close(); } }; diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index faf7a7cd0f..652872e8a8 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -109,9 +109,10 @@ BaseNetworkContentDownloadStatusWindow::BaseNetworkContentDownloadStatusWindow(W this->InitNested(WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD); } -BaseNetworkContentDownloadStatusWindow::~BaseNetworkContentDownloadStatusWindow() +void BaseNetworkContentDownloadStatusWindow::Close() { _network_content_client.RemoveCallback(this); + this->Window::Close(); } void BaseNetworkContentDownloadStatusWindow::UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) @@ -200,8 +201,7 @@ public: this->parent = FindWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_CONTENT_LIST); } - /** Free whatever we've allocated */ - ~NetworkContentDownloadStatusWindow() + void Close() override { TarScanner::Mode mode = TarScanner::NONE; for (auto ctype : this->receivedTypes) { @@ -282,6 +282,8 @@ public: /* Always invalidate the download window; tell it we are going to be gone */ InvalidateWindowData(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_CONTENT_LIST, 2); + + this->BaseNetworkContentDownloadStatusWindow::Close(); } void OnClick(Point pt, int widget, int click_count) override @@ -289,7 +291,7 @@ public: if (widget == WID_NCDS_CANCELOK) { if (this->downloaded_bytes != this->total_bytes) { _network_content_client.CloseConnection(); - delete this; + this->Close(); } else { /* If downloading succeeded, close the online content window. This will close * the current window as well. */ @@ -572,10 +574,10 @@ public: this->InvalidateData(); } - /** Free everything we allocated */ - ~NetworkContentListWindow() + void Close() override { _network_content_client.RemoveCallback(this); + this->Window::Close(); } void OnInit() override @@ -852,7 +854,7 @@ public: break; case WID_NCL_CANCEL: - delete this; + this->Close(); break; case WID_NCL_OPEN_URL: @@ -955,7 +957,7 @@ public: { if (!success) { ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_CONNECT, INVALID_STRING_ID, WL_ERROR); - delete this; + this->Close(); return; } diff --git a/src/network/network_content_gui.h b/src/network/network_content_gui.h index 00f68100cc..570f15462f 100644 --- a/src/network/network_content_gui.h +++ b/src/network/network_content_gui.h @@ -32,11 +32,7 @@ public: */ BaseNetworkContentDownloadStatusWindow(WindowDesc *desc); - /** - * Free everything associated with this window. - */ - ~BaseNetworkContentDownloadStatusWindow(); - + void Close() override; void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override; void DrawWidget(const Rect &r, int widget) const override; void OnDownloadProgress(const ContentInfo *ci, int bytes) override; diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 9728033935..881b6dcf54 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -523,9 +523,10 @@ public: this->servers.ForceRebuild(); } - ~NetworkGameWindow() + void Close() override { this->last_sorting = this->servers.GetListing(); + this->Window::Close(); } void OnInit() override @@ -2378,7 +2379,7 @@ struct NetworkCompanyPasswordWindow : public Window { FALLTHROUGH; case WID_NCP_CANCEL: - delete this; + this->Close(); break; case WID_NCP_SAVE_AS_DEFAULT_PASSWORD: @@ -2485,18 +2486,18 @@ struct NetworkAskRelayWindow : public Window { switch (widget) { case WID_NAR_NO: _network_coordinator_client.ConnectFailure(this->token, 0); - delete this; + this->Close(); break; case WID_NAR_YES_ONCE: _network_coordinator_client.StartTurnConnection(this->token); - delete this; + this->Close(); break; case WID_NAR_YES_ALWAYS: _settings_client.network.use_relay_service = URS_ALLOW; _network_coordinator_client.StartTurnConnection(this->token); - delete this; + this->Close(); break; } } diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index 60bef04a45..7268e4b161 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -184,9 +184,10 @@ struct NewGRFParametersWindow : public Window { this->InvalidateData(); } - ~NewGRFParametersWindow() + void Close() override { HideDropDownMenu(this); + this->Window::Close(); } /** @@ -449,7 +450,7 @@ struct NewGRFParametersWindow : public Window { break; case WID_NP_ACCEPT: - delete this; + this->Close(); break; } } @@ -686,7 +687,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { this->OnInvalidateData(GOID_NEWGRF_CURRENT_LOADED); } - ~NewGRFWindow() + void Close() override { CloseWindowByClass(WC_GRF_PARAMETERS); CloseWindowByClass(WC_TEXTFILE); @@ -699,6 +700,11 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { PostCheckNewGRFLoadWarnings(); } + this->Window::Close(); + } + + ~NewGRFWindow() + { /* Remove the temporary copy of grf-list used in window */ ClearGRFConfigList(&this->actives); } @@ -2121,10 +2127,6 @@ struct SavePresetWindow : public Window { if (initial_text != nullptr) this->presetname_editbox.text.Assign(initial_text); } - ~SavePresetWindow() - { - } - void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override { switch (widget) { @@ -2181,13 +2183,13 @@ struct SavePresetWindow : public Window { } case WID_SVP_CANCEL: - delete this; + this->Close(); break; case WID_SVP_SAVE: { 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); - delete this; + this->Close(); break; } } diff --git a/src/news_gui.cpp b/src/news_gui.cpp index 5f5ef264eb..d44bc246bf 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -485,7 +485,7 @@ struct NewsWindow : Window { switch (widget) { case WID_N_CLOSEBOX: NewsWindow::duration = 0; - delete this; + this->Close(); _forced_news = nullptr; break; @@ -1054,7 +1054,7 @@ static void ShowNewsMessage(const NewsItem *ni) bool HideActiveNewsMessage() { NewsWindow *w = (NewsWindow*)FindWindowById(WC_NEWS_WINDOW, 0); if (w == nullptr) return false; - delete w; + w->Close(); return true; } diff --git a/src/openttd.cpp b/src/openttd.cpp index 18bfb09933..210e40dabe 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -528,7 +528,7 @@ static void LoadIntroGame(bool load_newgrfs = true) { UnshowCriticalError(); for (Window *w : Window::IterateFromFront()) { - delete w; + w->Close(); } _game_mode = GM_MENU; diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 5894269398..4c1ad988f3 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -179,11 +179,12 @@ public: this->owner = v->owner; } - ~CargoTypeOrdersWindow() + void Close() override { if (!FocusWindowById(WC_VEHICLE_ORDERS, this->window_number)) { MarkDirtyFocusedRoutePaths(this->vehicle); } + this->Window::Close(); } virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override @@ -229,11 +230,11 @@ public: virtual void OnClick(Point pt, int widget, int click_count) override { if (!this->CheckOrderStillValid()) { - delete this; + this->Close(); return; } if (widget == WID_CTO_CLOSEBTN) { - delete this; + this->Close(); } else if (WID_CTO_CARGO_DROPDOWN_FIRST <= widget && widget <= WID_CTO_CARGO_DROPDOWN_LAST) { const CargoSpec *cs = _sorted_cargo_specs[widget - WID_CTO_CARGO_DROPDOWN_FIRST]; const CargoID cargo_id = cs->Index(); @@ -247,7 +248,7 @@ public: virtual void OnDropdownSelect(int widget, int action_type) override { if (!this->CheckOrderStillValid()) { - delete this; + this->Close(); return; } ModifyOrderFlags mof = (this->variant == CTOWV_LOAD) ? MOF_CARGO_TYPE_LOAD : MOF_CARGO_TYPE_UNLOAD; @@ -301,7 +302,7 @@ public: } } - virtual void OnFocusLost(Window *newly_focused_window) override + virtual void OnFocusLost(bool closing, Window *newly_focused_window) override { if (HasFocusedVehicleChanged(this->window_number, newly_focused_window)) { MarkDirtyFocusedRoutePaths(this->vehicle); @@ -316,7 +317,7 @@ public: virtual void OnInvalidateData(int data = 0, bool gui_scope = true) override { if (!this->CheckOrderStillValid()) { - delete this; + this->Close(); return; } if (gui_scope) { @@ -1900,13 +1901,14 @@ public: this->OnInvalidateData(VIWD_MODIFY_ORDERS); } - ~OrdersWindow() + void Close() override { CloseWindowById(WC_VEHICLE_CARGO_TYPE_LOAD_ORDERS, this->window_number, false); CloseWindowById(WC_VEHICLE_CARGO_TYPE_UNLOAD_ORDERS, this->window_number, false); if (!FocusWindowById(WC_VEHICLE_VIEW, this->window_number)) { MarkDirtyFocusedRoutePaths(this->vehicle); } + this->GeneralVehicleWindow::Close(); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override @@ -3575,7 +3577,7 @@ public: } } - virtual void OnFocusLost(Window *newly_focused_window) override + virtual void OnFocusLost(bool closing, Window *newly_focused_window) override { if (HasFocusedVehicleChanged(this->window_number, newly_focused_window)) { MarkDirtyFocusedRoutePaths(this->vehicle); diff --git a/src/osk_gui.cpp b/src/osk_gui.cpp index f38056f4e2..b43612f8d9 100644 --- a/src/osk_gui.cpp +++ b/src/osk_gui.cpp @@ -165,7 +165,7 @@ struct OskWindow : public Window { return; } } - delete this; + this->Close(); break; case WID_OSK_CANCEL: @@ -177,7 +177,7 @@ struct OskWindow : public Window { qs->text.Assign(this->orig_str.c_str()); qs->text.MovePos(WKC_END); this->OnEditboxChanged(WID_OSK_TEXT); - delete this; + this->Close(); } break; } @@ -197,10 +197,10 @@ struct OskWindow : public Window { this->parent->SetWidgetDirty(this->text_btn); } - void OnFocusLost(Window *newly_focused_window) override + void OnFocusLost(bool closing, Window *newly_focused_window) override { VideoDriver::GetInstance()->EditBoxLostFocus(); - delete this; + if (!closing) this->Close(); } }; diff --git a/src/plans_gui.cpp b/src/plans_gui.cpp index 052205d30e..e9c8b2c2c8 100644 --- a/src/plans_gui.cpp +++ b/src/plans_gui.cpp @@ -98,13 +98,14 @@ struct PlansWindow : Window { RebuildList(); } - ~PlansWindow() + void Close() override { this->list.clear(); if (_current_plan) { _current_plan->SetFocus(false); _current_plan = nullptr; } + this->Window::Close(); } virtual void OnClick(Point pt, int widget, int click_count) override diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index cfc1598724..5d732f2a5b 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -515,12 +515,13 @@ struct BuildRailToolbarWindow : Window { 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_WAYPOINT)) SetViewportCatchmentWaypoint(nullptr, true); if (_settings_client.gui.link_terraform_toolbar) CloseWindowById(WC_SCEN_LAND_GEN, 0, false); CloseWindowById(WC_SELECT_STATION, 0); + this->Window::Close(); } /** @@ -1249,9 +1250,10 @@ public: this->InvalidateData(); } - virtual ~BuildRailStationWindow() + void Close() override { CloseWindowById(WC_SELECT_STATION, 0); + this->PickerWindowBase::Close(); } /** Sort station classes by StationClassID. */ @@ -1979,11 +1981,12 @@ public: this->OnInvalidateData(); } - ~BuildSignalWindow() + void Close() override { _convert_signal_button = false; _trace_restrict_button = false; _program_signal_button = false; + this->PickerWindowBase::Close(); } void OnInit() override @@ -2516,9 +2519,10 @@ struct BuildRailWaypointWindow : PickerWindowBase { } } - virtual ~BuildRailWaypointWindow() + void Close() override { CloseWindowById(WC_SELECT_STATION, 0); + this->PickerWindowBase::Close(); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override diff --git a/src/road_gui.cpp b/src/road_gui.cpp index 5bd3a3b014..878a00ce10 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -377,12 +377,13 @@ struct BuildRoadToolbarWindow : Window { 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_BUILD_WAYPOINT)) SetViewportCatchmentWaypoint(nullptr, true); if (_settings_client.gui.link_terraform_toolbar) CloseWindowById(WC_SCEN_LAND_GEN, 0, false); CloseWindowById(WC_SELECT_STATION, 0); + this->Window::Close(); } /** @@ -1377,9 +1378,10 @@ public: } } - virtual ~BuildRoadStationWindow() + void Close() override { CloseWindowById(WC_SELECT_STATION, 0); + this->PickerWindowBase::Close(); } /** Sort classes by RoadStopClassID. */ @@ -2035,9 +2037,10 @@ struct BuildRoadWaypointWindow : PickerWindowBase { } } - virtual ~BuildRoadWaypointWindow() + void Close() override { CloseWindowById(WC_SELECT_STATION, 0); + this->PickerWindowBase::Close(); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override @@ -2395,7 +2398,7 @@ static BuildRoadToolbarWindow *GetRoadToolbarWindowForRoadStop(const RoadStopSpe if (w != nullptr) { if (spec != nullptr && ((HasBit(spec->flags, RSF_BUILD_MENU_ROAD_ONLY) && !RoadTypeIsRoad(_cur_roadtype)) || (HasBit(spec->flags, RSF_BUILD_MENU_TRAM_ONLY) && !RoadTypeIsTram(_cur_roadtype)))) { - delete w; + w->Close(); } else { return w; } diff --git a/src/schdispatch_gui.cpp b/src/schdispatch_gui.cpp index 5097bb722d..5fd35196ff 100644 --- a/src/schdispatch_gui.cpp +++ b/src/schdispatch_gui.cpp @@ -210,11 +210,12 @@ struct SchdispatchWindow : GeneralVehicleWindow { this->AutoSelectSchedule(); } - ~SchdispatchWindow() + void Close() override { if (!FocusWindowById(WC_VEHICLE_VIEW, this->window_number)) { MarkDirtyFocusedRoutePaths(this->vehicle); } + this->GeneralVehicleWindow::Close(); } uint base_width; @@ -1169,7 +1170,7 @@ struct ScheduledDispatchAddSlotsWindow : Window { case WID_SCHDISPATCH_ADD_SLOT_ADD_BUTTON: static_cast(this->parent)->AddMultipleDepartureSlots(this->start, this->step, this->end); - delete this; + this->Close(); break; } } diff --git a/src/script/script_gui.cpp b/src/script/script_gui.cpp index fa06cc0bfe..3d0c9e1797 100644 --- a/src/script/script_gui.cpp +++ b/src/script/script_gui.cpp @@ -201,7 +201,7 @@ struct ScriptListWindow : public Window { this->SetDirty(); if (click_count > 1) { this->ChangeScript(); - delete this; + this->Close(); } } break; @@ -209,12 +209,12 @@ struct ScriptListWindow : public Window { case WID_SCRL_ACCEPT: { this->ChangeScript(); - delete this; + this->Close(); break; } case WID_SCRL_CANCEL: - delete this; + this->Close(); break; } } @@ -232,7 +232,7 @@ struct ScriptListWindow : public Window { void OnInvalidateData(int data = 0, bool gui_scope = true) override { if (_game_mode == GM_NORMAL && Company::IsValidID(this->slot)) { - delete this; + this->Close(); return; } @@ -325,9 +325,10 @@ struct ScriptSettingsWindow : public Window { this->RebuildVisibleSettings(); } - ~ScriptSettingsWindow() + void Close() override { HideDropDownMenu(this); + this->Window::Close(); } /** @@ -520,7 +521,7 @@ struct ScriptSettingsWindow : public Window { } case WID_SCRS_ACCEPT: - delete this; + this->Close(); break; case WID_SCRS_RESET: @@ -660,7 +661,7 @@ struct ScriptTextfileWindow : public TextfileWindow { { const char *textfile = GetConfig(slot)->GetTextfile(file_type, slot); if (textfile == nullptr) { - delete this; + this->Close(); } else { this->LoadTextfile(textfile, (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR); } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 8d6b8015d6..3d31e99af1 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -197,11 +197,12 @@ struct GameOptionsWindow : Window { if constexpr (!NetworkSurveyHandler::IsSurveyPossible()) this->GetWidget(WID_GO_SURVEY_SEL)->SetDisplayedPlane(SZSP_NONE); } - ~GameOptionsWindow() + void Close() override { CloseWindowById(WC_CUSTOM_CURRENCY, 0); CloseWindowByClass(WC_TEXTFILE); if (this->reload) _switch_mode = SM_MENU; + this->Window::Close(); } /** diff --git a/src/signs_gui.cpp b/src/signs_gui.cpp index e2040b368e..d603b33bd0 100644 --- a/src/signs_gui.cpp +++ b/src/signs_gui.cpp @@ -527,7 +527,7 @@ struct SignWindow : Window, SignList { FALLTHROUGH; case WID_QES_CANCEL: - delete this; + this->Close(); break; } } @@ -596,5 +596,5 @@ void DeleteRenameSignWindow(SignID sign) { SignWindow *w = dynamic_cast(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(); } diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index 2a345e4758..c3e235f536 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -1086,7 +1086,12 @@ SmallMapWindow::SmallMapWindow(WindowDesc *desc, int window_number) : Window(des SmallMapWindow::~SmallMapWindow() { delete this->overlay; +} + +/* virtual */ void SmallMapWindow::Close() +{ this->BreakIndustryChainLink(); + this->Window::Close(); } /** diff --git a/src/smallmap_gui.h b/src/smallmap_gui.h index 2d8f75a70a..832e2c7d80 100644 --- a/src/smallmap_gui.h +++ b/src/smallmap_gui.h @@ -207,6 +207,7 @@ public: void SmallMapCenterOnCurrentPos(); Point GetStationMiddle(const Station *st) const; + void Close() override; void SetStringParameters(int widget) const override; void OnInit() override; void OnPaint() override; diff --git a/src/station_gui.cpp b/src/station_gui.cpp index 7b92c6cbe3..c875ce13ba 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -480,9 +480,10 @@ public: this->GetWidget(WID_STL_SORTDROPBTN)->widget_data = this->sorter_names[this->stations.SortType()]; } - ~CompanyStationsWindow() + void Close() override { this->last_sorting = this->stations.GetListing(); + this->Window::Close(); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override @@ -1435,7 +1436,7 @@ struct StationViewWindow : public Window { ZoningStationWindowOpenClose(Station::Get(window_number)); } - ~StationViewWindow() + void Close() override { ZoningStationWindowOpenClose(Station::Get(window_number)); CloseWindowById(WC_TRAINS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_TRAIN, this->owner, this->window_number).Pack(), false); @@ -1444,6 +1445,7 @@ struct StationViewWindow : public Window { CloseWindowById(WC_AIRCRAFT_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_AIRCRAFT, this->owner, this->window_number).Pack(), false); SetViewportCatchmentStation(Station::Get(this->window_number), false); + this->Window::Close(); } void OnInit() override @@ -2545,11 +2547,12 @@ struct SelectStationWindow : Window { _thd.freeze = true; } - ~SelectStationWindow() + void Close() override { SetViewportCatchmentStation(nullptr, true); _thd.freeze = false; + this->Window::Close(); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override @@ -2684,7 +2687,7 @@ static bool StationJoinerNeeded(const CommandContainer &cmd, TileArea ta) Window *selection_window = FindWindowById(WC_SELECT_STATION, 0); if (selection_window != nullptr) { /* Abort current distant-join and start new one */ - delete selection_window; + selection_window->Close(); UpdateTileSelection(); } @@ -3097,7 +3100,7 @@ public: void OnMouseLoop() override { if (!_cursor.in_window || !(_settings_client.gui.hover_delay_ms == 0 ? _right_button_down : _mouse_hovering)) { - delete this; + this->Close(); } } }; diff --git a/src/tbtr_template_gui_create.cpp b/src/tbtr_template_gui_create.cpp index c9f117c66c..6dd6119ba7 100644 --- a/src/tbtr_template_gui_create.cpp +++ b/src/tbtr_template_gui_create.cpp @@ -166,7 +166,7 @@ public: UpdateButtonState(); } - ~TemplateCreateWindow() + void Close() override { if (virtual_train != nullptr) { DoCommandP(0, virtual_train->index, 0, CMD_DELETE_VIRTUAL_TRAIN); @@ -177,6 +177,7 @@ public: *create_window_open = false; CloseWindowById(WC_BUILD_VIRTUAL_TRAIN, this->window_number); InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN); + this->Window::Close(); } void SetVirtualTrain(Train* const train) @@ -208,7 +209,7 @@ public: if (this->template_index != INVALID_VEHICLE) { if (TemplateVehicle::GetIfValid(this->template_index) == nullptr) { - delete this; + this->Close(); return; } } @@ -244,11 +245,11 @@ public: } else if (this->template_index != INVALID_VEHICLE) { DoCommandP(0, this->template_index, 0, CMD_DELETE_TEMPLATE_VEHICLE); } - delete this; + this->Close(); break; } case TCW_CANCEL: { - delete this; + this->Close(); break; } case TCW_REFIT: { diff --git a/src/tbtr_template_gui_main.cpp b/src/tbtr_template_gui_main.cpp index 710c105efe..eccece5b8f 100644 --- a/src/tbtr_template_gui_main.cpp +++ b/src/tbtr_template_gui_main.cpp @@ -255,8 +255,9 @@ public: this->BuildTemplateGuiList(); } - ~TemplateReplaceWindow() { + void Close() override { CloseWindowById(WC_CREATE_TEMPLATE, this->window_number); + this->Window::Close(); } virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override diff --git a/src/terraform_gui.cpp b/src/terraform_gui.cpp index 83320e6fe4..2bc996cf96 100644 --- a/src/terraform_gui.cpp +++ b/src/terraform_gui.cpp @@ -213,10 +213,6 @@ struct TerraformToolbarWindow : Window { this->last_user_action = WIDGET_LIST_END; } - ~TerraformToolbarWindow() - { - } - void OnInit() override { /* Don't show the place object button when there are no objects to place. */ diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp index 1348231c80..71a6abfd24 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -370,11 +370,12 @@ struct TimetableWindow : GeneralVehicleWindow { this->owner = this->vehicle->owner; } - ~TimetableWindow() + void Close() override { if (!FocusWindowById(WC_VEHICLE_VIEW, this->window_number)) { MarkDirtyFocusedRoutePaths(this->vehicle); } + this->GeneralVehicleWindow::Close(); } /** @@ -1165,7 +1166,7 @@ struct TimetableWindow : GeneralVehicleWindow { } } - virtual void OnFocusLost(Window *newly_focused_window) override + virtual void OnFocusLost(bool closing, Window *newly_focused_window) override { if (HasFocusedVehicleChanged(this->window_number, newly_focused_window)) { MarkDirtyFocusedRoutePaths(this->vehicle); diff --git a/src/town_gui.cpp b/src/town_gui.cpp index e6dc7b37a2..0cb3ed600a 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -534,9 +534,10 @@ public: nvp->InitializeViewport(this, this->town->xy, ScaleZoomGUI(ZOOM_LVL_TOWN)); } - ~TownViewWindow() + void Close() override { SetViewportCatchmentTown(Town::Get(this->window_number), false); + this->Window::Close(); } void SetStringParameters(int widget) const override @@ -2116,7 +2117,7 @@ struct SelectTownWindow : Window { DoCommandP(&this->cmd); /* Close the window */ - delete this; + this->Close(); } virtual void OnResize() diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 82a1f97c67..c8c7cbe5d5 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -1780,7 +1780,7 @@ public: this->ReloadProgramme(); } - ~TraceRestrictWindow() + void Close() override { extern const TraceRestrictProgram *_viewport_highlight_tracerestrict_program; if (_viewport_highlight_tracerestrict_program != nullptr) { @@ -1789,6 +1789,7 @@ public: SetViewportCatchmentTraceRestrictProgram(prog, false); } } + this->Window::Close(); } virtual void OnClick(Point pt, int widget, int click_count) override @@ -3844,9 +3845,10 @@ public: this->owner = vli.company; } - ~TraceRestrictSlotWindow() + void Close() override { *this->sorting = this->vehgroups.GetListing(); + this->Window::Close(); } virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 5059e676b9..0e16179fa5 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -906,7 +906,7 @@ struct RefitWindow : public Window { this->SetWidgetDisabledState(WID_VR_REFIT, this->sel[0] < 0); } - ~RefitWindow() + void Close() override { if (this->window_number != INVALID_VEHICLE) { if (!FocusWindowById(WC_VEHICLE_VIEW, this->window_number)) { @@ -916,6 +916,7 @@ struct RefitWindow : public Window { } } } + this->Window::Close(); } void OnFocus(Window *previously_focused_window) override @@ -928,7 +929,7 @@ struct RefitWindow : public Window { } } - void OnFocusLost(Window *newly_focused_window) override + void OnFocusLost(bool closing, Window *newly_focused_window) override { if (HasFocusedVehicleChanged(this->window_number, newly_focused_window)) { if (this->window_number != INVALID_VEHICLE) { @@ -1350,10 +1351,10 @@ struct RefitWindow : public Window { 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 | this->is_virtual_train << 31, GetCmdRefitVeh(v)) && delete_window) { - delete this; + this->Close(); } } else { - if (DoCommandP(v->tile, v->index, this->cargo->cargo | this->cargo->subtype << 8 | this->order << 16, CMD_ORDER_REFIT)) delete this; + if (DoCommandP(v->tile, v->index, this->cargo->cargo | this->cargo->subtype << 8 | this->order << 16, CMD_ORDER_REFIT)) this->Close(); } } break; @@ -2262,10 +2263,11 @@ public: if (this->vli.company != OWNER_NONE) this->owner = this->vli.company; } - ~VehicleListWindow() + void Close() override { *this->sorting = this->vehgroups.GetListing(); this->RefreshRouteOverlay(); + this->Window::Close(); } virtual void OnFocus(Window *previously_focused_window) override @@ -2273,7 +2275,7 @@ public: this->RefreshRouteOverlay(); } - virtual void OnFocusLost(Window *newly_focused_window) override + virtual void OnFocusLost(bool closing, Window *newly_focused_window) override { this->RefreshRouteOverlay(); } @@ -2671,7 +2673,7 @@ public: /* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */ this->vehgroups.ForceRebuild(); if (this->vli.type == VL_SHARED_ORDERS && !_settings_client.gui.enable_single_veh_shared_order_gui && this->vehicles.size() == 1) { - delete this; + this->Close(); return; } } else { @@ -2885,7 +2887,7 @@ struct VehicleDetailsWindow : Window { if (v->type == VEH_TRAIN && _shift_pressed) this->tab = TDW_TAB_TOTALS; } - ~VehicleDetailsWindow() + void Close() override { if (this->window_number != INVALID_VEHICLE) { if (!FocusWindowById(WC_VEHICLE_VIEW, this->window_number)) { @@ -2895,6 +2897,7 @@ struct VehicleDetailsWindow : Window { } } } + this->Window::Close(); } /** @@ -3401,7 +3404,7 @@ struct VehicleDetailsWindow : Window { } } - virtual void OnFocusLost(Window *newly_focused_window) override + virtual void OnFocusLost(bool closing, Window *newly_focused_window) override { if (HasFocusedVehicleChanged(this->window_number, newly_focused_window)) { if (this->window_number != INVALID_VEHICLE) { @@ -3676,7 +3679,7 @@ public: this->UpdateButtonStatus(); } - ~VehicleViewWindow() + void Close() override { if (this->window_number != INVALID_VEHICLE) { const Vehicle *v = Vehicle::Get(this->window_number); @@ -3690,6 +3693,8 @@ public: if (this->fixed_route_overlay_active) { RemoveFixedViewportRoutePath(this->window_number); } + + this->Window::Close(); } virtual void OnFocus(Window *previously_focused_window) override @@ -3702,7 +3707,7 @@ public: } } - virtual void OnFocusLost(Window *newly_focused_window) override + virtual void OnFocusLost(bool closing, Window *newly_focused_window) override { if (HasFocusedVehicleChanged(this->window_number, newly_focused_window)) { if (this->window_number != INVALID_VEHICLE) { diff --git a/src/waypoint_gui.cpp b/src/waypoint_gui.cpp index b5f80f989d..76c6fe0caf 100644 --- a/src/waypoint_gui.cpp +++ b/src/waypoint_gui.cpp @@ -106,11 +106,11 @@ public: this->OnInvalidateData(0); } - ~WaypointWindow() + void Close() override { CloseWindowById(GetWindowClassForVehicleType(this->vt), VehicleListIdentifier(VL_STATION_LIST, this->vt, this->owner, this->window_number).Pack(), false); - SetViewportCatchmentWaypoint(Waypoint::Get(this->window_number), false); + this->Window::Close(); } void SetStringParameters(int widget) const override diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index 9d8cef6958..9c18b1330f 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -179,12 +179,12 @@ struct DropdownWindow : Window { this->scrolling_timer = GUITimer(MILLISECONDS_PER_TICK); } - ~DropdownWindow() + void Close() override { /* Make the dropdown "invisible", so it doesn't affect new window placement. * Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */ - this->window_class = WC_INVALID; this->SetDirty(); + this->Window::Close(); Window *w2 = FindWindowById(this->parent_wnd_class, this->parent_wnd_num); if (w2 != nullptr) { @@ -291,7 +291,7 @@ struct DropdownWindow : Window { { Window *w2 = FindWindowById(this->parent_wnd_class, this->parent_wnd_num); if (w2 == nullptr) { - delete this; + this->Close(); return; } @@ -302,7 +302,7 @@ struct DropdownWindow : Window { this->SetDirty(); w2->OnDropdownSelect(this->parent_button, this->selected_index); - delete this; + this->Close(); return; } @@ -312,7 +312,7 @@ struct DropdownWindow : Window { if (!_left_button_clicked) { this->drag_mode = false; if (!this->GetDropDownItem(item)) { - if (this->instant_close) delete this; + if (this->instant_close) this->Close(); return; } this->click_delay = 2; @@ -345,11 +345,11 @@ struct DropdownWindow : Window { } } - virtual void OnFocusLost(Window *newly_focused_window) + virtual void OnFocusLost(bool closing, Window *newly_focused_window) { if (this->sync_parent_focus & DDSF_LOST_FOCUS) { Window *parent = FindWindowById(this->parent_wnd_class, this->parent_wnd_num); - if (parent) parent->OnFocusLost(newly_focused_window); + if (parent) parent->OnFocusLost(false, newly_focused_window); } } }; diff --git a/src/window.cpp b/src/window.cpp index 512e713564..53d35a552c 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -58,11 +58,11 @@ static Window *_mouseover_last_w = nullptr; ///< Window of the last OnMouseOver static Window *_last_scroll_window = nullptr; ///< Window of the last scroll event. /** List of windows opened at the screen sorted from the front. */ -WindowBase *_z_front_window = nullptr; +Window *_z_front_window = nullptr; /** List of windows opened at the screen sorted from the back. */ -WindowBase *_z_back_window = nullptr; +Window *_z_back_window = nullptr; /** List of windows in an arbitrary order, that is not instantaneously changed by bringing windows to the front. */ -WindowBase *_first_window = nullptr; +Window *_first_window = nullptr; /** If false, highlight is white, otherwise the by the widget defined colour. */ bool _window_highlight_colour = false; @@ -470,7 +470,7 @@ void SetFocusedWindow(Window *w) _focused_window = w; /* So we can inform it that it lost focus */ - if (old_focused != nullptr) old_focused->OnFocusLost(w); + if (old_focused != nullptr) old_focused->OnFocusLost(false, w); if (_focused_window != nullptr) _focused_window->OnFocus(old_focused); } @@ -561,7 +561,7 @@ void Window::OnFocus(Window *previously_focused_window) /** * Called when window loses focus */ -void Window::OnFocusLost(Window *newly_focused_window) +void Window::OnFocusLost(bool closing, Window *newly_focused_window) { if (this->nested_focus != nullptr && this->nested_focus->type == WWT_EDITBOX) VideoDriver::GetInstance()->EditBoxLostFocus(); } @@ -747,7 +747,7 @@ static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count) } case WWT_CLOSEBOX: // 'X' - delete w; + w->Close(); return; case WWT_CAPTION: // 'Title bar' @@ -835,7 +835,7 @@ static void DispatchRightClickEvent(Window *w, int x, int y) /* Right-click close is enabled and there is a closebox */ if (_settings_client.gui.right_mouse_wnd_close && (w->window_desc->flags & WDF_NO_CLOSE) == 0) { - 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) { GuiShowTooltips(w, wid->tool_tip, 0, nullptr, TCC_RIGHT_CLICK); } @@ -1120,15 +1120,15 @@ void Window::CloseChildWindows(WindowClass wc) const { Window *child = FindChildWindow(this, wc); while (child != nullptr) { - delete child; + child->Close(); 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() { if (_thd.window_class == this->window_class && _thd.window_number == this->window_number) { @@ -1147,33 +1147,27 @@ Window::~Window() /* Make sure we don't try to access this window as the focused window when it doesn't exist anymore. */ if (_focused_window == this) { _focused_window = nullptr; - this->OnFocusLost(nullptr); + this->OnFocusLost(true, nullptr); } this->CloseChildWindows(); - if (this->viewport != nullptr) DeleteWindowViewport(this); - this->SetDirtyAsBlocks(); + this->window_class = WC_INVALID; +} + +/** + * Remove window and all its child windows from the window stack. + */ +Window::~Window() +{ + assert(this->window_class == WC_INVALID); + + if (this->viewport != nullptr) DeleteWindowViewport(this); + free(this->nested_array); // Contents is released through deletion of #nested_root. delete this->nested_root; - - /* - * Make fairly sure that this is written, and not "optimized" away. - * The delete operator is overwritten to not delete it; the deletion - * happens at a later moment in time after the window has been - * removed from the list of windows to prevent issues with items - * being removed during the iteration as not one but more windows - * may be removed by a single call to ~Window by means of the - * CloseChildWindows function. - */ - const_cast(this->window_class) = WC_INVALID; -} - -void Window::Close() -{ - if (this->window_class != WC_INVALID) delete this; } /** @@ -1232,7 +1226,7 @@ void CloseWindowById(WindowClass cls, WindowNumber number, bool force) { Window *w = FindWindowById(cls, number); if (w != nullptr && (force || (w->flags & WF_STICKY) == 0)) { - delete w; + w->Close(); } } @@ -1247,9 +1241,9 @@ void CloseAllWindowsById(WindowClass cls, WindowNumber number, bool force) if (cls < WC_END && !_present_window_types[cls]) return; /* Note: the container remains stable, even when deleting windows. */ - for (Window *w : Window::IterateUnordered()) { + for (Window *w : Window::Iterate()) { if (w->window_class == cls && w->window_number == number && (force || (w->flags & WF_STICKY) == 0)) { - delete w; + w->Close(); } } } @@ -1263,9 +1257,9 @@ void CloseWindowByClass(WindowClass cls) if (cls < WC_END && !_present_window_types[cls]) return; /* Note: the container remains stable, even when deleting windows. */ - for (Window *w : Window::IterateUnordered()) { + for (Window *w : Window::Iterate()) { if (w->window_class == cls) { - delete w; + w->Close(); } } } @@ -1279,9 +1273,9 @@ void CloseWindowByClass(WindowClass cls) void DeleteCompanyWindows(CompanyID id) { /* Note: the container remains stable, even when deleting windows. */ - for (Window *w : Window::IterateUnordered()) { + for (Window *w : Window::Iterate()) { if (w->owner == id) { - delete w; + w->Close(); } } @@ -1458,7 +1452,7 @@ static void AddWindowToZOrdering(Window *w) w->z_front = w->z_back = nullptr; } else { /* Search down the z-ordering for its location. */ - WindowBase *v = _z_front_window; + Window *v = _z_front_window; uint last_z_priority = UINT_MAX; (void)last_z_priority; // Unused without asserts while (v != nullptr && (v->window_class == WC_INVALID || GetWindowZPriority(v->window_class) > GetWindowZPriority(w->window_class))) { @@ -1498,7 +1492,7 @@ static void AddWindowToZOrdering(Window *w) * Removes a window from the z-ordering. * @param w Window to remove */ -static void RemoveWindowFromZOrdering(WindowBase *w) +static void RemoveWindowFromZOrdering(Window *w) { if (w->z_front == nullptr) { dbg_assert(_z_front_window == w); @@ -2003,13 +1997,8 @@ void UnInitWindowSystem() { UnshowCriticalError(); - for (Window *w : Window::IterateUnordered()) delete w; - - for (WindowBase *w = _z_front_window; w != nullptr; /* nothing */) { - WindowBase *to_del = w; - w = w->z_back; - free(to_del); - } + for (Window *w : Window::Iterate()) w->Close(); + Window::DeleteClosedWindows(); _z_front_window = nullptr; _z_back_window = nullptr; @@ -3237,7 +3226,37 @@ static void CheckSoftLimit() if (deletable_count <= _settings_client.gui.window_soft_limit) break; assert(last_deletable != nullptr); - delete last_deletable; + last_deletable->Close(); + } +} + +/** + * Delete all closed windows. + */ +/* static */ void Window::DeleteClosedWindows() +{ + bool reset_window_nexts = false; + _present_window_types.reset(); + + /* Do the actual free of the deleted windows. */ + for (Window *v = _z_front_window; v != nullptr; /* nothing */) { + Window *w = v; + v = v->z_back; + + if (w->window_class < WC_END) _present_window_types.set(w->window_class); + + if (w->window_class != WC_INVALID) continue; + + RemoveWindowFromZOrdering(w); + delete w; + reset_window_nexts = true; + } + + if (reset_window_nexts) { + _first_window = _z_front_window; + for (Window *w = _z_front_window; w != nullptr; w = w->z_back) { + w->next_window = w->z_back; + } } } @@ -3252,30 +3271,7 @@ void InputLoop() CheckSoftLimit(); - bool reset_window_nexts = false; - - _present_window_types.reset(); - - /* Do the actual free of the deleted windows. */ - for (WindowBase *v = _z_front_window; v != nullptr; /* nothing */) { - WindowBase *w = v; - v = v->z_back; - - if (w->window_class < WC_END) _present_window_types.set(w->window_class); - - if (w->window_class != WC_INVALID) continue; - - RemoveWindowFromZOrdering(w); - free(w); - reset_window_nexts = true; - } - - if (reset_window_nexts) { - _first_window = _z_front_window; - for (WindowBase *w = _z_front_window; w != nullptr; w = w->z_back) { - w->next_window = w->z_back; - } - } + Window::DeleteClosedWindows(); if (_input_events_this_tick != 0) { /* The input loop is called only once per GameLoop() - so we can clear the counter here */ @@ -3541,11 +3537,11 @@ void CallWindowGameTickEvent() void CloseNonVitalWindows() { /* Note: the container remains stable, even when deleting windows. */ - for (Window *w : Window::IterateUnordered()) { + for (Window *w : Window::Iterate()) { if ((w->window_desc->flags & WDF_NO_CLOSE) == 0 && (w->flags & WF_STICKY) == 0) { // do not delete windows which are 'pinned' - delete w; + w->Close(); } } } @@ -3560,9 +3556,9 @@ void CloseNonVitalWindows() void CloseAllNonVitalWindows() { /* Note: the container remains stable, even when closing windows. */ - for (Window *w : Window::IterateUnordered()) { + for (Window *w : Window::Iterate()) { if ((w->window_desc->flags & WDF_NO_CLOSE) == 0) { - delete w; + w->Close(); } } } @@ -3585,9 +3581,9 @@ void DeleteAllMessages() void CloseConstructionWindows() { /* Note: the container remains stable, even when deleting windows. */ - for (const Window *w : Window::IterateUnordered()) { + for (Window *w : Window::Iterate()) { if (w->window_desc->flags & WDF_CONSTRUCTION) { - delete w; + w->Close(); } } } @@ -3598,9 +3594,9 @@ void CloseConstructionWindows() void CloseNetworkClientWindows() { /* Note: the container remains stable, even when deleting windows. */ - for (const Window *w : Window::IterateUnordered()) { + for (Window *w : Window::Iterate()) { if (w->window_desc->flags & WDF_NETWORK) { - delete w; + w->Close(); } } } @@ -3807,14 +3803,13 @@ void RelocateAllWindows(int neww, int newh) } /** - * Destructor of the base class PickerWindowBase - * Main utility is to stop the base Window destructor from triggering - * a free while the child will already be free, in this case by the ResetObjectToPlace(). + * Hide the window and all its child windows, and mark them for a later deletion. + * Always call ResetObjectToPlace() when closing a PickerWindow. */ -PickerWindowBase::~PickerWindowBase() +void PickerWindowBase::Close() { - this->window_class = WC_INVALID; // stop the ancestor from freeing the already (to be) child ResetObjectToPlace(); + this->Window::Close(); } char *DumpWindowInfo(char *b, const char *last, const Window *w) diff --git a/src/window_gui.h b/src/window_gui.h index 823ddd3f07..4356295dc9 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -77,9 +77,9 @@ static inline void DrawFrameRect(const Rect &r, Colours colour, FrameFlags flags void DrawCaption(const Rect &r, Colours colour, Owner owner, TextColour text_colour, StringID str, StringAlignment align, FontSize fs); /* window.cpp */ -extern WindowBase *_z_front_window; -extern WindowBase *_z_back_window; -extern WindowBase *_first_window; +extern Window *_z_front_window; +extern Window *_z_back_window; +extern Window *_first_window; extern Window *_focused_window; inline uint64 GetWindowUpdateNumber() @@ -233,51 +233,27 @@ enum TooltipCloseCondition { TCC_EXIT_VIEWPORT, }; -struct WindowBase { - WindowBase *z_front; ///< The window in front of us in z-order. - WindowBase *z_back; ///< The window behind us in z-order. - WindowBase *next_window; ///< The next window in arbitrary iteration order. - WindowClass window_class; ///< Window class - - virtual ~WindowBase() {} - - /** - * Memory allocator for a single class instance. - * @param size the amount of bytes to allocate. - * @return the given amounts of bytes zeroed. - */ - inline void *operator new(size_t size) { return CallocT(size); } - -protected: - WindowBase() {} - -private: - /** - * Memory allocator for an array of class instances. - * @param size the amount of bytes to allocate. - * @return the given amounts of bytes zeroed. - */ - inline void *operator new[](size_t size) { NOT_REACHED(); } - - /** - * Memory release for a single class instance. - * @param ptr the memory to free. - */ - inline void operator delete(void *ptr) { NOT_REACHED(); } - - /** - * Memory release for an array of class instances. - * @param ptr the memory to free. - */ - inline void operator delete[](void *ptr) { NOT_REACHED(); } -}; - typedef std::vector VehicleList; /** * Data structure for an opened window */ -struct Window : WindowBase { +struct Window : ZeroedMemoryAllocator { + Window *z_front; ///< The window in front of us in z-order. + Window *z_back; ///< The window behind us in z-order. + Window *next_window; ///< The next window in arbitrary iteration order. + WindowClass window_class; ///< Window class + +private: + /** + * Helper allocation function to disallow something. + * Don't allow arrays; arrays of Windows are pointless as you need + * to destruct them all at the same time too, which is kinda hard. + * @param size the amount of space not to allocate + */ + inline void *operator new[](size_t size) { NOT_REACHED(); } + inline void operator delete[](void *ptr) { NOT_REACHED(); } + protected: void InitializeData(WindowNumber window_number); void InitializePositionSize(int x, int y, int min_width, int min_height); @@ -285,32 +261,13 @@ protected: std::vector scheduled_invalidation_data; ///< Data of scheduled OnInvalidateData() calls. + virtual ~Window(); + public: Window(WindowDesc *desc); - virtual ~Window(); - virtual void Close(); - - /** - * Helper allocation function to disallow something. - * Don't allow arrays; arrays of Windows are pointless as you need - * to destruct them all at the same time too, which is kinda hard. - * @param size the amount of space not to allocate - */ - inline void *operator new[](size_t size) - { - NOT_REACHED(); - } - - /** - * Helper allocation function to disallow something. - * Don't free the window directly; it corrupts the linked list when iterating - * @param ptr the pointer not to free - */ - inline void operator delete(void *ptr) - { - } + static void DeleteClosedWindows(); WindowDesc *window_desc; ///< Window description WindowFlags flags; ///< Window flags @@ -601,7 +558,7 @@ public: virtual void OnFocus(Window *previously_focused_window); - virtual void OnFocusLost(Window *newly_focused_window); + virtual void OnFocusLost(bool closing, Window *newly_focused_window); /** * A key has been pressed. @@ -845,7 +802,7 @@ public: virtual void ShowNewGRFInspectWindow() const { NOT_REACHED(); } template - using window_base_t = std::conditional_t{}, WindowBase const, WindowBase>; + using window_type = std::conditional_t{}, Window const, Window>; enum IterationMode { IM_FROM_FRONT, @@ -866,7 +823,7 @@ public: typedef size_t difference_type; typedef std::forward_iterator_tag iterator_category; - explicit WindowIterator(window_base_t *start) : w(start) + explicit WindowIterator(window_type *start) : w(start) { this->Validate(); } @@ -877,7 +834,7 @@ public: WindowIterator & operator++() { this->Next(); this->Validate(); return *this; } private: - window_base_t *w; + window_type *w; void Validate() { while (this->w != nullptr && this->w->window_class == WC_INVALID) this->Next(); } void Next() @@ -901,16 +858,16 @@ public: /** * Iterable ensemble of all valid Windows * @tparam T Type of the class/struct that is going to be iterated - * @tparam Tfront Wether we iterate from front + * @tparam Tmode Iteration mode */ template - struct Iterate { - Iterate(window_base_t *from) : from(from) {} + struct IterateCommon { + IterateCommon(window_type *from) : from(from) {} WindowIterator begin() { return WindowIterator(this->from); } WindowIterator end() { return WindowIterator(nullptr); } bool empty() { return this->begin() == this->end(); } private: - window_base_t *from; + window_type *from; }; /** @@ -920,7 +877,7 @@ public: * @return an iterable ensemble of all valid Window */ template - static Iterate IterateFromBack(window_base_t *from = _z_back_window) { return Iterate(from); } + static IterateCommon IterateFromBack(window_type *from = _z_back_window) { return IterateCommon(from); } /** * Returns an iterable ensemble of all valid Window from front to back @@ -929,7 +886,7 @@ public: * @return an iterable ensemble of all valid Window */ template - static Iterate IterateFromFront(window_base_t *from = _z_front_window) { return Iterate(from); } + static IterateCommon IterateFromFront(window_type *from = _z_front_window) { return IterateCommon(from); } /** * Returns an iterable ensemble of all valid Window in an arbitrary order which is safe to use when deleting @@ -938,7 +895,7 @@ public: * @return an iterable ensemble of all valid Window */ template - static Iterate IterateUnordered(window_base_t *from = _first_window) { return Iterate(from); } + static IterateCommon Iterate(window_type *from = _first_window) { return IterateCommon(from); } }; /** @@ -1001,7 +958,7 @@ public: this->parent = parent; } - virtual ~PickerWindowBase(); + void Close() override; }; Window *BringWindowToFrontById(WindowClass cls, WindowNumber number);