Window resizing

Lots of code duplication that needs cleaning
This commit is contained in:
outfoxxed 2023-04-18 23:41:18 -07:00
parent 034e23e758
commit be3bd8c535
No known key found for this signature in database
GPG key ID: 4C88A185FB89301E
2 changed files with 235 additions and 6 deletions

View file

@ -150,7 +150,7 @@ void Hy3Node::recalcSizePosRecursive(bool force) {
break; break;
} }
child->recalcSizePosRecursive(); child->recalcSizePosRecursive(force);
return; return;
} }
@ -166,20 +166,22 @@ void Hy3Node::recalcSizePosRecursive(bool force) {
break; break;
} }
double ratio_mul = group->layout != Hy3GroupLayout::Tabbed ? group->children.empty() ? 0 : constraint / group->children.size() : 0;
double offset = 0; double offset = 0;
for(auto child: group->children) { for(auto child: group->children) {
switch (group->layout) { switch (group->layout) {
case Hy3GroupLayout::SplitH: case Hy3GroupLayout::SplitH:
child->position.x = this->position.x + offset; child->position.x = this->position.x + offset;
child->size.x = child->size_ratio * ((double) constraint / group->children.size()); child->size.x = child->size_ratio * ratio_mul;
offset += child->size.x; offset += child->size.x;
child->position.y = this->position.y; child->position.y = this->position.y;
child->size.y = this->size.y; child->size.y = this->size.y;
break; break;
case Hy3GroupLayout::SplitV: case Hy3GroupLayout::SplitV:
child->position.y = this->position.y + offset; child->position.y = this->position.y + offset;
child->size.y = child->size_ratio * ((double) constraint / group->children.size()); child->size.y = child->size_ratio * ratio_mul;
offset += child->size.y; offset += child->size.y;
child->position.x = this->position.x; child->position.x = this->position.x;
child->size.x = this->size.x; child->size.x = this->size.x;
@ -349,7 +351,7 @@ void Hy3Layout::applyNodeDataToWindow(Hy3Node* node, bool force) {
g_pHyprRenderer->damageWindow(window); g_pHyprRenderer->damageWindow(window);
window->m_vRealPosition.warp(); window->m_vRealPosition.warp();
window->m_vRealPosition.warp(); window->m_vRealSize.warp();
g_pHyprRenderer->damageWindow(window); g_pHyprRenderer->damageWindow(window);
} }
@ -466,6 +468,12 @@ void Hy3Layout::onWindowRemovedTiling(CWindow* window) {
} }
group->children.remove(node); group->children.remove(node);
auto splitmod = group->children.empty() ? 0.0 : (1.0 - node->size_ratio) / group->children.size();
for (auto child: group->children) {
child->size_ratio -= splitmod;
}
this->nodes.remove(*node); this->nodes.remove(*node);
if (group->children.size() == 1) { if (group->children.size() == 1) {
@ -487,6 +495,12 @@ void Hy3Layout::onWindowRemovedTiling(CWindow* window) {
} }
group->children.remove(child); group->children.remove(child);
auto splitmod = group->children.empty() ? 0.0 : (1.0 - child->size_ratio) / group->children.size();
for (auto child: group->children) {
child->size_ratio -= splitmod;
}
this->nodes.remove(*child); this->nodes.remove(*child);
if (group->children.size() == 1) { if (group->children.size() == 1) {
@ -570,8 +584,203 @@ void Hy3Layout::recalculateWindow(CWindow* pWindow) {
; // empty ; // empty
} }
void Hy3Layout::onBeginDragWindow() {
this->drag_flags.started = false;
IHyprLayout::onBeginDragWindow();
}
void Hy3Layout::resizeActiveWindow(const Vector2D& delta, CWindow* pWindow) { void Hy3Layout::resizeActiveWindow(const Vector2D& delta, CWindow* pWindow) {
; // empty auto window = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(window)) return;
auto* node = this->getNodeFromWindow(window);
if (node == nullptr) return;
if (!this->drag_flags.started) {
auto mouse = g_pInputManager->getMouseCoordsInternal();
auto mouseOffset = mouse - window->m_vPosition;
this->drag_flags = {
.started = true,
.xExtent = mouseOffset.x > window->m_vSize.x / 2,
.yExtent = mouseOffset.y > window->m_vSize.y / 2,
};
Debug::log(LOG, "Positive offsets - x: %d, y: %d", this->drag_flags.xExtent, this->drag_flags.yExtent);
}
const auto animate = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
auto monitor = g_pCompositor->getMonitorFromID(window->m_iMonitorID);
const bool display_left = STICKS(node->position.x, monitor->vecPosition.x + monitor->vecReservedTopLeft.x);
const bool display_right = STICKS(node->position.x + node->size.x, monitor->vecPosition.x + monitor->vecSize.x - monitor->vecReservedBottomRight.x);
const bool display_top = STICKS(node->position.y, monitor->vecPosition.y + monitor->vecReservedTopLeft.y);
const bool display_bottom = STICKS(node->position.y + node->size.y, monitor->vecPosition.y + monitor->vecSize.y - monitor->vecReservedBottomRight.y);
Vector2D allowed_movement = delta;
if (display_left && display_right) allowed_movement.x = 0;
if (display_top && display_bottom) allowed_movement.y = 0;
auto* inner_node = node;
// break into parent groups when encountering a corner we're dragging in or a tab group
while (inner_node->parent != nullptr) {
auto& group = inner_node->parent->data.as_group;
switch (group.layout) {
case Hy3GroupLayout::Tabbed:
// treat tabbed layouts as if they dont exist during resizing
goto cont;
case Hy3GroupLayout::SplitH:
if ((this->drag_flags.xExtent && group.children.back() == inner_node)
|| (!this->drag_flags.xExtent && group.children.front() == inner_node)) {
goto cont;
}
break;
case Hy3GroupLayout::SplitV:
if ((this->drag_flags.yExtent && group.children.back() == inner_node)
|| (!this->drag_flags.yExtent && group.children.front() == inner_node)) {
goto cont;
}
break;
}
break;
cont:
inner_node = inner_node->parent;
}
auto* inner_parent = inner_node->parent;
if (inner_parent == nullptr) return;
auto* outer_node = inner_node;
// break into parent groups when encountering a corner we're dragging in, a tab group,
// or a layout matching the inner_parent.
while (outer_node->parent != nullptr) {
auto& group = outer_node->parent->data.as_group;
// break out of all layouts that match the orientation of the inner_parent
if (group.layout == inner_parent->data.as_group.layout) goto cont2;
switch (group.layout) {
case Hy3GroupLayout::Tabbed:
// treat tabbed layouts as if they dont exist during resizing
goto cont2;
case Hy3GroupLayout::SplitH:
if ((this->drag_flags.xExtent && group.children.back() == outer_node)
|| (!this->drag_flags.xExtent && group.children.front() == outer_node)) {
goto cont2;
}
break;
case Hy3GroupLayout::SplitV:
if ((this->drag_flags.yExtent && group.children.back() == outer_node)
|| (!this->drag_flags.yExtent && group.children.front() == outer_node)) {
goto cont2;
}
break;
}
break;
cont2:
outer_node = outer_node->parent;
}
Debug::log(LOG, "resizeActive - inner_node: %p, outer_node: %p", inner_node, outer_node);
auto& inner_group = inner_parent->data.as_group;
// adjust the inner node
switch (inner_group.layout) {
case Hy3GroupLayout::SplitH: {
auto ratio_mod = allowed_movement.x * (float) inner_group.children.size() / inner_parent->size.x;
auto iter = std::find(inner_group.children.begin(), inner_group.children.end(), inner_node);
if (this->drag_flags.xExtent) {
if (inner_node == inner_group.children.back()) break;
iter = std::next(iter);
} else {
if (inner_node == inner_group.children.front()) break;
iter = std::prev(iter);
ratio_mod = -ratio_mod;
}
auto* neighbor = *iter;
inner_node->size_ratio += ratio_mod;
neighbor->size_ratio -= ratio_mod;
} break;
case Hy3GroupLayout::SplitV: {
auto ratio_mod = allowed_movement.y * (float) inner_parent->data.as_group.children.size() / inner_parent->size.y;
auto iter = std::find(inner_group.children.begin(), inner_group.children.end(), inner_node);
if (this->drag_flags.yExtent) {
if (inner_node == inner_group.children.back()) break;
iter = std::next(iter);
} else {
if (inner_node == inner_group.children.front()) break;
iter = std::prev(iter);
ratio_mod = -ratio_mod;
}
auto* neighbor = *iter;
inner_node->size_ratio += ratio_mod;
neighbor->size_ratio -= ratio_mod;
} break;
}
inner_parent->recalcSizePosRecursive(*animate == 0);
if (outer_node != nullptr && outer_node->parent != nullptr) {
auto* outer_parent = outer_node->parent;
auto& outer_group = outer_parent->data.as_group;
// adjust the outer node
switch (outer_group.layout) {
case Hy3GroupLayout::SplitH: {
auto ratio_mod = allowed_movement.x * (float) outer_group.children.size() / outer_parent->size.x;
auto iter = std::find(outer_group.children.begin(), outer_group.children.end(), outer_node);
if (this->drag_flags.xExtent) {
if (outer_node == inner_group.children.back()) break;
iter = std::next(iter);
} else {
if (outer_node == inner_group.children.front()) break;
iter = std::prev(iter);
ratio_mod = -ratio_mod;
}
auto* neighbor = *iter;
outer_node->size_ratio += ratio_mod;
neighbor->size_ratio -= ratio_mod;
} break;
case Hy3GroupLayout::SplitV: {
auto ratio_mod = allowed_movement.y * (float) outer_parent->data.as_group.children.size() / outer_parent->size.y;
auto iter = std::find(outer_group.children.begin(), outer_group.children.end(), outer_node);
if (this->drag_flags.yExtent) {
if (outer_node == outer_group.children.back()) break;
iter = std::next(iter);
} else {
if (outer_node == outer_group.children.front()) break;
iter = std::prev(iter);
ratio_mod = -ratio_mod;
}
auto* neighbor = *iter;
outer_node->size_ratio += ratio_mod;
neighbor->size_ratio -= ratio_mod;
} break;
}
outer_parent->recalcSizePosRecursive(*animate == 0);
}
} }
void Hy3Layout::fullscreenRequestForWindow(CWindow* window, eFullscreenMode fullscreen_mode, bool on) { void Hy3Layout::fullscreenRequestForWindow(CWindow* window, eFullscreenMode fullscreen_mode, bool on) {
@ -879,11 +1088,19 @@ Hy3Node* shiftOrGetFocus(Hy3Node& node, ShiftDirection direction, bool shift) {
} }
node.parent = target_group; node.parent = target_group;
node.size_ratio = 1.0;
target_group->data.as_group.children.insert(insert, &node); target_group->data.as_group.children.insert(insert, &node);
// must happen AFTER `insert` is used // must happen AFTER `insert` is used
old_group->children.remove(&node); old_group->children.remove(&node);
auto splitmod = old_group->children.empty() ? 0.0 : (1.0 - node.size_ratio) / old_group->children.size();
for (auto child: old_group->children) {
child->size_ratio -= splitmod;
}
node.size_ratio = 1.0;
if (old_group->children.empty()) { if (old_group->children.empty()) {
while (old_parent->parent != nullptr && old_parent->data.as_group.children.empty()) { while (old_parent->parent != nullptr && old_parent->data.as_group.children.empty()) {
auto* child = old_parent; auto* child = old_parent;
@ -906,6 +1123,11 @@ Hy3Node* shiftOrGetFocus(Hy3Node& node, ShiftDirection direction, bool shift) {
} }
old_parent->layout->nodes.remove(*child); old_parent->layout->nodes.remove(*child);
auto splitmod = old_group->children.empty() ? 0.0 : (1.0 - child->size_ratio) / old_group->children.size();
for (auto child: old_group->children) {
child->size_ratio -= splitmod;
}
} }
} else if (old_group->children.size() == 1) { } else if (old_group->children.size() == 1) {
old_group->lastFocusedChild = old_group->children.front(); old_group->lastFocusedChild = old_group->children.front();

View file

@ -86,6 +86,7 @@ public:
virtual bool isWindowTiled(CWindow*); virtual bool isWindowTiled(CWindow*);
virtual void recalculateMonitor(const int&); virtual void recalculateMonitor(const int&);
virtual void recalculateWindow(CWindow*); virtual void recalculateWindow(CWindow*);
virtual void onBeginDragWindow();
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr); virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool); virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
virtual std::any layoutMessage(SLayoutMessageHeader, std::string); virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
@ -107,6 +108,12 @@ public:
private: private:
CWindow* lastActiveWindow = nullptr; CWindow* lastActiveWindow = nullptr;
struct {
bool started = false;
bool xExtent = false;
bool yExtent = false;
} drag_flags;
int getWorkspaceNodeCount(const int&); int getWorkspaceNodeCount(const int&);
Hy3Node* getNodeFromWindow(CWindow*); Hy3Node* getNodeFromWindow(CWindow*);
Hy3Node* getWorkspaceRootGroup(const int&); Hy3Node* getWorkspaceRootGroup(const int&);