Skip to content

Commit beaad90

Browse files
committed
Focus is now recovered by all views. Fields of widgets can recover active status using Tab key.
1 parent 6799dfe commit beaad90

File tree

2 files changed

+52
-22
lines changed

2 files changed

+52
-22
lines changed

lib/libimhex/include/hex/ui/view.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,9 @@ namespace hex {
145145
* @brief A view that draws a regular window. This should be the default for most views
146146
*/
147147
class View::Window : public View {
148-
std::string m_focusedSubWindowName;
148+
ImGuiWindow *m_focusedSubWindow;
149149
public:
150-
explicit Window(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {}
150+
explicit Window(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon), m_focusedSubWindow(nullptr) {}
151151

152152
/**
153153
* @brief Draws help text for the view

lib/libimhex/source/ui/view.cpp

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -120,43 +120,73 @@ namespace hex {
120120

121121
void View::Window::draw(ImGuiWindowFlags extraFlags) {
122122
if (this->shouldDraw()) {
123-
if (!allowScroll())
124-
extraFlags |= ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
125-
126-
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
127123
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
128124

129125
const ImGuiContext& g = *ImGui::GetCurrentContext();
130126
bool foundTopFocused = false;
131-
std::string topFocusedWindowName;
127+
ImGuiWindow *imguiFocusedWindow = nullptr;
128+
ImGuiWindow *focusedSubWindow = nullptr;
129+
132130
if (g.NavWindow != nullptr) {
133-
topFocusedWindowName = g.NavWindow->Name;
131+
imguiFocusedWindow = g.NavWindow;
134132
foundTopFocused = true;
135133
}
136-
for (auto window : g.WindowsFocusOrder | std::views::reverse) {
137-
if (window == nullptr || !window->WasActive)
134+
for (auto focusedWindow: g.WindowsFocusOrder | std::views::reverse) {
135+
if (focusedWindow == nullptr || !focusedWindow->WasActive)
138136
continue;
139-
std::string windowName = window->Name;
137+
std::string focusedWindowName = focusedWindow->Name;
140138
if (!foundTopFocused) {
141-
topFocusedWindowName = windowName;
139+
imguiFocusedWindow = focusedWindow;
142140
foundTopFocused = true;
143141
}
144-
if (!windowName.contains("###hex.builtin.view."))
142+
if (imguiFocusedWindow == nullptr || !focusedWindowName.contains("###hex.builtin.view."))
145143
continue;
146-
auto focusedChild = window->NavLastChildNavWindow;
147-
if (focusedChild != nullptr)
148-
m_focusedSubWindowName.assign(focusedChild->Name);
144+
if (auto focusedChild = focusedWindow->NavLastChildNavWindow; focusedChild != nullptr)
145+
focusedSubWindow = focusedChild;
146+
else if (focusedWindow == focusedWindow->RootWindow)
147+
focusedSubWindow = focusedWindow;
148+
149149
break;
150150
}
151-
bool isParentFocused = m_focusedSubWindowName.starts_with(topFocusedWindowName);
152-
if (s_lastFocusedView == this && !ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) {
153-
std::string activeName = g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL";
154-
if ((activeName == "NULL" && (topFocusedWindowName == "##MainMenuBar" || topFocusedWindowName.starts_with("ImHexDockSpace") || isParentFocused))) {
155-
auto window = ImGui::FindWindowByName(m_focusedSubWindowName.c_str());
156-
ImGui::FocusWindow(window, ImGuiFocusRequestFlags_None);
151+
152+
std::string imguiFocusedWindowName = "NULL";
153+
if (imguiFocusedWindow != nullptr)
154+
imguiFocusedWindowName.assign(imguiFocusedWindow->Name);
155+
156+
std::string focusedSubWindowName;
157+
if (focusedSubWindow != nullptr || m_focusedSubWindow != nullptr) {
158+
focusedSubWindowName = focusedSubWindow != nullptr ? focusedSubWindow->Name : m_focusedSubWindow->Name;
159+
if (focusedSubWindow != nullptr && m_focusedSubWindow != nullptr) {
160+
std::string_view windowName = m_focusedSubWindow->Name;
161+
auto stringsVector = wolv::util::splitString(focusedSubWindowName, "/");
162+
if (stringsVector.back().contains("resize") || (focusedSubWindow == focusedSubWindow->RootWindow && windowName.starts_with(focusedSubWindowName)))
163+
focusedSubWindowName = windowName;
164+
else
165+
m_focusedSubWindow = focusedSubWindow;
166+
} else if (focusedSubWindow != nullptr)
167+
m_focusedSubWindow = focusedSubWindow;
168+
169+
bool windowAlreadyFocused = focusedSubWindowName == imguiFocusedWindowName;
170+
bool titleFocused = focusedSubWindowName.starts_with(title);
171+
172+
if (titleFocused && !windowAlreadyFocused) {
173+
174+
bool windowMayNeedFocus = focusedSubWindowName.starts_with(imguiFocusedWindowName);
175+
std::string activeName = g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL";
176+
177+
if ((activeName == "NULL" || windowMayNeedFocus) && (imguiFocusedWindowName == "##MainMenuBar" || imguiFocusedWindowName.starts_with("ImHexDockSpace") || imguiFocusedWindowName.contains("###hex.builtin.view."))) {
178+
if (m_focusedSubWindow == m_focusedSubWindow->RootWindow)
179+
ImGui::FocusWindow(m_focusedSubWindow, ImGuiFocusRequestFlags_RestoreFocusedChild);
180+
else
181+
ImGui::FocusWindow(m_focusedSubWindow, ImGuiFocusRequestFlags_None);
182+
}
157183
}
158184
}
159185

186+
if (!allowScroll())
187+
extraFlags |= ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
188+
189+
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
160190
if (ImGui::Begin(title.c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse | extraFlags | this->getWindowFlags())) {
161191
TutorialManager::setLastItemInteractiveHelpPopup([this]{ this->drawHelpText(); });
162192
this->drawContent();

0 commit comments

Comments
 (0)