mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-24 08:23:48 -07:00
masterlayout: add previous mode for focusmaster command (#11361)
This commit is contained in:
71
hyprtester/src/tests/main/master.cpp
Normal file
71
hyprtester/src/tests/main/master.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include "../shared.hpp"
|
||||
#include "../../shared.hpp"
|
||||
#include "../../hyprctlCompat.hpp"
|
||||
#include "tests.hpp"
|
||||
|
||||
static int ret = 0;
|
||||
|
||||
static void focusMasterPrevious() {
|
||||
// setup
|
||||
NLog::log("{}Spawning 1 master and 3 slave windows", Colors::YELLOW);
|
||||
// order of windows set according to new_status = master (set in test.conf)
|
||||
for (auto const& win : {"slave1", "slave2", "slave3", "master"}) {
|
||||
if (!Tests::spawnKitty(win)) {
|
||||
NLog::log("{}Failed to spawn kitty with win class `{}`", Colors::RED, win);
|
||||
++TESTS_FAILED;
|
||||
ret = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
NLog::log("{}Ensuring focus is on master before testing", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch layoutmsg focusmaster master"));
|
||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "class: master");
|
||||
|
||||
// test
|
||||
NLog::log("{}Testing fallback to focusmaster auto", Colors::YELLOW);
|
||||
|
||||
OK(getFromSocket("/dispatch layoutmsg focusmaster previous"));
|
||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "class: slave1");
|
||||
|
||||
NLog::log("{}Testing focusing from slave to master", Colors::YELLOW);
|
||||
|
||||
OK(getFromSocket("/dispatch layoutmsg cyclenext noloop"));
|
||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "class: slave2");
|
||||
OK(getFromSocket("/dispatch layoutmsg focusmaster previous"));
|
||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "class: master");
|
||||
|
||||
NLog::log("{}Testing focusing on previous window", Colors::YELLOW);
|
||||
|
||||
OK(getFromSocket("/dispatch layoutmsg focusmaster previous"));
|
||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "class: slave2");
|
||||
|
||||
NLog::log("{}Testing focusing back to master", Colors::YELLOW);
|
||||
|
||||
OK(getFromSocket("/dispatch layoutmsg focusmaster previous"));
|
||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "class: master");
|
||||
|
||||
// clean up
|
||||
NLog::log("{}Killing all windows", Colors::YELLOW);
|
||||
Tests::killAllWindows();
|
||||
}
|
||||
|
||||
static bool test() {
|
||||
NLog::log("{}Testing Master layout", Colors::GREEN);
|
||||
|
||||
// setup
|
||||
OK(getFromSocket("/dispatch workspace name:master"));
|
||||
OK(getFromSocket("/keyword general:layout master"));
|
||||
|
||||
// test
|
||||
NLog::log("{}Testing `focusmaster previous` layoutmsg", Colors::GREEN);
|
||||
focusMasterPrevious();
|
||||
|
||||
// clean up
|
||||
NLog::log("Cleaning up", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace 1"));
|
||||
OK(getFromSocket("/reload"));
|
||||
|
||||
return !ret;
|
||||
}
|
||||
|
||||
REGISTER_TEST_FN(test);
|
@@ -25,7 +25,7 @@ static bool test() {
|
||||
|
||||
// test on workspace "window"
|
||||
NLog::log("{}Switching to workspace 1", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace 1"));
|
||||
getFromSocket("/dispatch workspace 1"); // no OK: we might be on 1 already
|
||||
|
||||
OK(getFromSocket("/keyword workspace 5, monitor:HEADLESS-2, persistent:1"));
|
||||
OK(getFromSocket("/keyword workspace 6, monitor:HEADLESS-PERSISTENT-TEST, persistent:1"));
|
||||
|
@@ -1123,9 +1123,10 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
||||
|
||||
return 0;
|
||||
}
|
||||
// focusmaster <master | auto>
|
||||
// focusmaster <master | previous | auto>
|
||||
// first message argument can have the following values:
|
||||
// * master - keep the focus at the new master, even if it was focused before
|
||||
// * previous - focus window which was previously switched from using `focusmaster previous` command, otherwise fallback to `auto`
|
||||
// * auto (default) - swap the focus with the first child, if the current focus was master, otherwise focus master
|
||||
else if (command == "focusmaster") {
|
||||
const auto PWINDOW = header.pWindow;
|
||||
@@ -1138,21 +1139,35 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
||||
if (!PMASTER)
|
||||
return 0;
|
||||
|
||||
const auto& ARG = vars[1]; // returns empty string if out of bounds
|
||||
|
||||
if (PMASTER->pWindow.lock() != PWINDOW) {
|
||||
switchToWindow(PMASTER->pWindow.lock());
|
||||
} else if (vars.size() >= 2 && vars[1] == "master") {
|
||||
// save previously focused window (only for `previous` mode)
|
||||
if (ARG == "previous")
|
||||
getMasterWorkspaceData(PWINDOW->workspaceID())->focusMasterPrev = PWINDOW;
|
||||
return 0;
|
||||
} else {
|
||||
// if master is focused keep master focused (don't do anything)
|
||||
}
|
||||
|
||||
const auto focusAuto = [&]() {
|
||||
// focus first non-master window
|
||||
for (auto const& n : m_masterNodesData) {
|
||||
if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) {
|
||||
switchToWindow(n.pWindow.lock());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (ARG == "master")
|
||||
return 0;
|
||||
// switch to previously saved window
|
||||
else if (ARG == "previous") {
|
||||
const auto PREVWINDOW = getMasterWorkspaceData(PWINDOW->workspaceID())->focusMasterPrev.lock();
|
||||
const bool VALID = validMapped(PREVWINDOW) && PWINDOW->workspaceID() == PREVWINDOW->workspaceID() && PWINDOW != PREVWINDOW;
|
||||
VALID ? switchToWindow(PREVWINDOW) : focusAuto();
|
||||
} else
|
||||
focusAuto();
|
||||
} else if (command == "cyclenext") {
|
||||
const auto PWINDOW = header.pWindow;
|
||||
|
||||
|
@@ -42,6 +42,8 @@ struct SMasterNodeData {
|
||||
struct SMasterWorkspaceData {
|
||||
WORKSPACEID workspaceID = WORKSPACE_INVALID;
|
||||
eOrientation orientation = ORIENTATION_LEFT;
|
||||
// Previously focused non-master window when `focusmaster previous` command was issued
|
||||
PHLWINDOWREF focusMasterPrev;
|
||||
|
||||
//
|
||||
bool operator==(const SMasterWorkspaceData& rhs) const {
|
||||
|
Reference in New Issue
Block a user