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>
This commit is contained in:
aoqia194 2025-08-07 06:22:46 +10:00 committed by GitHub
parent 40b48f6460
commit cf87294a8c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 53 additions and 27 deletions

View File

@ -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

View File

@ -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.
*

View File

@ -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<Shortcut, ShortcutManager::ShortcutEntry> m_shortcuts;
bool m_windowJustOpened = false;
bool m_windowJustOpened = false, m_windowJustClosed = false;
const char *m_icon;
bool m_focused = false;

View File

@ -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;
}

View File

@ -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());
}
}
}