Improve iteration handling and validate results

This commit is contained in:
Pete Appleton 2024-01-29 08:31:16 +00:00
parent f3e8d2ff9a
commit dad1589d21
3 changed files with 81 additions and 42 deletions

View file

@ -390,6 +390,17 @@ void Hy3Layout::recalculateWindow(CWindow* window) {
node->recalcSizePosRecursive(); node->recalcSizePosRecursive();
} }
ShiftDirection reverse(ShiftDirection direction) {
switch (direction)
{
case ShiftDirection::Left: return ShiftDirection::Right;
case ShiftDirection::Right: return ShiftDirection::Left;
case ShiftDirection::Up: return ShiftDirection::Down;
case ShiftDirection::Down: return ShiftDirection::Up;
default: return direction;
}
}
void Hy3Layout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CWindow* pWindow) { void Hy3Layout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CWindow* pWindow) {
auto window = pWindow ? pWindow : g_pCompositor->m_pLastWindow; auto window = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(window)) return; if (!g_pCompositor->windowValidMapped(window)) return;
@ -421,11 +432,15 @@ void Hy3Layout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CW
ShiftDirection target_edge_x; ShiftDirection target_edge_x;
ShiftDirection target_edge_y; ShiftDirection target_edge_y;
// Determine the direction in which we're going to look for the sibling node // Determine the direction in which we're going to look for the neighbor node
// that will be resized // that will be resized
if(corner == CORNER_NONE) { // It's probably a keyboard event. if(corner == CORNER_NONE) { // It's probably a keyboard event.
target_edge_x = display_right ? ShiftDirection::Left : ShiftDirection::Right; target_edge_x = display_right ? ShiftDirection::Left : ShiftDirection::Right;
target_edge_y = display_bottom ? ShiftDirection::Up : ShiftDirection::Down; target_edge_y = display_bottom ? ShiftDirection::Up : ShiftDirection::Down;
// If the anchor is not at the top/left then reverse the delta
if(target_edge_x == ShiftDirection::Left) resize_delta.x = -resize_delta.x;
if(target_edge_y == ShiftDirection::Up) resize_delta.y = -resize_delta.y;
} else { // It's probably a mouse event } else { // It's probably a mouse event
// Resize against the edges corresponding to the selected corner // Resize against the edges corresponding to the selected corner
target_edge_x = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT target_edge_x = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT
@ -434,25 +449,32 @@ void Hy3Layout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CW
? ShiftDirection::Up : ShiftDirection::Down; ? ShiftDirection::Up : ShiftDirection::Down;
} }
auto sibling_node_x = node->findSibling(target_edge_x); // Find the neighboring node in each axis, which will be either above or at the
auto sibling_node_y = node->findSibling(target_edge_y); // same level as the initiating node in the layout hierarchy. These are the nodes
// which must get resized (rather than the initiator) because they are the
// highest point in the hierarchy
auto horizontal_neighbor = node->findNeighbor(target_edge_x);
auto vertical_neighbor = node->findNeighbor(target_edge_y);
if(sibling_node_x) { const auto animate =
sibling_node_x->resize(resize_delta.x, target_edge_x); &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
// Note that the resize direction is reversed, because from the neighbor's perspective
// the edge to be moved is the opposite way round. However, the delta is still the same.
if(horizontal_neighbor) {
horizontal_neighbor->resize(reverse(target_edge_x), resize_delta.x, *animate == 0);
} }
if(sibling_node_y) { if(vertical_neighbor) {
sibling_node_y->resize(resize_delta.y, target_edge_y); vertical_neighbor->resize(reverse(target_edge_y), resize_delta.y, *animate == 0);
} }
} else { } else if(window->m_bIsFloating) {
// No parent node - is this a floating window? If so, use the same logic as the `main` layout // No parent node - is this a floating window? If so, use the same logic as the `main` layout
if(window->m_bIsFloating) { const auto required_size = Vector2D(
const auto required_size = Vector2D( std::max((window->m_vRealSize.goalv() + delta).x, 20.0),
std::max((window->m_vRealSize.goalv() + delta).x, 20.0), std::max((window->m_vRealSize.goalv() + delta).y, 20.0)
std::max((window->m_vRealSize.goalv() + delta).y, 20.0) );
); window->m_vRealSize = required_size;
window->m_vRealSize = required_size;
}
} }
} }

View file

