1
0
mirror of https://github.com/OpenTTD/OpenTTD synced 2025-12-10 06:52:05 +01:00

Fix #14756: Invalidate nested focus before widget container is cleared. (#14809)

This commit is contained in:
Cyprian Klimaszewski
2025-12-06 18:52:44 +01:00
committed by GitHub
parent 92e895a37a
commit abf8438a1b
6 changed files with 38 additions and 11 deletions

View File

@@ -1334,8 +1334,7 @@ struct BuildVehicleWindow : Window {
this->badge_classes = GUIBadgeClasses(static_cast<GrfSpecFeature>(GSF_TRAINS + this->vehicle_type));
this->SetCargoFilterArray();
auto container = this->GetWidget<NWidgetContainer>(WID_BV_BADGE_FILTER);
this->badge_filters = AddBadgeDropdownFilters(*container, WID_BV_BADGE_FILTER, COLOUR_GREY, static_cast<GrfSpecFeature>(GSF_TRAINS + this->vehicle_type));
this->badge_filters = AddBadgeDropdownFilters(this, WID_BV_BADGE_FILTER, WID_BV_BADGE_FILTER, COLOUR_GREY, static_cast<GrfSpecFeature>(GSF_TRAINS + this->vehicle_type));
this->widget_lookup.clear();
this->nested_root->FillWidgetLookup(this->widget_lookup);

View File

@@ -21,6 +21,7 @@
#include "strings_func.h"
#include "timer/timer_game_calendar.h"
#include "window_gui.h"
#include "window_type.h"
#include "zoom_func.h"
#include "table/strings.h"
@@ -550,15 +551,17 @@ DropDownList NWidgetBadgeFilter::GetDropDownList(PaletteID palette) const
/**
* Add badge drop down filter widgets.
* @param container Container widget to hold filter widgets.
* @param window Window that holds the container.
* @param container Container widget index to hold filter widgets.
* @param widget Widget index to apply to first filter.
* @param colour Background colour of widgets.
* @param feature GRF feature for filters.
* @return First and last widget indexes of filter widgets.
*/
std::pair<WidgetID, WidgetID> AddBadgeDropdownFilters(NWidgetContainer &container, WidgetID widget, Colours colour, GrfSpecFeature feature)
std::pair<WidgetID, WidgetID> AddBadgeDropdownFilters(Window *window, WidgetID container_id, WidgetID widget, Colours colour, GrfSpecFeature feature)
{
container.Clear();
auto container = window->GetWidget<NWidgetContainer>(container_id);
container->Clear(window);
WidgetID first = ++widget;
/* Get list of classes used by feature. */
@@ -568,7 +571,7 @@ std::pair<WidgetID, WidgetID> AddBadgeDropdownFilters(NWidgetContainer &containe
const auto [config, _] = GetBadgeClassConfigItem(feature, GetClassBadge(class_index)->label);
if (!config.show_filter) continue;
container.Add(std::make_unique<NWidgetBadgeFilter>(colour, widget, feature, class_index));
container->Add(std::make_unique<NWidgetBadgeFilter>(colour, widget, feature, class_index));
++widget;
}

View File

@@ -57,7 +57,7 @@ std::unique_ptr<DropDownListItem> MakeDropDownListBadgeIconItem(const std::share
DropDownList BuildBadgeClassConfigurationList(const class GUIBadgeClasses &badge_class, uint columns, std::span<const StringID> column_separators, Colours bg_colour);
bool HandleBadgeConfigurationDropDownClick(GrfSpecFeature feature, uint columns, int result, int click_result, BadgeFilterChoices &choices);
std::pair<WidgetID, WidgetID> AddBadgeDropdownFilters(NWidgetContainer &container, WidgetID widget, Colours colour, GrfSpecFeature feature);
std::pair<WidgetID, WidgetID> AddBadgeDropdownFilters(Window *window, WidgetID container_id, WidgetID widget, Colours colour, GrfSpecFeature feature);
class NWidgetBadgeFilter : public NWidgetLeaf {
public:

View File

@@ -251,9 +251,7 @@ void PickerWindow::ConstructWindow()
void PickerWindow::OnInit()
{
this->badge_classes = GUIBadgeClasses(this->callbacks.GetFeature());
auto container = this->GetWidget<NWidgetContainer>(WID_PW_BADGE_FILTER);
this->badge_filters = AddBadgeDropdownFilters(*container, WID_PW_BADGE_FILTER, COLOUR_DARK_GREEN, this->callbacks.GetFeature());
this->badge_filters = AddBadgeDropdownFilters(this, WID_PW_BADGE_FILTER, WID_PW_BADGE_FILTER, COLOUR_DARK_GREEN, this->callbacks.GetFeature());
this->widget_lookup.clear();
this->nested_root->FillWidgetLookup(this->widget_lookup);

View File

@@ -3476,3 +3476,20 @@ std::unique_ptr<NWidgetBase> MakeCompanyButtonRows(WidgetID widget_first, Widget
if (hor != nullptr) vert->Add(std::move(hor));
return vert;
}
/**
* Unfocuses the focused widget of the window,
* if the focused widget is contained inside the container.
* @param parent_window Window which contains this container.
*/
void NWidgetContainer::UnfocusWidgets(Window *parent_window)
{
assert(parent_window != nullptr);
if (parent_window->nested_focus != nullptr) {
for (auto &widget : this->children) {
if (parent_window->nested_focus == widget.get()) {
parent_window->UnfocusFocusedWidget();
}
}
}
}

View File

@@ -484,7 +484,17 @@ public:
inline bool IsEmpty() { return this->children.empty(); }
NWidgetBase *GetWidgetOfType(WidgetType tp) override;
void Clear() { this->children.clear(); }
void UnfocusWidgets(Window *parent_window);
/**
* Clears the container, deleting all widgets that were contained.
* @param parent_window Window that contains the container.
*/
inline void Clear(Window *parent_window)
{
this->UnfocusWidgets(parent_window);
this->children.clear();
}
protected:
std::vector<std::unique_ptr<NWidgetBase>> children{}; ///< Child widgets in container.