From b49bd86a46aeff5b5b8b4b1251d3bcfef62e9eec Mon Sep 17 00:00:00 2001 From: PeterN Date: Wed, 7 Jun 2023 19:01:30 +0100 Subject: [PATCH] Fix dec7ff6b0c: Dropdowns couldn't be closed by pressing the parent button. (#10954) Since dropdowns self-close, the detection of re-clicking a dropdown button no longer worked, as the dropdown is already closed. Instead set (and then test) a flag on the parent widget to indicate that the dropdown closed. This method avoids looping windows on every click. --- src/widget_type.h | 2 ++ src/widgets/dropdown.cpp | 26 ++++---------------------- src/widgets/dropdown_func.h | 3 --- src/window.cpp | 9 +++++---- 4 files changed, 11 insertions(+), 29 deletions(-) diff --git a/src/widget_type.h b/src/widget_type.h index ca08f2f571..974fd4d852 100644 --- a/src/widget_type.h +++ b/src/widget_type.h @@ -295,6 +295,7 @@ enum NWidgetDisplay { NDB_SCROLLBAR_DOWN = 7, ///< Down-button is lowered bit. /* Generic. */ NDB_HIGHLIGHT = 8, ///< Highlight of widget is on. + NDB_DROPDOWN_CLOSED = 9, ///< Dropdown menu of the dropdown widget has closed. ND_LOWERED = 1 << NDB_LOWERED, ///< Bit value of the lowered flag. ND_DISABLED = 1 << NDB_DISABLED, ///< Bit value of the disabled flag. @@ -306,6 +307,7 @@ enum NWidgetDisplay { ND_SCROLLBAR_UP = 1 << NDB_SCROLLBAR_UP, ///< Bit value of the 'scrollbar up' flag. ND_SCROLLBAR_DOWN = 1 << NDB_SCROLLBAR_DOWN, ///< Bit value of the 'scrollbar down' flag. ND_SCROLLBAR_BTN = ND_SCROLLBAR_UP | ND_SCROLLBAR_DOWN, ///< Bit value of the 'scrollbar up' or 'scrollbar down' flag. + ND_DROPDOWN_CLOSED = 1 << NDB_DROPDOWN_CLOSED, ///< Bit value of the 'dropdown closed' flag. }; DECLARE_ENUM_AS_BIT_SET(NWidgetDisplay) diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index 6ffbfc1bd6..a0ff70e7b4 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -191,6 +191,10 @@ struct DropdownWindow : Window { pt.x -= this->parent->left; pt.y -= this->parent->top; this->parent->OnDropdownClose(pt, this->parent_button, this->selected_index, this->instant_close); + + /* Set flag on parent widget to indicate that we have just closed. */ + NWidgetCore *nwc = this->parent->GetWidget(this->parent_button); + if (nwc != nullptr) SetBit(nwc->disp_flags, NDB_DROPDOWN_CLOSED); } void OnFocusLost() override @@ -471,25 +475,3 @@ void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int butt if (!list.empty()) ShowDropDownList(w, std::move(list), selected, button, width); } - -/** - * Delete the drop-down menu from window \a pw - * @param pw Parent window of the drop-down menu window - * @return Parent widget number if the drop-down was found and closed, \c -1 if the window was not found. - */ -int HideDropDownMenu(Window *pw) -{ - for (Window *w : Window::Iterate()) { - if (w->parent != pw) continue; - if (w->window_class != WC_DROPDOWN_MENU) continue; - - DropdownWindow *dw = dynamic_cast(w); - assert(dw != nullptr); - int parent_button = dw->parent_button; - dw->Close(); - return parent_button; - } - - return -1; -} - diff --git a/src/widgets/dropdown_func.h b/src/widgets/dropdown_func.h index f047fb43df..1a0102c17b 100644 --- a/src/widgets/dropdown_func.h +++ b/src/widgets/dropdown_func.h @@ -15,7 +15,4 @@ /* Show drop down menu containing a fixed list of strings */ void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask, uint32 hidden_mask, uint width = 0); -/* Hide drop down menu of a parent window */ -int HideDropDownMenu(Window *pw); - #endif /* WIDGETS_DROPDOWN_FUNC_H */ diff --git a/src/window.cpp b/src/window.cpp index a1cda1ab4d..314b6eb77e 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -22,7 +22,6 @@ #include "tilehighlight_func.h" #include "network/network.h" #include "querystring_gui.h" -#include "widgets/dropdown_func.h" #include "strings_func.h" #include "settings_type.h" #include "settings_func.h" @@ -679,6 +678,9 @@ static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count) NWidgetCore *nw = w->nested_root->GetWidgetFromPos(x, y); WidgetType widget_type = (nw != nullptr) ? nw->type : WWT_EMPTY; + /* Allow dropdown close flag detection to work. */ + if (nw != nullptr) ClrBit(nw->disp_flags, NDB_DROPDOWN_CLOSED); + bool focused_widget_changed = false; /* If clicked on a window that previously did not have focus */ if (_focused_window != w && // We already have focus, right? @@ -711,9 +713,8 @@ static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count) focused_widget_changed |= w->SetFocusedWidget(widget_index); } - /* Close any child drop down menus. If the button pressed was the drop down - * list's own button, then we should not process the click any further. */ - if (HideDropDownMenu(w) == widget_index && widget_index >= 0) return; + /* Dropdown window of this widget was closed so don't process click this time. */ + if (HasBit(nw->disp_flags, NDB_DROPDOWN_CLOSED)) return; if ((widget_type & ~WWB_PUSHBUTTON) < WWT_LAST && (widget_type & WWB_PUSHBUTTON)) w->HandleButtonClick(widget_index);