From e17d0f21fcfa03f4baa25f659229f833d55af768 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Tue, 2 Jun 2026 00:40:49 -0600 Subject: [PATCH] Console focus & closing fixes --- res/rml/command_console.rcss | 4 --- src/dusk/ui/command_console.cpp | 54 ++++++++++++--------------------- src/dusk/ui/command_console.hpp | 8 ++--- src/dusk/ui/document.cpp | 1 + src/dusk/ui/ui.cpp | 14 +++++++++ src/m_Do/m_Do_main.cpp | 1 - 6 files changed, 39 insertions(+), 43 deletions(-) diff --git a/res/rml/command_console.rcss b/res/rml/command_console.rcss index 1446e6f165..44074d40a5 100644 --- a/res/rml/command_console.rcss +++ b/res/rml/command_console.rcss @@ -26,10 +26,6 @@ console { color: #FFFFFF; } -console[hidden] { - display: none; -} - output { display: block; overflow: hidden; diff --git a/src/dusk/ui/command_console.cpp b/src/dusk/ui/command_console.cpp index 9f561fb08d..3f964b1f0c 100644 --- a/src/dusk/ui/command_console.cpp +++ b/src/dusk/ui/command_console.cpp @@ -44,10 +44,6 @@ CommandConsole::CommandConsole() : Document(kDocumentSource) { auto* rawInput = mDocument ? mDocument->GetElementById("console-input") : nullptr; mInput = rmlui_dynamic_cast(rawInput); - if (mConsole != nullptr) { - mConsole->SetAttribute("hidden", ""); - } - listen( Rml::EventId::Keydown, [this](Rml::Event& event) { @@ -59,7 +55,7 @@ CommandConsole::CommandConsole() : Document(kDocumentSource) { executeFromInput(); event.StopImmediatePropagation(); } else if (key == Rml::Input::KI_ESCAPE) { - closeInput(); + hide(true); event.StopImmediatePropagation(); } else if (key == Rml::Input::KI_UP) { navigateHistory(-1); @@ -72,12 +68,6 @@ CommandConsole::CommandConsole() : Document(kDocumentSource) { true); } -void CommandConsole::show() { - if (mDocument != nullptr) { - mDocument->Show(Rml::ModalFlag::None, Rml::FocusFlag::None, Rml::ScrollFlag::None); - } -} - bool CommandConsole::handle_nav_command(Rml::Event&, NavCommand) { return false; } @@ -87,14 +77,6 @@ void CommandConsole::update() { return; } - int numKeys = 0; - const bool* keyState = SDL_GetKeyboardState(&numKeys); - const bool slashNow = SDL_SCANCODE_SLASH < numKeys && keyState[SDL_SCANCODE_SLASH]; - if (!mInputActive && slashNow && !mPrevSlashState) { - openInput(); - } - mPrevSlashState = slashNow; - const float dt = std::max(ImGui::GetIO().DeltaTime, 0.0f); for (auto& line : mOutputLines) { line.remain -= dt; @@ -103,13 +85,9 @@ void CommandConsole::update() { std::ranges::remove_if(mOutputLines, [](const OutputLine& l) { return l.remain <= 0.0f; }); mOutputLines.erase(first, last); - if (mConsole != nullptr) { - if (!mOutputLines.empty() || mInputActive) { - mConsole->RemoveAttribute("hidden"); - } else { - mConsole->SetAttribute("hidden", ""); - return; - } + if (mOutputLines.empty() && !mInputActive) { + Document::hide(mPendingClose); + return; } if (mOutput == nullptr) { @@ -143,21 +121,28 @@ void CommandConsole::update() { } } -void CommandConsole::openInput() { +void CommandConsole::show() { + if (mDocument != nullptr) { + mDocument->Show(Rml::ModalFlag::None, Rml::FocusFlag::None, Rml::ScrollFlag::None); + } mInputActive = true; mScrollToBottom = true; if (mConsole != nullptr) { mConsole->SetAttribute("open", ""); - mConsole->RemoveAttribute("hidden"); } + focus(); +} + +bool CommandConsole::focus() { if (mInput != nullptr) { mInput->SetValue(""); aurora::rmlui::set_input_type(aurora::rmlui::InputType::Text); - mInput->Focus(true); + return mInput->Focus(true); } + return false; } -void CommandConsole::closeInput() { +void CommandConsole::hide(bool close) { mInputActive = false; mHistoryPos = -1; if (mConsole != nullptr) { @@ -166,18 +151,19 @@ void CommandConsole::closeInput() { if (mInput != nullptr) { mInput->SetValue(""); } - if (mDocument != nullptr) { - mDocument->Focus(false); + mPendingClose = close; + // Immediately refocus + if (auto* doc = top_document()) { + doc->focus(); } } void CommandConsole::executeFromInput() { if (mInput == nullptr) { - closeInput(); return; } const Rml::String value = mInput->GetValue(); - closeInput(); + hide(true); if (!value.empty()) { runCommand(value, mState, [this](std::string text) { ConsolePrint(std::move(text)); }); } diff --git a/src/dusk/ui/command_console.hpp b/src/dusk/ui/command_console.hpp index 8d476ae085..b228158f6a 100644 --- a/src/dusk/ui/command_console.hpp +++ b/src/dusk/ui/command_console.hpp @@ -15,8 +15,11 @@ namespace dusk::ui { class CommandConsole : public Document { public: CommandConsole(); - void show() override; + void update() override; + void show() override; + bool focus() override; + void hide(bool close) override; private: struct OutputLine { @@ -39,15 +42,12 @@ private: int mHistoryPos = -1; bool mInputActive = false; bool mScrollToBottom = false; - bool mPrevSlashState = false; CommandState mState; bool handle_nav_command(Rml::Event& event, NavCommand cmd) override; void ConsolePrint(std::string text); - void openInput(); - void closeInput(); void executeFromInput(); void navigateHistory(int dir); }; diff --git a/src/dusk/ui/document.cpp b/src/dusk/ui/document.cpp index a7bcc3f9ed..91e126fc00 100644 --- a/src/dusk/ui/document.cpp +++ b/src/dusk/ui/document.cpp @@ -68,6 +68,7 @@ void Document::show() { focus(); } } + mPendingClose = false; } void Document::hide(bool close) { diff --git a/src/dusk/ui/ui.cpp b/src/dusk/ui/ui.cpp index af05d0f476..37a403d8af 100644 --- a/src/dusk/ui/ui.cpp +++ b/src/dusk/ui/ui.cpp @@ -11,6 +11,7 @@ #include #include "aurora/lib/window.hpp" +#include "command_console.hpp" #include "dusk/io.hpp" #include "input.hpp" #include "prelaunch.hpp" @@ -172,6 +173,19 @@ void handle_event(const SDL_Event& event) noexcept { sConnectedGamepads.erase(event.gdevice.which); } input::handle_event(event); + // TODO: don't overlap with PAD bindings? + if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_SLASH) { + bool found = false; + for (auto& doc : sDocumentStack) { + if (auto* console = dynamic_cast(doc.get())) { + console->show(); + found = true; + } + } + if (!found) { + push_document(std::make_unique(), true, false); + } + } } Document& push_document(std::unique_ptr doc, bool show, bool passive) noexcept { diff --git a/src/m_Do/m_Do_main.cpp b/src/m_Do/m_Do_main.cpp index a904f23b30..a59ab186e7 100644 --- a/src/m_Do/m_Do_main.cpp +++ b/src/m_Do/m_Do_main.cpp @@ -658,7 +658,6 @@ int game_main(int argc, char* argv[]) { dusk::texture_replacements::reload(); dusk::ui::initialize(); dusk::ui::push_document(std::make_unique(), true, true); - dusk::ui::push_document(std::make_unique(), true, true); dusk::ui::push_document(std::make_unique(), false); // Invalidate a bad saved isoPath so that Dusklight can't get blocked from starting up.