diff --git a/src/gui/toolbars/control_bar.cpp b/src/gui/toolbars/control_bar.cpp index 9f0cf30..a8fef77 100644 --- a/src/gui/toolbars/control_bar.cpp +++ b/src/gui/toolbars/control_bar.cpp @@ -163,6 +163,7 @@ int Render::ControlBar(std::shared_ptr& props) { ImVec2 btn_min = ImGui::GetItemRectMin(); ImVec2 btn_size_actual = ImGui::GetItemRectSize(); + props->display_selectable_hovered_ = false; if (ImGui::BeginPopup("display")) { ImGui::SetWindowFontScale(0.5f); for (int i = 0; i < props->display_info_list_.size(); i++) { @@ -178,8 +179,9 @@ int Render::ControlBar(std::shared_ptr& props) { props->control_data_label_.c_str()); } } - props->display_selectable_hovered_ = ImGui::IsWindowHovered(); } + props->display_selectable_hovered_ = + ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); ImGui::EndPopup(); } @@ -486,4 +488,4 @@ int Render::NetTrafficStats(std::shared_ptr& props) { return 0; } -} // namespace crossdesk \ No newline at end of file +} // namespace crossdesk diff --git a/tests/display_popup_hover_state_test.cpp b/tests/display_popup_hover_state_test.cpp new file mode 100644 index 0000000..b5ebef8 --- /dev/null +++ b/tests/display_popup_hover_state_test.cpp @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include + +namespace { + +std::filesystem::path FindRepoRoot() { + std::filesystem::path current = std::filesystem::current_path(); + while (!current.empty()) { + if (std::filesystem::exists(current / "xmake.lua") && + std::filesystem::exists(current / "src/gui/toolbars/control_bar.cpp")) { + return current; + } + current = current.parent_path(); + } + return {}; +} + +std::string ReadFile(const std::filesystem::path& path) { + std::ifstream file(path, std::ios::binary); + if (!file) { + return {}; + } + + std::ostringstream stream; + stream << file.rdbuf(); + return stream.str(); +} + +bool ExpectContains(const char* name, const std::string& value, + const std::string& expected) { + if (value.find(expected) != std::string::npos) { + return true; + } + + std::cerr << name << " missing expected text: " << expected << "\n"; + return false; +} + +bool ExpectResetBeforeDisplayPopup(const std::string& value) { + const std::string reset = "props->display_selectable_hovered_ = false;"; + const std::string popup = "ImGui::BeginPopup(\"display\")"; + const size_t reset_pos = value.find(reset); + const size_t popup_pos = value.find(popup); + + if (reset_pos != std::string::npos && popup_pos != std::string::npos && + reset_pos < popup_pos) { + return true; + } + + std::cerr << "control_bar.cpp must clear display_selectable_hovered_ before " + "checking the display popup\n"; + return false; +} + +} // namespace + +int main() { + const std::filesystem::path repo_root = FindRepoRoot(); + if (repo_root.empty()) { + std::cerr << "failed to locate repository root\n"; + return 1; + } + + const std::string control_bar = + ReadFile(repo_root / "src/gui/toolbars/control_bar.cpp"); + + bool ok = true; + ok &= ExpectContains("control_bar.cpp", control_bar, + "props->display_selectable_hovered_ = false;"); + ok &= ExpectContains("control_bar.cpp", control_bar, + "ImGui::IsWindowHovered(" + "ImGuiHoveredFlags_RootAndChildWindows)"); + ok &= ExpectResetBeforeDisplayPopup(control_bar); + return ok ? 0 : 1; +} diff --git a/xmake/targets.lua b/xmake/targets.lua index 5cdd9af..f3e3db5 100644 --- a/xmake/targets.lua +++ b/xmake/targets.lua @@ -54,6 +54,11 @@ function setup_targets() set_default(false) add_files("tests/windows_mouse_controller_safety_test.cpp") + target("display_popup_hover_state_test") + set_kind("binary") + set_default(false) + add_files("tests/display_popup_hover_state_test.cpp") + target("screen_capturer") set_kind("object") add_deps("rd_log", "common")