layouts: apply [min|max]size window rules to dwindle & master layouts (#11898)
Uses min/max rules in the tiled layouts, akin to pseudotiling
This commit is contained in:
parent
6582f42db8
commit
7fcaf332e8
6 changed files with 105 additions and 5 deletions
|
|
@ -228,6 +228,48 @@ static bool test() {
|
||||||
|
|
||||||
testSwapWindow();
|
testSwapWindow();
|
||||||
|
|
||||||
|
NLog::log("{}Testing minsize/maxsize rules for tiled windows", Colors::YELLOW);
|
||||||
|
{
|
||||||
|
// Enable the config for testing, test max/minsize for tiled windows and centering
|
||||||
|
OK(getFromSocket("/keyword misc:size_limits_tiled 1"));
|
||||||
|
OK(getFromSocket("/keyword windowrule maxsize 1500 500, class:kitty_maxsize"));
|
||||||
|
OK(getFromSocket("/keyword windowrule minsize 1200 500, class:kitty_maxsize"));
|
||||||
|
if (!spawnKitty("kitty_maxsize"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto dwindle = getFromSocket("/activewindow");
|
||||||
|
EXPECT_CONTAINS(dwindle, "size: 1500,500");
|
||||||
|
EXPECT_CONTAINS(dwindle, "at: 210,290");
|
||||||
|
|
||||||
|
if (!spawnKitty("kitty_maxsize"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
EXPECT_CONTAINS(getFromSocket("/activewindow"), "size: 1200,500");
|
||||||
|
|
||||||
|
Tests::killAllWindows();
|
||||||
|
EXPECT(Tests::windowCount(), 0);
|
||||||
|
|
||||||
|
OK(getFromSocket("/keyword general:layout master"));
|
||||||
|
|
||||||
|
if (!spawnKitty("kitty_maxsize"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto master = getFromSocket("/activewindow");
|
||||||
|
EXPECT_CONTAINS(master, "size: 1500,500");
|
||||||
|
EXPECT_CONTAINS(master, "at: 210,290");
|
||||||
|
|
||||||
|
if (!spawnKitty("kitty_maxsize"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
OK(getFromSocket("/dispatch focuswindow class:kitty_maxsize"));
|
||||||
|
EXPECT_CONTAINS(getFromSocket("/activewindow"), "size: 1200,500")
|
||||||
|
|
||||||
|
NLog::log("{}Reloading config", Colors::YELLOW);
|
||||||
|
OK(getFromSocket("/reload"));
|
||||||
|
Tests::killAllWindows();
|
||||||
|
EXPECT(Tests::windowCount(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
NLog::log("{}Testing window rules", Colors::YELLOW);
|
NLog::log("{}Testing window rules", Colors::YELLOW);
|
||||||
if (!spawnKitty("wr_kitty"))
|
if (!spawnKitty("wr_kitty"))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -247,6 +289,7 @@ static bool test() {
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "special:magic");
|
EXPECT_CONTAINS(getFromSocket("/activewindow"), "special:magic");
|
||||||
EXPECT_NOT_CONTAINS(str, "workspace: 9");
|
EXPECT_NOT_CONTAINS(str, "workspace: 9");
|
||||||
}
|
}
|
||||||
|
|
||||||
NLog::log("{}Testing faulty rules", Colors::YELLOW);
|
NLog::log("{}Testing faulty rules", Colors::YELLOW);
|
||||||
{
|
{
|
||||||
const auto PARAM = "Invalid parameter";
|
const auto PARAM = "Invalid parameter";
|
||||||
|
|
|
||||||
|
|
@ -1339,6 +1339,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||||
.type = CONFIG_OPTION_BOOL,
|
.type = CONFIG_OPTION_BOOL,
|
||||||
.data = SConfigOptionDescription::SBoolData{false},
|
.data = SConfigOptionDescription::SBoolData{false},
|
||||||
},
|
},
|
||||||
|
SConfigOptionDescription{
|
||||||
|
.value = "misc:size_limits_tiled",
|
||||||
|
.description = "whether to apply minsize and maxsize rules to tiled windows",
|
||||||
|
.type = CONFIG_OPTION_BOOL,
|
||||||
|
.data = SConfigOptionDescription::SBoolData{false},
|
||||||
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* binds:
|
* binds:
|
||||||
|
|
|
||||||
|
|
@ -522,6 +522,7 @@ CConfigManager::CConfigManager() {
|
||||||
registerConfigVar("misc:anr_missed_pings", Hyprlang::INT{5});
|
registerConfigVar("misc:anr_missed_pings", Hyprlang::INT{5});
|
||||||
registerConfigVar("misc:screencopy_force_8b", Hyprlang::INT{1});
|
registerConfigVar("misc:screencopy_force_8b", Hyprlang::INT{1});
|
||||||
registerConfigVar("misc:disable_scale_notification", Hyprlang::INT{0});
|
registerConfigVar("misc:disable_scale_notification", Hyprlang::INT{0});
|
||||||
|
registerConfigVar("misc:size_limits_tiled", Hyprlang::INT{0});
|
||||||
|
|
||||||
registerConfigVar("group:insert_after_current", Hyprlang::INT{1});
|
registerConfigVar("group:insert_after_current", Hyprlang::INT{1});
|
||||||
registerConfigVar("group:focus_removed_window", Hyprlang::INT{1});
|
registerConfigVar("group:focus_removed_window", Hyprlang::INT{1});
|
||||||
|
|
|
||||||
|
|
@ -634,7 +634,8 @@ bool CWindow::isHidden() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::applyDynamicRule(const SP<CWindowRule>& r) {
|
void CWindow::applyDynamicRule(const SP<CWindowRule>& r) {
|
||||||
const eOverridePriority priority = r->m_execRule ? PRIORITY_SET_PROP : PRIORITY_WINDOW_RULE;
|
const eOverridePriority priority = r->m_execRule ? PRIORITY_SET_PROP : PRIORITY_WINDOW_RULE;
|
||||||
|
static auto PCLAMP_TILED = CConfigValue<Hyprlang::INT>("misc:size_limits_tiled");
|
||||||
|
|
||||||
switch (r->m_ruleType) {
|
switch (r->m_ruleType) {
|
||||||
case CWindowRule::RULE_TAG: {
|
case CWindowRule::RULE_TAG: {
|
||||||
|
|
@ -751,7 +752,7 @@ void CWindow::applyDynamicRule(const SP<CWindowRule>& r) {
|
||||||
}
|
}
|
||||||
case CWindowRule::RULE_MAXSIZE: {
|
case CWindowRule::RULE_MAXSIZE: {
|
||||||
try {
|
try {
|
||||||
if (!m_isFloating)
|
if (!m_isFloating && !sc<bool>(*PCLAMP_TILED))
|
||||||
return;
|
return;
|
||||||
const auto VEC = configStringToVector2D(r->m_rule.substr(8));
|
const auto VEC = configStringToVector2D(r->m_rule.substr(8));
|
||||||
if (VEC.x < 1 || VEC.y < 1) {
|
if (VEC.x < 1 || VEC.y < 1) {
|
||||||
|
|
@ -767,7 +768,7 @@ void CWindow::applyDynamicRule(const SP<CWindowRule>& r) {
|
||||||
}
|
}
|
||||||
case CWindowRule::RULE_MINSIZE: {
|
case CWindowRule::RULE_MINSIZE: {
|
||||||
try {
|
try {
|
||||||
if (!m_isFloating)
|
if (!m_isFloating && !sc<bool>(*PCLAMP_TILED))
|
||||||
return;
|
return;
|
||||||
const auto VEC = configStringToVector2D(r->m_rule.substr(8));
|
const auto VEC = configStringToVector2D(r->m_rule.substr(8));
|
||||||
if (VEC.x < 1 || VEC.y < 1) {
|
if (VEC.x < 1 || VEC.y < 1) {
|
||||||
|
|
@ -1359,7 +1360,8 @@ int CWindow::surfacesCount() {
|
||||||
|
|
||||||
void CWindow::clampWindowSize(const std::optional<Vector2D> minSize, const std::optional<Vector2D> maxSize) {
|
void CWindow::clampWindowSize(const std::optional<Vector2D> minSize, const std::optional<Vector2D> maxSize) {
|
||||||
const Vector2D REALSIZE = m_realSize->goal();
|
const Vector2D REALSIZE = m_realSize->goal();
|
||||||
const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), maxSize.value_or(Vector2D{INFINITY, INFINITY}));
|
const Vector2D MAX = isFullscreen() ? Vector2D{INFINITY, INFINITY} : maxSize.value_or(Vector2D{INFINITY, INFINITY});
|
||||||
|
const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), MAX);
|
||||||
const Vector2D DELTA = REALSIZE - NEWSIZE;
|
const Vector2D DELTA = REALSIZE - NEWSIZE;
|
||||||
|
|
||||||
*m_realPosition = m_realPosition->goal() + DELTA / 2.0;
|
*m_realPosition = m_realPosition->goal() + DELTA / 2.0;
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,28 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||||
calcPos = calcPos + RESERVED.topLeft;
|
calcPos = calcPos + RESERVED.topLeft;
|
||||||
calcSize = calcSize - (RESERVED.topLeft + RESERVED.bottomRight);
|
calcSize = calcSize - (RESERVED.topLeft + RESERVED.bottomRight);
|
||||||
|
|
||||||
|
Vector2D availableSpace = calcSize;
|
||||||
|
|
||||||
|
static auto PCLAMP_TILED = CConfigValue<Hyprlang::INT>("misc:size_limits_tiled");
|
||||||
|
|
||||||
|
if (*PCLAMP_TILED) {
|
||||||
|
const auto borderSize = PWINDOW->getRealBorderSize();
|
||||||
|
Vector2D monitorAvailable = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight -
|
||||||
|
Vector2D{(double)(gapsOut.m_left + gapsOut.m_right), (double)(gapsOut.m_top + gapsOut.m_bottom)} - Vector2D{2.0 * borderSize, 2.0 * borderSize};
|
||||||
|
|
||||||
|
Vector2D minSize = PWINDOW->m_windowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}).clamp(Vector2D{0, 0}, monitorAvailable);
|
||||||
|
Vector2D maxSize =
|
||||||
|
PWINDOW->isFullscreen() ? Vector2D{INFINITY, INFINITY} : PWINDOW->m_windowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY}).clamp(Vector2D{0, 0}, monitorAvailable);
|
||||||
|
calcSize = calcSize.clamp(minSize, maxSize);
|
||||||
|
|
||||||
|
calcPos += (availableSpace - calcSize) / 2.0;
|
||||||
|
|
||||||
|
calcPos.x = std::clamp(calcPos.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x + gapsOut.m_left + borderSize,
|
||||||
|
PMONITOR->m_size.x + PMONITOR->m_position.x - PMONITOR->m_reservedBottomRight.x - gapsOut.m_right - calcSize.x - borderSize);
|
||||||
|
calcPos.y = std::clamp(calcPos.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y + gapsOut.m_top + borderSize,
|
||||||
|
PMONITOR->m_size.y + PMONITOR->m_position.y - PMONITOR->m_reservedBottomRight.y - gapsOut.m_bottom - calcSize.y - borderSize);
|
||||||
|
}
|
||||||
|
|
||||||
if (PWINDOW->onSpecialWorkspace() && !PWINDOW->isFullscreen()) {
|
if (PWINDOW->onSpecialWorkspace() && !PWINDOW->isFullscreen()) {
|
||||||
// if special, we adjust the coords a bit
|
// if special, we adjust the coords a bit
|
||||||
static auto PSCALEFACTOR = CConfigValue<Hyprlang::FLOAT>("dwindle:special_scale_factor");
|
static auto PSCALEFACTOR = CConfigValue<Hyprlang::FLOAT>("dwindle:special_scale_factor");
|
||||||
|
|
@ -626,7 +648,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||||
CBox wbox = PNODE->box;
|
CBox wbox = PNODE->box;
|
||||||
wbox.round();
|
wbox.round();
|
||||||
|
|
||||||
PWINDOW->m_pseudoSize = {std::clamp(PWINDOW->m_pseudoSize.x, 30.0, wbox.w), std::clamp(PWINDOW->m_pseudoSize.y, 30.0, wbox.h)};
|
Vector2D minSize = PWINDOW->m_windowData.minSize.valueOr(Vector2D{30.0, 30.0});
|
||||||
|
Vector2D maxSize = PWINDOW->m_windowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY});
|
||||||
|
Vector2D upperBound = Vector2D{std::min(maxSize.x, wbox.w), std::min(maxSize.y, wbox.h)};
|
||||||
|
|
||||||
|
PWINDOW->m_pseudoSize = PWINDOW->m_pseudoSize.clamp(minSize, upperBound);
|
||||||
|
|
||||||
PWINDOW->m_lastFloatingSize = PWINDOW->m_pseudoSize;
|
PWINDOW->m_lastFloatingSize = PWINDOW->m_pseudoSize;
|
||||||
PNODE->recalcSizePosRecursive(*PANIMATE == 0);
|
PNODE->recalcSizePosRecursive(*PANIMATE == 0);
|
||||||
|
|
|
||||||
|
|
@ -691,6 +691,28 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||||
calcPos = calcPos + RESERVED.topLeft;
|
calcPos = calcPos + RESERVED.topLeft;
|
||||||
calcSize = calcSize - (RESERVED.topLeft + RESERVED.bottomRight);
|
calcSize = calcSize - (RESERVED.topLeft + RESERVED.bottomRight);
|
||||||
|
|
||||||
|
Vector2D availableSpace = calcSize;
|
||||||
|
|
||||||
|
static auto PCLAMP_TILED = CConfigValue<Hyprlang::INT>("misc:size_limits_tiled");
|
||||||
|
|
||||||
|
if (*PCLAMP_TILED) {
|
||||||
|
const auto borderSize = PWINDOW->getRealBorderSize();
|
||||||
|
Vector2D monitorAvailable = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight -
|
||||||
|
Vector2D{(double)(gapsOut.m_left + gapsOut.m_right), (double)(gapsOut.m_top + gapsOut.m_bottom)} - Vector2D{2.0 * borderSize, 2.0 * borderSize};
|
||||||
|
|
||||||
|
Vector2D minSize = PWINDOW->m_windowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}).clamp(Vector2D{0, 0}, monitorAvailable);
|
||||||
|
Vector2D maxSize =
|
||||||
|
PWINDOW->isFullscreen() ? Vector2D{INFINITY, INFINITY} : PWINDOW->m_windowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY}).clamp(Vector2D{0, 0}, monitorAvailable);
|
||||||
|
calcSize = calcSize.clamp(minSize, maxSize);
|
||||||
|
|
||||||
|
calcPos += (availableSpace - calcSize) / 2.0;
|
||||||
|
|
||||||
|
calcPos.x = std::clamp(calcPos.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x + gapsOut.m_left + borderSize,
|
||||||
|
PMONITOR->m_size.x + PMONITOR->m_position.x - PMONITOR->m_reservedBottomRight.x - gapsOut.m_right - calcSize.x - borderSize);
|
||||||
|
calcPos.y = std::clamp(calcPos.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y + gapsOut.m_top + borderSize,
|
||||||
|
PMONITOR->m_size.y + PMONITOR->m_position.y - PMONITOR->m_reservedBottomRight.y - gapsOut.m_bottom - calcSize.y - borderSize);
|
||||||
|
}
|
||||||
|
|
||||||
if (PWINDOW->onSpecialWorkspace() && !PWINDOW->isFullscreen()) {
|
if (PWINDOW->onSpecialWorkspace() && !PWINDOW->isFullscreen()) {
|
||||||
static auto PSCALEFACTOR = CConfigValue<Hyprlang::FLOAT>("master:special_scale_factor");
|
static auto PSCALEFACTOR = CConfigValue<Hyprlang::FLOAT>("master:special_scale_factor");
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue