summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author0xFMD <30713087+0xFMD@users.noreply.github.com>2025-08-31 19:14:39 +0300
committerGitHub <noreply@github.com>2025-08-31 18:14:39 +0200
commit5bb8adbc3228901d199e8d22d6f712bd1d7d4e15 (patch)
tree4bc61196518c37c7845380a723b757b9bf602449
parentea42041f936d5810c5cfa45d6bece12dde2fd9b6 (diff)
dispatchers: allow window address in swapwindow (#11518)
-rw-r--r--hyprtester/src/tests/main/window.cpp113
-rw-r--r--src/managers/KeybindManager.cpp27
2 files changed, 127 insertions, 13 deletions
diff --git a/hyprtester/src/tests/main/window.cpp b/hyprtester/src/tests/main/window.cpp
index ec4ba20c..306d0d8f 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 0eab9689..536f85b1 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 {};
}