summaryrefslogtreecommitdiff
path: root/src/layout
diff options
context:
space:
mode:
authoroutfoxxed <outfoxxed@outfoxxed.me>2026-03-09 12:10:59 +0100
committerGitHub <noreply@github.com>2026-03-09 11:10:59 +0000
commit5cf53f581b8b383fe7b1bf9bb9e28c72394e2e16 (patch)
tree497bb4e7aecb82f27028ad00e81fd79606368f6c /src/layout
parent03f444e0ab1cabe79cf05f2291b168d9c7a7ab49 (diff)
layout/windowTarget: add visualBox (#13626)
Allows layouts to explicitly define the visual geometry of a tiled window.
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/target/Target.cpp11
-rw-r--r--src/layout/target/Target.hpp12
-rw-r--r--src/layout/target/WindowGroupTarget.cpp2
-rw-r--r--src/layout/target/WindowGroupTarget.hpp4
-rw-r--r--src/layout/target/WindowTarget.cpp99
-rw-r--r--src/layout/target/WindowTarget.hpp4
6 files changed, 72 insertions, 60 deletions
diff --git a/src/layout/target/Target.cpp b/src/layout/target/Target.cpp
index e433c237..e8ce48bd 100644
--- a/src/layout/target/Target.cpp
+++ b/src/layout/target/Target.cpp
@@ -7,9 +7,14 @@
using namespace Layout;
using namespace Hyprutils::Utils;
-void ITarget::setPositionGlobal(const CBox& box) {
+void ITarget::setPositionGlobal(const STargetBox& box) {
m_box = box;
- m_box.round();
+ m_box.logicalBox.round();
+ m_box.visualBox.round();
+}
+
+void ITarget::setPositionGlobal(const CBox& box) {
+ setPositionGlobal({.logicalBox = box});
}
void ITarget::assignToSpace(const SP<CSpace>& space, std::optional<Vector2D> focalPoint) {
@@ -57,7 +62,7 @@ PHLWORKSPACE ITarget::workspace() const {
}
CBox ITarget::position() const {
- return m_box;
+ return m_box.logicalBox;
}
void ITarget::rememberFloatingSize(const Vector2D& size) {
diff --git a/src/layout/target/Target.hpp b/src/layout/target/Target.hpp
index dcaefdb4..bae5eee5 100644
--- a/src/layout/target/Target.hpp
+++ b/src/layout/target/Target.hpp
@@ -25,6 +25,11 @@ namespace Layout {
std::optional<Vector2D> pos;
};
+ struct STargetBox {
+ CBox logicalBox;
+ CBox visualBox;
+ };
+
class ITarget {
public:
virtual ~ITarget() = default;
@@ -32,7 +37,8 @@ namespace Layout {
virtual eTargetType type() = 0;
// position is within its space
- virtual void setPositionGlobal(const CBox& box);
+ virtual void setPositionGlobal(const STargetBox& box);
+ void setPositionGlobal(const CBox& box);
virtual CBox position() const;
virtual void assignToSpace(const SP<CSpace>& space, std::optional<Vector2D> focalPoint = std::nullopt);
virtual void setSpaceGhost(const SP<CSpace>& space);
@@ -67,7 +73,7 @@ namespace Layout {
protected:
ITarget() = default;
- CBox m_box;
+ STargetBox m_box;
SP<CSpace> m_space;
WP<ITarget> m_self;
Vector2D m_floatingSize;
@@ -76,4 +82,4 @@ namespace Layout {
Vector2D m_pseudoSize = {1280, 720};
bool m_wasTiling = false;
};
-}; \ No newline at end of file
+};
diff --git a/src/layout/target/WindowGroupTarget.cpp b/src/layout/target/WindowGroupTarget.cpp
index 3b1dc91e..8f9260e2 100644
--- a/src/layout/target/WindowGroupTarget.cpp
+++ b/src/layout/target/WindowGroupTarget.cpp
@@ -23,7 +23,7 @@ eTargetType CWindowGroupTarget::type() {
return TARGET_TYPE_GROUP;
}
-void CWindowGroupTarget::setPositionGlobal(const CBox& box) {
+void CWindowGroupTarget::setPositionGlobal(const STargetBox& box) {
ITarget::setPositionGlobal(box);
updatePos();
diff --git a/src/layout/target/WindowGroupTarget.hpp b/src/layout/target/WindowGroupTarget.hpp
index 3d4b85a0..b3e79749 100644
--- a/src/layout/target/WindowGroupTarget.hpp
+++ b/src/layout/target/WindowGroupTarget.hpp
@@ -14,7 +14,7 @@ namespace Layout {
virtual eTargetType type();
- virtual void setPositionGlobal(const CBox& box);
+ virtual void setPositionGlobal(const STargetBox& box);
virtual void assignToSpace(const SP<CSpace>& space, std::optional<Vector2D> focalPoint = std::nullopt);
virtual PHLWINDOW window() const;
@@ -36,4 +36,4 @@ namespace Layout {
WP<Desktop::View::CGroup> m_group;
};
-}; \ No newline at end of file
+};
diff --git a/src/layout/target/WindowTarget.cpp b/src/layout/target/WindowTarget.cpp
index db03a385..bd94a8c9 100644
--- a/src/layout/target/WindowTarget.cpp
+++ b/src/layout/target/WindowTarget.cpp
@@ -29,14 +29,13 @@ eTargetType CWindowTarget::type() {
return TARGET_TYPE_WINDOW;
}
-void CWindowTarget::setPositionGlobal(const CBox& box) {
+void CWindowTarget::setPositionGlobal(const STargetBox& box) {
ITarget::setPositionGlobal(box);
updatePos();
}
void CWindowTarget::updatePos() {
-
g_pHyprRenderer->damageWindow(m_window.lock());
CScopeGuard x([this] { g_pHyprRenderer->damageWindow(m_window.lock()); });
@@ -47,11 +46,11 @@ void CWindowTarget::updatePos() {
return;
if (floating() && fullscreenMode() != FSMODE_MAXIMIZED) {
- m_window->m_position = m_box.pos();
- m_window->m_size = m_box.size();
+ m_window->m_position = m_box.logicalBox.pos();
+ m_window->m_size = m_box.logicalBox.size();
- *m_window->m_realPosition = m_box.pos();
- *m_window->m_realSize = m_box.size();
+ *m_window->m_realPosition = m_box.logicalBox.pos();
+ *m_window->m_realSize = m_box.logicalBox.size();
m_window->sendWindowSize();
m_window->updateWindowDecos();
@@ -64,21 +63,11 @@ void CWindowTarget::updatePos() {
// if we are in maximized, force the box to be max work area.
// TODO: this shouldn't be here.
if (fullscreenMode() == FSMODE_MAXIMIZED)
- ITarget::setPositionGlobal(m_space->workArea(floating()));
-
- const auto PMONITOR = m_space->workspace()->m_monitor;
- const auto PWORKSPACE = m_space->workspace();
+ ITarget::setPositionGlobal({.logicalBox = m_space->workArea(floating())});
- // for gaps outer
+ const auto PMONITOR = m_space->workspace()->m_monitor;
+ const auto PWORKSPACE = m_space->workspace();
const auto MONITOR_WORKAREA = m_space->workArea();
- const bool DISPLAYLEFT = STICKS(m_box.x, MONITOR_WORKAREA.x);
- const bool DISPLAYRIGHT = STICKS(m_box.x + m_box.w, MONITOR_WORKAREA.x + MONITOR_WORKAREA.w);
- const bool DISPLAYTOP = STICKS(m_box.y, MONITOR_WORKAREA.y);
- const bool DISPLAYBOTTOM = STICKS(m_box.y + m_box.h, MONITOR_WORKAREA.y + MONITOR_WORKAREA.h);
-
- // this is used for scrolling, so that the gaps are correct when a window is the full width and has neighbors
- const bool DISPLAYINVERSELEFT = STICKS(m_box.x, MONITOR_WORKAREA.x + MONITOR_WORKAREA.w);
- const bool DISPLAYINVERSERIGHT = STICKS(m_box.x + m_box.w, MONITOR_WORKAREA.x);
// get specific gaps and rules for this workspace,
// if user specified them in config
@@ -95,52 +84,64 @@ void CWindowTarget::updatePos() {
g_pHyprRenderer->damageWindow(window());
- static auto PGAPSINDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_in");
- auto* const PGAPSIN = sc<CCssGapData*>((PGAPSINDATA.ptr())->getData());
-
- auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
- CBox nodeBox = m_box;
+ CBox nodeBox = m_box.logicalBox;
nodeBox.round();
m_window->m_size = nodeBox.size();
m_window->m_position = nodeBox.pos();
- m_window->updateWindowDecos();
+ auto calcPos = m_box.visualBox.pos();
+ auto calcSize = m_box.visualBox.size();
- auto calcPos = m_window->m_position;
- auto calcSize = m_window->m_size;
+ if (m_box.visualBox.empty()) {
+ calcPos = nodeBox.pos();
+ calcSize = nodeBox.size();
+ // for gaps outer
+ const bool DISPLAYLEFT = STICKS(m_box.logicalBox.x, MONITOR_WORKAREA.x);
+ const bool DISPLAYRIGHT = STICKS(m_box.logicalBox.x + m_box.logicalBox.w, MONITOR_WORKAREA.x + MONITOR_WORKAREA.w);
+ const bool DISPLAYTOP = STICKS(m_box.logicalBox.y, MONITOR_WORKAREA.y);
+ const bool DISPLAYBOTTOM = STICKS(m_box.logicalBox.y + m_box.logicalBox.h, MONITOR_WORKAREA.y + MONITOR_WORKAREA.h);
- const static auto REQUESTEDRATIO = CConfigValue<Hyprlang::VEC2>("layout:single_window_aspect_ratio");
- const static auto REQUESTEDRATIOTOLERANCE = CConfigValue<Hyprlang::FLOAT>("layout:single_window_aspect_ratio_tolerance");
+ // this is used for scrolling, so that the gaps are correct when a window is the full width and has neighbors
+ const bool DISPLAYINVERSELEFT = STICKS(m_box.logicalBox.x, MONITOR_WORKAREA.x + MONITOR_WORKAREA.w);
+ const bool DISPLAYINVERSERIGHT = STICKS(m_box.logicalBox.x + m_box.logicalBox.w, MONITOR_WORKAREA.x);
- Vector2D ratioPadding;
+ static auto PGAPSINDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_in");
+ auto* const PGAPSIN = sc<CCssGapData*>((PGAPSINDATA.ptr())->getData());
+ auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
- if ((*REQUESTEDRATIO).y != 0 && m_space->algorithm()->tiledTargets() <= 1 && fullscreenMode() == FSMODE_NONE) {
- const Vector2D originalSize = MONITOR_WORKAREA.size();
+ const static auto REQUESTEDRATIO = CConfigValue<Hyprlang::VEC2>("layout:single_window_aspect_ratio");
+ const static auto REQUESTEDRATIOTOLERANCE = CConfigValue<Hyprlang::FLOAT>("layout:single_window_aspect_ratio_tolerance");
- const double requestedRatio = (*REQUESTEDRATIO).x / (*REQUESTEDRATIO).y;
- const double originalRatio = originalSize.x / originalSize.y;
+ Vector2D ratioPadding;
- if (requestedRatio > originalRatio) {
- double padding = originalSize.y - (originalSize.x / requestedRatio);
+ if ((*REQUESTEDRATIO).y != 0 && m_space->algorithm()->tiledTargets() <= 1 && fullscreenMode() == FSMODE_NONE) {
+ const Vector2D originalSize = MONITOR_WORKAREA.size();
- if (padding / 2 > (*REQUESTEDRATIOTOLERANCE) * originalSize.y)
- ratioPadding = Vector2D{0., padding};
- } else if (requestedRatio < originalRatio) {
- double padding = originalSize.x - (originalSize.y * requestedRatio);
+ const double requestedRatio = (*REQUESTEDRATIO).x / (*REQUESTEDRATIO).y;
+ const double originalRatio = originalSize.x / originalSize.y;
- if (padding / 2 > (*REQUESTEDRATIOTOLERANCE) * originalSize.x)
- ratioPadding = Vector2D{padding, 0.};
+ if (requestedRatio > originalRatio) {
+ double padding = originalSize.y - (originalSize.x / requestedRatio);
+
+ if (padding / 2 > (*REQUESTEDRATIOTOLERANCE) * originalSize.y)
+ ratioPadding = Vector2D{0., padding};
+ } else if (requestedRatio < originalRatio) {
+ double padding = originalSize.x - (originalSize.y * requestedRatio);
+
+ if (padding / 2 > (*REQUESTEDRATIOTOLERANCE) * originalSize.x)
+ ratioPadding = Vector2D{padding, 0.};
+ }
}
- }
- const auto GAPOFFSETTOPLEFT = Vector2D(sc<double>(DISPLAYLEFT ? 0 : (DISPLAYINVERSELEFT ? 2 * gapsIn.m_left : gapsIn.m_left)), sc<double>(DISPLAYTOP ? 0 : gapsIn.m_top));
+ const auto GAPOFFSETTOPLEFT = Vector2D(sc<double>(DISPLAYLEFT ? 0 : (DISPLAYINVERSELEFT ? 2 * gapsIn.m_left : gapsIn.m_left)), sc<double>(DISPLAYTOP ? 0 : gapsIn.m_top));
- const auto GAPOFFSETBOTTOMRIGHT =
- Vector2D(sc<double>(DISPLAYRIGHT ? 0 : (DISPLAYINVERSERIGHT ? 2 * gapsIn.m_right : gapsIn.m_right)), sc<double>(DISPLAYBOTTOM ? 0 : gapsIn.m_bottom));
+ const auto GAPOFFSETBOTTOMRIGHT =
+ Vector2D(sc<double>(DISPLAYRIGHT ? 0 : (DISPLAYINVERSERIGHT ? 2 * gapsIn.m_right : gapsIn.m_right)), sc<double>(DISPLAYBOTTOM ? 0 : gapsIn.m_bottom));
- calcPos = calcPos + GAPOFFSETTOPLEFT + ratioPadding / 2;
- calcSize = calcSize - GAPOFFSETTOPLEFT - GAPOFFSETBOTTOMRIGHT - ratioPadding;
+ calcPos = calcPos + GAPOFFSETTOPLEFT + ratioPadding / 2;
+ calcSize = calcSize - GAPOFFSETTOPLEFT - GAPOFFSETBOTTOMRIGHT - ratioPadding;
+ }
if (isPseudo() && fullscreenMode() == FSMODE_NONE) {
// Calculate pseudo
@@ -347,7 +348,7 @@ eFullscreenMode CWindowTarget::fullscreenMode() {
void CWindowTarget::setFullscreenMode(eFullscreenMode mode) {
if (floating() && m_window->m_fullscreenState.internal == FSMODE_NONE)
- rememberFloatingSize(m_box.size());
+ rememberFloatingSize(m_box.logicalBox.size());
m_window->m_fullscreenState.internal = mode;
}
diff --git a/src/layout/target/WindowTarget.hpp b/src/layout/target/WindowTarget.hpp
index 2939fd74..e42f4d78 100644
--- a/src/layout/target/WindowTarget.hpp
+++ b/src/layout/target/WindowTarget.hpp
@@ -13,7 +13,7 @@ namespace Layout {
virtual eTargetType type();
- virtual void setPositionGlobal(const CBox& box);
+ virtual void setPositionGlobal(const STargetBox& box);
virtual void assignToSpace(const SP<CSpace>& space, std::optional<Vector2D> focalPoint = std::nullopt);
virtual PHLWINDOW window() const;
@@ -37,4 +37,4 @@ namespace Layout {
PHLWINDOWREF m_window;
};
-}; \ No newline at end of file
+};