diff --git a/hyprtester/src/tests/main/window.cpp b/hyprtester/src/tests/main/window.cpp index ec4ba20ce..306d0d8f4 100644 --- a/hyprtester/src/tests/main/window.cpp +++ b/hyprtester/src/tests/main/window.cpp @@ -20,6 +20,117 @@ static bool spawnKitty(const std::string& class_) { return true; } +static std::string getWindowAttribute(const std::string& winInfo, const std::string& attr) { + auto pos = winInfo.find(attr); + if (pos == std::string::npos) { + NLog::log("{}Wrong window attribute", Colors::RED); + ret = 1; + return "Wrong window attribute"; + } + auto pos2 = winInfo.find('\n', pos); + return winInfo.substr(pos, pos2 - pos); +} + +static std::string getWindowAddress(const std::string& winInfo) { + auto pos = winInfo.find("Window "); + auto pos2 = winInfo.find(" -> "); + if (pos == std::string::npos || pos2 == std::string::npos) { + NLog::log("{}Wrong window info", Colors::RED); + ret = 1; + return "Wrong window info"; + } + return winInfo.substr(pos + 7, pos2 - pos - 7); +} + +static void testSwapWindow() { + NLog::log("{}Testing swapwindow", Colors::GREEN); + + // test on workspace "swapwindow" + NLog::log("{}Switching to workspace \"swapwindow\"", Colors::YELLOW); + getFromSocket("/dispatch workspace name:swapwindow"); + + if (!Tests::spawnKitty("kitty_A")) { + ret = 1; + return; + } + + if (!Tests::spawnKitty("kitty_B")) { + ret = 1; + return; + } + + NLog::log("{}Expecting 2 windows", Colors::YELLOW); + EXPECT(Tests::windowCount(), 2); + + // Test swapwindow by direction + { + getFromSocket("/dispatch focuswindow class:kitty_A"); + auto pos = getWindowAttribute(getFromSocket("/activewindow"), "at:"); + NLog::log("{}Testing kitty_A {}, swapwindow with direction 'l'", Colors::YELLOW, pos); + + OK(getFromSocket("/dispatch swapwindow l")); + OK(getFromSocket("/dispatch focuswindow class:kitty_B")); + + EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("{}", pos)); + } + + // Test swapwindow by class + { + getFromSocket("/dispatch focuswindow class:kitty_A"); + auto pos = getWindowAttribute(getFromSocket("/activewindow"), "at:"); + NLog::log("{}Testing kitty_A {}, swapwindow with class:kitty_B", Colors::YELLOW, pos); + + OK(getFromSocket("/dispatch swapwindow class:kitty_B")); + OK(getFromSocket("/dispatch focuswindow class:kitty_B")); + + EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("{}", pos)); + } + + // Test swapwindow by address + { + getFromSocket("/dispatch focuswindow class:kitty_B"); + auto addr = getWindowAddress(getFromSocket("/activewindow")); + getFromSocket("/dispatch focuswindow class:kitty_A"); + auto pos = getWindowAttribute(getFromSocket("/activewindow"), "at:"); + NLog::log("{}Testing kitty_A {}, swapwindow with address:0x{}(kitty_B)", Colors::YELLOW, pos, addr); + + OK(getFromSocket(std::format("/dispatch swapwindow address:0x{}", addr))); + OK(getFromSocket(std::format("/dispatch focuswindow address:0x{}", addr))); + + EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("{}", pos)); + } + + NLog::log("{}Testing swapwindow with fullscreen. Expecting to fail", Colors::YELLOW); + { + OK(getFromSocket("/dispatch fullscreen")); + + auto str = getFromSocket("/dispatch swapwindow l"); + EXPECT_CONTAINS(str, "Can't swap fullscreen window"); + + OK(getFromSocket("/dispatch fullscreen")); + } + + NLog::log("{}Testing swapwindow with different workspace", Colors::YELLOW); + { + getFromSocket("/dispatch focuswindow class:kitty_B"); + auto addr = getWindowAddress(getFromSocket("/activewindow")); + auto ws = getWindowAttribute(getFromSocket("/activewindow"), "workspace:"); + NLog::log("{}Sending address:0x{}(kitty_B) to workspace \"swapwindow2\"", Colors::YELLOW, addr); + + OK(getFromSocket("/dispatch movetoworkspacesilent name:swapwindow2")); + OK(getFromSocket(std::format("/dispatch swapwindow address:0x{}", addr))); + getFromSocket("/dispatch focuswindow class:kitty_B"); + EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("{}", ws)); + } + + // kill all + NLog::log("{}Killing all windows", Colors::YELLOW); + Tests::killAllWindows(); + + NLog::log("{}Expecting 0 windows", Colors::YELLOW); + EXPECT(Tests::windowCount(), 0); +} + static bool test() { NLog::log("{}Testing windows", Colors::GREEN); @@ -115,6 +226,8 @@ static bool test() { NLog::log("{}Expecting 0 windows", Colors::YELLOW); EXPECT(Tests::windowCount(), 0); + testSwapWindow(); + return !ret; } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 0eab96895..536f85b10 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1608,15 +1608,9 @@ SDispatchResult CKeybindManager::focusCurrentOrLast(std::string args) { } SDispatchResult CKeybindManager::swapActive(std::string args) { - char arg = args[0]; - - if (!isDirection(args)) { - Debug::log(ERR, "Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg); - return {.success = false, .error = std::format("Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)}; - } - - Debug::log(LOG, "Swapping active window in direction {}", arg); - const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock(); + char arg = args[0]; + const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock(); + PHLWINDOW PWINDOWTOCHANGETO = nullptr; if (!PLASTWINDOW) return {.success = false, .error = "Window to swap with not found"}; @@ -1624,14 +1618,21 @@ SDispatchResult CKeybindManager::swapActive(std::string args) { if (PLASTWINDOW->isFullscreen()) return {.success = false, .error = "Can't swap fullscreen window"}; - const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg); - if (!PWINDOWTOCHANGETO) - return {.success = false, .error = "Window to swap with not found"}; + if (isDirection(args)) + PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg); + else + PWINDOWTOCHANGETO = g_pCompositor->getWindowByRegex(args); + + if (!PWINDOWTOCHANGETO || PWINDOWTOCHANGETO == PLASTWINDOW) { + Debug::log(ERR, "Can't swap with {}, invalid window", args); + return {.success = false, .error = std::format("Can't swap with {}, invalid window", args)}; + } + + Debug::log(LOG, "Swapping active window with {}", args); updateRelativeCursorCoords(); g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, PWINDOWTOCHANGETO); PLASTWINDOW->warpCursor(); - return {}; }