From a6a92230576908134e8478b700b2725f361fce40 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Wed, 14 Jun 2023 08:55:15 +0100 Subject: [PATCH 1/2] Change: Allow dropdowns to steal/lose focus regardless of focus-stealing prevention. --- src/window.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/window.cpp b/src/window.cpp index 2aa4b2bc08..ac15768e6e 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -613,12 +613,17 @@ static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count) 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? - (w->window_desc.flags & WDF_NO_FOCUS) == 0 && // Don't lose focus to toolbars - widget_type != WWT_CLOSEBOX) { // Don't change focused window if 'X' (close button) was clicked - focused_widget_changed = true; - SetFocusedWindow(w); + if (_focused_window != w) { + /* Don't switch focus to an unfocusable window, or if the 'X' (close button) was clicked. */ + if ((w->window_desc.flags & WDF_NO_FOCUS) == 0 && widget_type != WWT_CLOSEBOX) { + focused_widget_changed = true; + SetFocusedWindow(w); + } else if (_focused_window != nullptr && _focused_window->window_class == WC_DROPDOWN_MENU) { + /* Previously focused window was a dropdown menu, close it even if clicked window is unfocusable. */ + SetFocusedWindow(nullptr); + } } if (nw == nullptr) return; // exit if clicked outside of widgets @@ -1386,7 +1391,7 @@ void Window::InitializeData(WindowNumber window_number) * (so we don't interrupt typing) unless the new window has a text box. */ bool dropdown_active = _focused_window != nullptr && _focused_window->window_class == WC_DROPDOWN_MENU; bool editbox_active = EditBoxInGlobalFocus() && this->nested_root->GetWidgetOfType(WWT_EDITBOX) == nullptr; - if (!dropdown_active && !editbox_active) SetFocusedWindow(this); + if (this->window_class == WC_DROPDOWN_MENU || (!dropdown_active && !editbox_active)) SetFocusedWindow(this); /* Insert the window into the correct location in the z-ordering. */ BringWindowToFront(this, false); From 1620047fcf865c9876c735b42b5a7fb88736beee Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 4 Jun 2023 17:48:33 +0100 Subject: [PATCH 2/2] Feature: Option to disable activate-on-release behaviour of toolbar dropdown buttons. --- src/lang/english.txt | 3 +++ src/settings_gui.cpp | 1 + src/settings_type.h | 1 + src/table/settings/gui_settings.ini | 8 ++++++++ src/toolbar_gui.cpp | 24 ++++++++++++------------ 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index ede50e8dda..2d56612755 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1661,6 +1661,9 @@ STR_CONFIG_SETTING_SCROLLMODE_LMB :Move map with L STR_CONFIG_SETTING_SMOOTH_SCROLLING :Smooth viewport scrolling: {STRING2} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Control how the main view scrolls to a specific position when clicking on the smallmap or when issuing a command to scroll to a specific object on the map. If enabled, the viewport scrolls smoothly, if disabled it jumps directly to the targeted spot +STR_CONFIG_SETTING_TOOLBAR_DROPDOWN_CLOSE :Toolbar dropdowns activate on release: {STRING2} +STR_CONFIG_SETTING_TOOLBAR_DROPDOWN_CLOSE_HELPTEXT :Control whether the main toolbar dropdowns activate their default function when the mouse button is released. If not enabled then the dropdown menu will stay open so a selection can be made. + STR_CONFIG_SETTING_MEASURE_TOOLTIP :Show a measurement tooltip when using various build-tools: {STRING2} STR_CONFIG_SETTING_MEASURE_TOOLTIP_HELPTEXT :Display tile-distances and height differences when dragging during construction operations diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index a37aa1fb1d..4b1a7335f6 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -2015,6 +2015,7 @@ static SettingsContainer &GetSettingsTree() general->Add(new SettingEntry("gui.window_snap_radius")); general->Add(new SettingEntry("gui.window_soft_limit")); general->Add(new SettingEntry("gui.right_click_wnd_close")); + general->Add(new SettingEntry("gui.toolbar_dropdown_close")); } SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS)); diff --git a/src/settings_type.h b/src/settings_type.h index b086bc2950..747df2ed9e 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -178,6 +178,7 @@ struct GUISettings { uint8_t scrollwheel_multiplier; ///< how much 'wheel' per incoming event from the OS? bool timetable_arrival_departure; ///< show arrivals and departures in vehicle timetables RightClickClose right_click_wnd_close; ///< close window with right click + bool toolbar_dropdown_close; ///< should toolbar dropdown buttons close immediately bool pause_on_newgame; ///< whether to start new games paused or not SignalGUISettings signal_gui_mode; ///< select which signal types are shown in the signal GUI SignalCycleSettings cycle_signal_types; ///< Which signal types to cycle with the build signal tool. diff --git a/src/table/settings/gui_settings.ini b/src/table/settings/gui_settings.ini index edac87e2b9..b0f131f27c 100644 --- a/src/table/settings/gui_settings.ini +++ b/src/table/settings/gui_settings.ini @@ -147,6 +147,14 @@ strhelp = STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT strval = STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_NO cat = SC_BASIC +[SDTC_BOOL] +var = gui.toolbar_dropdown_close +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC +def = false +str = STR_CONFIG_SETTING_TOOLBAR_DROPDOWN_CLOSE +strhelp = STR_CONFIG_SETTING_TOOLBAR_DROPDOWN_CLOSE_HELPTEXT +cat = SC_BASIC + ; We might need to emulate a right mouse button on mac [SDTC_VAR] ifdef = __APPLE__ diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index fe8a32eb6b..0a22426271 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -115,7 +115,7 @@ public: */ static void PopupMainToolbarMenu(Window *w, WidgetID widget, DropDownList &&list, int def) { - ShowDropDownList(w, std::move(list), def, widget, 0, true); + ShowDropDownList(w, std::move(list), def, widget, 0, _settings_client.gui.toolbar_dropdown_close); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); } @@ -289,7 +289,7 @@ static CallBackFunction ToolbarOptionsClick(Window *w) list.push_back(MakeDropDownListCheckedItem(IsTransparencySet(TO_HOUSES), STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS, OME_TRANSPARENTBUILDINGS)); list.push_back(MakeDropDownListCheckedItem(IsTransparencySet(TO_SIGNS), STR_SETTINGS_MENU_TRANSPARENT_SIGNS, OME_SHOW_STATIONSIGNS)); - ShowDropDownList(w, std::move(list), 0, WID_TN_SETTINGS, 140, true); + ShowDropDownList(w, std::move(list), 0, WID_TN_SETTINGS, 140, _settings_client.gui.toolbar_dropdown_close); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; } @@ -684,7 +684,7 @@ static CallBackFunction ToolbarGraphsClick(Window *w) if (_toolbar_mode != TB_NORMAL) AddDropDownLeagueTableOptions(list); - ShowDropDownList(w, std::move(list), GRMN_OPERATING_PROFIT_GRAPH, WID_TN_GRAPHS, 140, true); + ShowDropDownList(w, std::move(list), GRMN_OPERATING_PROFIT_GRAPH, WID_TN_GRAPHS, 140, _settings_client.gui.toolbar_dropdown_close); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; @@ -697,7 +697,7 @@ static CallBackFunction ToolbarLeagueClick(Window *w) AddDropDownLeagueTableOptions(list); int selected = list[0]->result; - ShowDropDownList(w, std::move(list), selected, WID_TN_LEAGUE, 140, true); + ShowDropDownList(w, std::move(list), selected, WID_TN_LEAGUE, 140, _settings_client.gui.toolbar_dropdown_close); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; @@ -878,7 +878,7 @@ static CallBackFunction ToolbarZoomOutClick(Window *w) static CallBackFunction ToolbarBuildRailClick(Window *w) { - ShowDropDownList(w, GetRailTypeDropDownList(), _last_built_railtype, WID_TN_RAILS, 140, true); + ShowDropDownList(w, GetRailTypeDropDownList(), _last_built_railtype, WID_TN_RAILS, 140, _settings_client.gui.toolbar_dropdown_close); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; } @@ -900,7 +900,7 @@ static CallBackFunction MenuClickBuildRail(int index) static CallBackFunction ToolbarBuildRoadClick(Window *w) { - ShowDropDownList(w, GetRoadTypeDropDownList(RTTB_ROAD), _last_built_roadtype, WID_TN_ROADS, 140, true); + ShowDropDownList(w, GetRoadTypeDropDownList(RTTB_ROAD), _last_built_roadtype, WID_TN_ROADS, 140, _settings_client.gui.toolbar_dropdown_close); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; } @@ -922,7 +922,7 @@ static CallBackFunction MenuClickBuildRoad(int index) static CallBackFunction ToolbarBuildTramClick(Window *w) { - ShowDropDownList(w, GetRoadTypeDropDownList(RTTB_TRAM), _last_built_tramtype, WID_TN_TRAMS, 140, true); + ShowDropDownList(w, GetRoadTypeDropDownList(RTTB_TRAM), _last_built_tramtype, WID_TN_TRAMS, 140, _settings_client.gui.toolbar_dropdown_close); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; } @@ -946,7 +946,7 @@ static CallBackFunction ToolbarBuildWaterClick(Window *w) { DropDownList list; list.push_back(MakeDropDownListIconItem(SPR_IMG_BUILD_CANAL, PAL_NONE, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION, 0)); - ShowDropDownList(w, std::move(list), 0, WID_TN_WATER, 140, true); + ShowDropDownList(w, std::move(list), 0, WID_TN_WATER, 140, _settings_client.gui.toolbar_dropdown_close); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; } @@ -968,7 +968,7 @@ static CallBackFunction ToolbarBuildAirClick(Window *w) { DropDownList list; list.push_back(MakeDropDownListIconItem(SPR_IMG_AIRPORT, PAL_NONE, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION, 0)); - ShowDropDownList(w, std::move(list), 0, WID_TN_AIR, 140, true); + ShowDropDownList(w, std::move(list), 0, WID_TN_AIR, 140, _settings_client.gui.toolbar_dropdown_close); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; } @@ -992,7 +992,7 @@ static CallBackFunction ToolbarForestClick(Window *w) list.push_back(MakeDropDownListIconItem(SPR_IMG_LANDSCAPING, PAL_NONE, STR_LANDSCAPING_MENU_LANDSCAPING, 0)); list.push_back(MakeDropDownListIconItem(SPR_IMG_PLANTTREES, PAL_NONE, STR_LANDSCAPING_MENU_PLANT_TREES, 1)); list.push_back(MakeDropDownListIconItem(SPR_IMG_SIGN, PAL_NONE, STR_LANDSCAPING_MENU_PLACE_SIGN, 2)); - ShowDropDownList(w, std::move(list), 0, WID_TN_LANDSCAPE, 100, true); + ShowDropDownList(w, std::move(list), 0, WID_TN_LANDSCAPE, 100, _settings_client.gui.toolbar_dropdown_close); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; } @@ -1265,7 +1265,7 @@ static CallBackFunction ToolbarScenGenIndustry(Window *w) static CallBackFunction ToolbarScenBuildRoadClick(Window *w) { - ShowDropDownList(w, GetScenRoadTypeDropDownList(RTTB_ROAD), _last_built_roadtype, WID_TE_ROADS, 140, true); + ShowDropDownList(w, GetScenRoadTypeDropDownList(RTTB_ROAD), _last_built_roadtype, WID_TE_ROADS, 140, _settings_client.gui.toolbar_dropdown_close); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; } @@ -1285,7 +1285,7 @@ static CallBackFunction ToolbarScenBuildRoad(int index) static CallBackFunction ToolbarScenBuildTramClick(Window *w) { - ShowDropDownList(w, GetScenRoadTypeDropDownList(RTTB_TRAM), _last_built_tramtype, WID_TE_TRAMS, 140, true); + ShowDropDownList(w, GetScenRoadTypeDropDownList(RTTB_TRAM), _last_built_tramtype, WID_TE_TRAMS, 140, _settings_client.gui.toolbar_dropdown_close); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; }