aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Pedro CĂ´rte-Real <pedro@pedrocr.net>2019-07-28 11:17:33 +0100
committerLibravatar Drew DeVault <sir@cmpwn.com>2020-01-08 10:27:20 -0500
commitc284ed379c60884f70418e6720a41c3af6e600e2 (patch)
treed3f6eb851738aba3f8664afac307dd916f0defd9
parentUpdate version to 1.3-rc1 (diff)
downloadsway-c284ed379c60884f70418e6720a41c3af6e600e2.tar.gz
sway-c284ed379c60884f70418e6720a41c3af6e600e2.tar.zst
sway-c284ed379c60884f70418e6720a41c3af6e600e2.zip
Avoid numerical instability in resize
Because the layout code rounds down the dimensions of the windows resizing would often be off by one pixel. The width/height fraction would not exactly reflect the final computed width and so the resize code would end up calculating things wrong. To fix this first snap the container size fractions to the pixel grid and only then do the resize. Also use round() instead of floor() during layout to avoid a slightly too small width. This applies in two cases: 1. For the container we are actually resizing using floor() might result in being 1px too small. 2. For the other containers it might result in resizing them down by 1px and then if the container being resized is the last all those extra pixels would make the resize too large. Fixes #4391
-rw-r--r--include/sway/tree/container.h5
-rw-r--r--sway/commands/resize.c28
-rw-r--r--sway/tree/arrange.c6
3 files changed, 33 insertions, 6 deletions
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index 099a8089..62c6556b 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -92,6 +92,11 @@ struct sway_container {
92 double width_fraction; 92 double width_fraction;
93 double height_fraction; 93 double height_fraction;
94 94
95 // The share of space of the parent container that all children occupy
96 // Used for doing the resize calculations
97 double child_total_width;
98 double child_total_height;
99
95 // These are in layout coordinates. 100 // These are in layout coordinates.
96 double content_x, content_y; 101 double content_x, content_y;
97 int content_width, content_height; 102 int content_width, content_height;
diff --git a/sway/commands/resize.c b/sway/commands/resize.c
index 0c9af12d..7ff4ef7b 100644
--- a/sway/commands/resize.c
+++ b/sway/commands/resize.c
@@ -172,9 +172,19 @@ void container_resize_tiled(struct sway_container *con,
172 if (prev && prev->width - sibling_amount < MIN_SANE_W) { 172 if (prev && prev->width - sibling_amount < MIN_SANE_W) {
173 return; 173 return;
174 } 174 }
175 if (con->child_total_width <= 0) {
176 return;
177 }
178
179 // We're going to resize so snap all the width fractions to full pixels
180 // to avoid rounding issues
181 list_t *siblings = container_get_siblings(con);
182 for (int i = 0; i < siblings->length; ++i) {
183 struct sway_container *con = siblings->items[i];
184 con->width_fraction = con->width / con->child_total_width;
185 }
175 186
176 double amount_fraction = 187 double amount_fraction = (double)amount / con->child_total_width;
177 ((double)amount / con->width) * con->width_fraction;
178 double sibling_amount_fraction = 188 double sibling_amount_fraction =
179 prev ? amount_fraction / 2.0 : amount_fraction; 189 prev ? amount_fraction / 2.0 : amount_fraction;
180 190
@@ -193,9 +203,19 @@ void container_resize_tiled(struct sway_container *con,
193 if (prev && prev->height - sibling_amount < MIN_SANE_H) { 203 if (prev && prev->height - sibling_amount < MIN_SANE_H) {
194 return; 204 return;
195 } 205 }
206 if (con->child_total_height <= 0) {
207 return;
208 }
209
210 // We're going to resize so snap all the height fractions to full pixels
211 // to avoid rounding issues
212 list_t *siblings = container_get_siblings(con);
213 for (int i = 0; i < siblings->length; ++i) {
214 struct sway_container *con = siblings->items[i];
215 con->height_fraction = con->height / con->child_total_height;
216 }
196 217
197 double amount_fraction = 218 double amount_fraction = (double)amount / con->child_total_height;
198 ((double)amount / con->height) * con->height_fraction;
199 double sibling_amount_fraction = 219 double sibling_amount_fraction =
200 prev ? amount_fraction / 2.0 : amount_fraction; 220 prev ? amount_fraction / 2.0 : amount_fraction;
201 221
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c
index 7b88b3a2..e4f59110 100644
--- a/sway/tree/arrange.c
+++ b/sway/tree/arrange.c
@@ -78,9 +78,10 @@ static void apply_horiz_layout(list_t *children, struct wlr_box *parent) {
78 double child_x = parent->x; 78 double child_x = parent->x;
79 for (int i = 0; i < children->length; ++i) { 79 for (int i = 0; i < children->length; ++i) {
80 struct sway_container *child = children->items[i]; 80 struct sway_container *child = children->items[i];
81 child->child_total_width = child_total_width;
81 child->x = child_x; 82 child->x = child_x;
82 child->y = parent->y; 83 child->y = parent->y;
83 child->width = floor(child->width_fraction * child_total_width); 84 child->width = round(child->width_fraction * child_total_width);
84 child->height = parent->height; 85 child->height = parent->height;
85 child_x += child->width + inner_gap; 86 child_x += child->width + inner_gap;
86 87
@@ -156,10 +157,11 @@ static void apply_vert_layout(list_t *children, struct wlr_box *parent) {
156 double child_y = parent->y; 157 double child_y = parent->y;
157 for (int i = 0; i < children->length; ++i) { 158 for (int i = 0; i < children->length; ++i) {
158 struct sway_container *child = children->items[i]; 159 struct sway_container *child = children->items[i];
160 child->child_total_height = child_total_height;
159 child->x = parent->x; 161 child->x = parent->x;
160 child->y = child_y; 162 child->y = child_y;
161 child->width = parent->width; 163 child->width = parent->width;
162 child->height = floor(child->height_fraction * child_total_height); 164 child->height = round(child->height_fraction * child_total_height);
163 child_y += child->height + inner_gap; 165 child_y += child->height + inner_gap;
164 166
165 // Make last child use remaining height of parent 167 // Make last child use remaining height of parent