From cf87294a8cd10d4551c6e8f22d2da8f7f36fd694 Mon Sep 17 00:00:00 2001 From: aoqia194 <30682549+aoqia194@users.noreply.github.com> Date: Thu, 7 Aug 2025 06:22:46 +1000 Subject: [PATCH] feat: Add EventViewClosed event (#2377) Where one door opens, another one closes (said someone) and in this situation i mean view, because there's no event for closing a view only opening one, so please add this :c ### Problem description Simply adds an **EventViewClosed** to match the pre-existing **EventViewOpened**. Also fixes the issue where EventViewOpened wouldn't trigger for windows that were popups (even if they are technically a View. ### Implementation description I mirrored the current functionality of EventViewOpened for closing. --------- Co-authored-by: paxcut <53811119+paxcut@users.noreply.github.com> --- CONTRIBUTING.md | 4 +- .../include/hex/api/events/events_gui.hpp | 16 +++++--- lib/libimhex/include/hex/ui/view.hpp | 7 +++- lib/libimhex/source/ui/view.cpp | 14 ++++++- main/gui/source/window/window.cpp | 39 ++++++++++++------- 5 files changed, 53 insertions(+), 27 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a8c314f32..41121cb6c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,9 +10,7 @@ This document is a guide for developers who want to contribute to ImHex in any w If you'd like to add new features, the best way to start is by joining our Discord and telling us about your idea. We can then discuss the best way to implement it and how it should be integrated into ImHex or if it should be done in a separate plugin. -There are standalone plugin templates that use ImHex as a submodule. You can find them here: -- https://github.com/WerWolv/ImHex-Cpp-Plugin-Template -- https://github.com/WerWolv/ImHex-Rust-Plugin-Template +There are standalone plugin templates that use ImHex as a submodule. You can find them located in the README's [Plugin Development](README.md#plugin-development) section. ### Adding a new language diff --git a/lib/libimhex/include/hex/api/events/events_gui.hpp b/lib/libimhex/include/hex/api/events/events_gui.hpp index d8c7b328d..074d35010 100644 --- a/lib/libimhex/include/hex/api/events/events_gui.hpp +++ b/lib/libimhex/include/hex/api/events/events_gui.hpp @@ -9,13 +9,10 @@ namespace hex { class View; } /* GUI events definitions */ namespace hex { - /** - * @brief Signals a newly opened window + * @brief Signals a newly opened view * - * This event is sent when the window has just been opened and docked by the Window manager. - * - * FIXME: In the event that a newly created window is already docked, this will not be sent. + * This event is sent when the view has just been opened by the Window manager. * * FIXME: This is currently only used for the introduction tutorial. * If the event's only purpose is this, maybe rename it? @@ -24,6 +21,15 @@ namespace hex { */ EVENT_DEF(EventViewOpened, View*); + /** + * @brief Signals a newly closed view + * + * This event is sent when the view has just been closed. + * + * @param view the closed view reference + */ + EVENT_DEF(EventViewClosed, View*); + /** * @brief Signals a change in the DPI scale. * diff --git a/lib/libimhex/include/hex/ui/view.hpp b/lib/libimhex/include/hex/ui/view.hpp index b3106bd5a..5d4290ad2 100644 --- a/lib/libimhex/include/hex/ui/view.hpp +++ b/lib/libimhex/include/hex/ui/view.hpp @@ -98,7 +98,10 @@ namespace hex { [[nodiscard]] bool didWindowJustOpen(); void setWindowJustOpened(bool state); - void trackViewOpenState(); + [[nodiscard]] bool didWindowJustClose(); + void setWindowJustClosed(bool state); + + void trackViewState(); static void discardNavigationRequests(); @@ -125,7 +128,7 @@ namespace hex { UnlocalizedString m_unlocalizedViewName; bool m_windowOpen = false, m_prevWindowOpen = false; std::map m_shortcuts; - bool m_windowJustOpened = false; + bool m_windowJustOpened = false, m_windowJustClosed = false; const char *m_icon; bool m_focused = false; diff --git a/lib/libimhex/source/ui/view.cpp b/lib/libimhex/source/ui/view.cpp index 81cde98d6..e8becf468 100644 --- a/lib/libimhex/source/ui/view.cpp +++ b/lib/libimhex/source/ui/view.cpp @@ -56,13 +56,23 @@ namespace hex { return std::exchange(m_windowJustOpened, false); } - void View::setWindowJustOpened(bool state) { + void View::setWindowJustOpened(const bool state) { m_windowJustOpened = state; } - void View::trackViewOpenState() { + bool View::didWindowJustClose() { + return std::exchange(m_windowJustClosed, false); + } + + void View::setWindowJustClosed(const bool state) { + m_windowJustClosed = state; + } + + void View::trackViewState() { if (m_windowOpen && !m_prevWindowOpen) this->setWindowJustOpened(true); + else if (!m_windowOpen && m_prevWindowOpen) + this->setWindowJustClosed(true); m_prevWindowOpen = m_windowOpen; } diff --git a/main/gui/source/window/window.cpp b/main/gui/source/window/window.cpp index 2cc157717..8a632aae1 100644 --- a/main/gui/source/window/window.cpp +++ b/main/gui/source/window/window.cpp @@ -773,38 +773,47 @@ namespace hex { ImGui::SetNextWindowClass(&windowClass); - auto window = ImGui::FindWindowByName(view->getName().c_str()); + const auto window = ImGui::FindWindowByName(view->getName().c_str()); if (window != nullptr && window->DockNode == nullptr) ImGui::SetNextWindowBgAlpha(1.0F); // Draw view view->draw(); - view->trackViewOpenState(); + view->trackViewState(); - if (view->getWindowOpenState()) { - // Get the currently focused view - if (window != nullptr && (window->Flags & ImGuiWindowFlags_Popup) != ImGuiWindowFlags_Popup) { + if (window != nullptr) { + if (view->getWindowOpenState()) { + // Get the currently focused view auto windowName = View::toWindowName(name); - ImGui::Begin(windowName.c_str()); + bool focused = false; - // Detect if the window is focused - const bool focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_NoPopupHierarchy); - view->setFocused(focused); + const bool windowIsPopup = (window->Flags & ImGuiWindowFlags_Popup) == ImGuiWindowFlags_Popup; + if (!windowIsPopup) { + ImGui::Begin(windowName.c_str()); + + // Detect if the window is focused + focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_NoPopupHierarchy); + view->setFocused(focused); + } - // Dock the window if it's not already docked if (view->didWindowJustOpen()) { - if (!ImGui::IsWindowDocked()) + // Dock the window if it's not already docked + if (!windowIsPopup && !ImGui::IsWindowDocked()) ImGui::DockBuilderDockWindow(windowName.c_str(), ImHexApi::System::getMainDockSpaceId()); EventViewOpened::post(view.get()); } // Pass on currently pressed keys to the shortcut handler - for (const auto &key : m_pressedKeys) { - ShortcutManager::process(view.get(), io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl, io.KeyAlt, io.KeyShift, io.ConfigMacOSXBehaviors ? io.KeyCtrl : io.KeySuper, focused, key); - } + if (!windowIsPopup) { + for (const auto &key : m_pressedKeys) { + ShortcutManager::process(view.get(), io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl, io.KeyAlt, io.KeyShift, io.ConfigMacOSXBehaviors ? io.KeyCtrl : io.KeySuper, focused, key); + } - ImGui::End(); + ImGui::End(); + } + } else if (view->didWindowJustClose()) { + EventViewClosed::post(view.get()); } } }