@@ -31,6 +31,8 @@ namespace Hyprtoolkit::LinearLayout {
3131
3232 std::vector<size_t > sizes;
3333 sizes.resize (C.size ());
34+ std::vector<double > preferredSizes;
35+ preferredSizes.resize (C.size ());
3436
3537 size_t i = 0 ;
3638 for (i = 0 ; i < C.size (); ++i) {
@@ -39,6 +41,7 @@ namespace Hyprtoolkit::LinearLayout {
3941 Vector2D cSize = childSize (child);
4042 if (cSize == Vector2D{-1 , -1 })
4143 cSize = Horizontal ? Vector2D{1 .F , box.h } : Vector2D{box.w , 1 .F };
44+ preferredSizes.at (i) = axisPrimary (cSize);
4245
4346 if (used + axisPrimary (cSize) > MAX + 1 ) {
4447 // we exceeded our available space.
@@ -56,7 +59,7 @@ namespace Hyprtoolkit::LinearLayout {
5659 // (needs > 0 below), the current child is dropped and we
5760 // expand the previous one to cover the gap; minor visual
5861 // artefact in degenerate cases but the layout stays sane.
59- float needs = (used + axisPrimary (cSize)) - ( MAX + 1 ) ;
62+ float needs = (used + axisPrimary (cSize)) - MAX ;
6063 for (int j = (int )i - 1 ; j >= 0 ; --j) {
6164 const auto & prevChild = C.at (j);
6265 const auto MIN = prevChild->minimumSize (box.size ());
@@ -91,11 +94,12 @@ namespace Hyprtoolkit::LinearLayout {
9194 child->impl ->setFailedPositioning (true );
9295 if (i != 0 ) {
9396 const auto & lastChild = C.at (i - 1 );
97+ const auto AVAILABLE = std::max (0.0 , MAX - used);
9498
95- if (lastChild->maximumSize (box.size ()) && sizes.at (i - 1 ) + MAX - used > axisPrimary (*lastChild->maximumSize (box.size ())))
99+ if (lastChild->maximumSize (box.size ()) && sizes.at (i - 1 ) + AVAILABLE > axisPrimary (*lastChild->maximumSize (box.size ())))
96100 continue ; // too bad, we'll have a gap
97101
98- sizes.at (i - 1 ) += MAX - used ;
102+ sizes.at (i - 1 ) += AVAILABLE ;
99103 }
100104 continue ;
101105 } else {
@@ -104,15 +108,19 @@ namespace Hyprtoolkit::LinearLayout {
104108
105109 // recalc used, we changed prior sizes
106110 used = 0 ;
107- for (const auto & s : sizes)
108- used += s + gap;
111+ for (size_t j = 0 ; j <= i; ++j) {
112+ if (!C.at (j)->impl ->failedPositioning )
113+ used += sizes.at (j) + gap;
114+ }
109115
110116 continue ;
111117 }
112118 }
113119
114120 // squeeze the last element in
115- sizes.at (i) = MAX - used;
121+ child->impl ->setFailedPositioning (false );
122+ sizes.at (i) = std::max (0.0 , MAX - used);
123+ used = MAX + gap; // the common final-gap removal below still runs
116124 continue ;
117125 }
118126
@@ -142,17 +150,19 @@ namespace Hyprtoolkit::LinearLayout {
142150 if (child->impl ->failedPositioning )
143151 continue ;
144152
145- Vector2D cSize = childSize (child);
153+ Vector2D cSize = childSize (child);
154+ const double ROOM = grows (child) ? 0 : std::max (0.0 , MAX - used);
155+ const bool SQUEEZED = sizes.at (i) + ROOM + 1 < preferredSizes.at (i);
146156
147- CBox childBox;
157+ CBox childBox;
148158 if constexpr (Horizontal) {
149159 cSize.y = std::clamp (cSize.y , 0.0 , box.h );
150160 childBox = CBox{box.x + (double )cursor, box.y + ((box.h - cSize.y ) / 2 ), (double )sizes.at (i), cSize.y };
151- g_positioner->position (child, childBox, Vector2D{childBox.w + ( MAX - used) , box.h });
161+ g_positioner->position (child, childBox, Vector2D{SQUEEZED ? childBox.w + ROOM : - 1 , box.h });
152162 } else {
153163 cSize.x = std::clamp (cSize.x , 0.0 , box.w );
154164 childBox = CBox{box.x + ((box.w - cSize.x ) / 2 ), box.y + (double )cursor, cSize.x , (double )sizes.at (i)};
155- g_positioner->position (child, childBox, Vector2D{box.w , childBox.h + ( MAX - used) });
165+ g_positioner->position (child, childBox, Vector2D{box.w , SQUEEZED ? childBox.h + ROOM : - 1 });
156166 }
157167
158168 cursor += (size_t )((Horizontal ? childBox.w : childBox.h ) + gap);
0 commit comments