@ -7,7 +7,7 @@
#include "Hy3Node.hpp" #include "Hy3Node.hpp"
#include "globals.hpp" #include "globals.hpp"
const float MIN_RATIO = 0.02f; const float MIN_WINDOW_SIZE = 20;
// Hy3GroupData // // Hy3GroupData //
@ -879,7 +879,7 @@ Axis getAxis(ShiftDirection direction) {
} }
} }
Hy3Node* Hy3Node::findSibling(ShiftDirection direction) { Hy3Node* Hy3Node::findNeighbor(ShiftDirection direction) {
auto current_node = this; auto current_node = this;
Hy3Node* sibling = nullptr; Hy3Node* sibling = nullptr;
@ -901,40 +901,57 @@ Hy3Node* Hy3Node::findSibling(ShiftDirection direction) {
return sibling; return sibling;
} }
int directionToIteratorIncrement(ShiftDirection direction) {
switch (direction)
{
case ShiftDirection::Left:
case ShiftDirection::Up:
return -1;
case ShiftDirection::Right:
case ShiftDirection::Down:
return 1;
default:
hy3_log(WARN, "Unknown ShiftDirection enum value: {}", (int)direction);
return 1;
}
}
void Hy3Node::resize( void Hy3Node::resize(
double resize_delta, ShiftDirection direction,
ShiftDirection target_edge_x double delta,
bool no_animation
) { ) {
auto& parent_node = this->parent; auto& parent_node = this->parent;
auto& containing_group = parent_node->data.as_group; auto& containing_group = parent_node->data.as_group;
const auto animate =
&g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
if(containing_group.layout != Hy3GroupLayout::Tabbed && getAxis(target_edge_x) == getAxis(containing_group.layout)) { if(containing_group.layout != Hy3GroupLayout::Tabbed && getAxis(direction) == getAxis(containing_group.layout)) {
double parent_size = getAxis(target_edge_x) == Axis::Horizontal ? parent_node->size.x double parent_size = getAxis(direction) == Axis::Horizontal ? parent_node->size.x
: parent_node->size.y; : parent_node->size.y;
auto ratio_mod = resize_delta * (float) containing_group.children.size() / parent_size; auto ratio_mod = delta * (float) containing_group.children.size() / parent_size;
auto iter = std::find(containing_group.children.begin(), containing_group.children.end(), this); const auto end_of_children = containing_group.children.end();
auto iter = std::find(containing_group.children.begin(), end_of_children, this);
if (target_edge_x == ShiftDirection::Left || target_edge_x == ShiftDirection::Up) { if(iter != end_of_children) {
if (this != containing_group.children.back()) { const auto outermost_node_in_group = getOuterChild(containing_group, direction);
iter = std::next(iter); if(this != outermost_node_in_group) {
auto inc = directionToIteratorIncrement(direction);
iter = std::next(iter, inc);
ratio_mod *= inc;
} }
} else {
if (this != containing_group.children.front()) { if(iter != end_of_children) {
iter = std::prev(iter); auto* neighbor = *iter;
ratio_mod = -ratio_mod; auto requested_size_ratio = this->size_ratio + ratio_mod;
auto requested_neighbor_size_ratio = neighbor->size_ratio -ratio_mod;
if(requested_size_ratio * parent_size >= MIN_WINDOW_SIZE) {
this->size_ratio = requested_size_ratio;
neighbor->size_ratio = requested_neighbor_size_ratio;
parent_node->recalcSizePosRecursive(no_animation);
}
} }
} }
auto* neighbor = *iter;
if(this->size_ratio + ratio_mod > MIN_RATIO && neighbor->size_ratio - ratio_mod > MIN_RATIO) {
this->size_ratio += ratio_mod;
neighbor->size_ratio -= ratio_mod;
parent_node->recalcSizePosRecursive(*animate == 0);
}
} }
} }

View file

@ -99,9 +99,9 @@ struct Hy3Node {
void markFocused(); void markFocused();
void raiseToTop(); void raiseToTop();
Hy3Node* getFocusedNode(bool ignore_group_focus = false, bool stop_at_expanded = false); Hy3Node* getFocusedNode(bool ignore_group_focus = false, bool stop_at_expanded = false);
Hy3Node* findSibling(ShiftDirection); Hy3Node* findNeighbor(ShiftDirection);
Hy3Node* getImmediateSibling(ShiftDirection); Hy3Node* getImmediateSibling(ShiftDirection);
void resize(double, ShiftDirection); void resize(ShiftDirection, double, bool no_animation = false);
bool isIndirectlyFocused(); bool isIndirectlyFocused();
Hy3Node& getExpandActor(); Hy3Node& getExpandActor();