diff --git a/docs/changelog.txt b/docs/changelog.txt index b39243133..06831d065 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -37,6 +37,12 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ================================================================================ # Future +## Fixes +- `command-prompt`: added support for commands that require a specific screen to be visible, e.g. `spotclean` + +## API +- Added ``Screen::Hide`` to temporarily hide screens, like `command-prompt` + ================================================================================ # 0.44.11-beta1 diff --git a/library/include/Core.h b/library/include/Core.h index dbe73621d..529633ff2 100644 --- a/library/include/Core.h +++ b/library/include/Core.h @@ -73,6 +73,11 @@ namespace DFHack class df_window; } + namespace Screen + { + struct Hide; + } + enum state_change_event { SC_UNKNOWN = -1, @@ -274,6 +279,7 @@ namespace DFHack void *last_world_data_ptr; // for state change tracking void *last_local_map_ptr; + friend struct Screen::Hide; df::viewscreen *top_viewscreen; bool last_pause_state; // Very important! diff --git a/library/include/modules/Screen.h b/library/include/modules/Screen.h index 4d458f5a7..1775f3e15 100644 --- a/library/include/modules/Screen.h +++ b/library/include/modules/Screen.h @@ -306,6 +306,15 @@ namespace DFHack GUI_HOOK_DECLARE(set_tile, bool, (const Pen &pen, int x, int y, bool map)); } + //! Temporary hide a screen until destructor is called + struct DFHACK_EXPORT Hide { + Hide(df::viewscreen* screen); + ~Hide(); + private: + void extract(df::viewscreen*); + void merge(df::viewscreen*); + df::viewscreen* screen_; + }; } class DFHACK_EXPORT dfhack_viewscreen : public df::viewscreen { @@ -379,4 +388,5 @@ namespace DFHack virtual df::building *getSelectedBuilding(); virtual df::plant *getSelectedPlant(); }; + } diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index 43ec88cfc..733f8cb78 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -376,6 +376,42 @@ bool Screen::hasActiveScreens(Plugin *plugin) return false; } +namespace DFHack { namespace Screen { + +Hide::Hide(df::viewscreen* screen) : + screen_{screen} +{ + extract(screen_); +} + +Hide::~Hide() +{ + if (screen_) + merge(screen_); +} + +void Hide::extract(df::viewscreen* a) +{ + df::viewscreen* ap = a->parent; + df::viewscreen* ac = a->child; + + ap->child = ac; + if (ac) ac->parent = ap; + else Core::getInstance().top_viewscreen = ap; +} + +void Hide::merge(df::viewscreen* a) +{ + df::viewscreen* ap = a->parent; + df::viewscreen* ac = a->parent->child; + + ap->child = a; + a->child = ac; + if (ac) ac->parent = a; + else Core::getInstance().top_viewscreen = a; +} +} } + #ifdef _LINUX class DFHACK_EXPORT renderer { unsigned char *screen; diff --git a/plugins/command-prompt.cpp b/plugins/command-prompt.cpp index 0a45708d7..1c68a8fbb 100644 --- a/plugins/command-prompt.cpp +++ b/plugins/command-prompt.cpp @@ -200,7 +200,10 @@ void viewscreen_commandpromptst::submit() return; submitted = true; prompt_ostream out(this); - Core::getInstance().runCommand(out, get_entry()); + { + Screen::Hide hide_guard(this); + Core::getInstance().runCommand(out, get_entry()); + } if(out.empty() && responses.empty()) Screen::dismiss(this); else @@ -312,7 +315,7 @@ void viewscreen_commandpromptst::feed(std::set *events) command_result show_prompt(color_ostream &out, std::vector & parameters) { - if (Gui::getCurFocus() == "dfhack/commandprompt") + if (Gui::getCurFocus(true) == "dfhack/commandprompt") { Screen::dismiss(Gui::getCurViewscreen(true)); return CR_OK;