diff options
Diffstat (limited to 'sway/commands/resize.c')
-rw-r--r-- | sway/commands/resize.c | 313 |
1 files changed, 112 insertions, 201 deletions
diff --git a/sway/commands/resize.c b/sway/commands/resize.c index 2c5b3f6b..28b20dc4 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c | |||
@@ -63,224 +63,135 @@ static bool resize_floating(int amount, bool use_width) { | |||
63 | } | 63 | } |
64 | 64 | ||
65 | static bool resize_tiled(int amount, bool use_width) { | 65 | static bool resize_tiled(int amount, bool use_width) { |
66 | swayc_t *parent = get_focused_view(swayc_active_workspace()); | 66 | swayc_t *container = get_focused_view(swayc_active_workspace()); |
67 | swayc_t *focused = parent; | 67 | swayc_t *parent = container->parent; |
68 | swayc_t *sibling; | 68 | int idx_focused = 0; |
69 | if (!parent) { | 69 | bool use_major = false; |
70 | return true; | 70 | size_t nb_before = 0; |
71 | } | 71 | size_t nb_after = 0; |
72 | // Find the closest parent container which has siblings of the proper layout. | 72 | |
73 | // Then apply the resize to all of them. | 73 | // 1. Identify a container ancestor that will allow the focused child to grow in the requested |
74 | int i; | 74 | // direction. |
75 | if (use_width) { | 75 | while (container->parent) { |
76 | int lnumber = 0; | 76 | parent = container->parent; |
77 | int rnumber = 0; | 77 | if ((parent->children && parent->children->length > 1) |
78 | while (parent->parent) { | 78 | && (is_auto_layout(parent->layout) |
79 | if (parent->parent->layout == L_HORIZ && parent->parent->children) { | 79 | || (use_width ? parent->layout == L_HORIZ : parent->layout == L_VERT))) { |
80 | for (i = 0; i < parent->parent->children->length; i++) { | 80 | // check if container has siblings that can provide/absorb the space needed for |
81 | sibling = parent->parent->children->items[i]; | 81 | // the resize operation. |
82 | if (sibling->x != focused->x) { | 82 | use_major = use_width |
83 | if (sibling->x < parent->x) { | 83 | ? parent->layout == L_AUTO_LEFT || parent->layout == L_AUTO_RIGHT |
84 | lnumber++; | 84 | : parent->layout == L_AUTO_TOP || parent->layout == L_AUTO_BOTTOM; |
85 | } else if (sibling->x > parent->x) { | 85 | // Note: use_major will be false for L_HORIZ and L_VERT |
86 | rnumber++; | 86 | |
87 | } | 87 | idx_focused = index_child(container); |
88 | } | 88 | if (idx_focused < 0) { |
89 | } | 89 | sway_log(L_ERROR, "Something weird is happening, child container not " |
90 | if (rnumber || lnumber) { | 90 | "present in its parent's children list."); |
91 | break; | 91 | continue; |
92 | } | ||
93 | } | 92 | } |
94 | parent = parent->parent; | 93 | if (use_major) { |
95 | } | 94 | nb_before = auto_group_index(parent, idx_focused); |
96 | if (parent == &root_container) { | 95 | nb_after = auto_group_count(parent) - nb_before - 1; |
97 | return true; | ||
98 | } | ||
99 | sway_log(L_DEBUG, "Found the proper parent: %p. It has %d l conts, and %d r conts", parent->parent, lnumber, rnumber); | ||
100 | //TODO: Ensure rounding is done in such a way that there are NO pixel leaks | ||
101 | bool valid = true; | ||
102 | for (i = 0; i < parent->parent->children->length; i++) { | ||
103 | sibling = parent->parent->children->items[i]; | ||
104 | if (sibling->x != focused->x) { | ||
105 | if (sibling->x < parent->x) { | ||
106 | double pixels = -1 * amount; | ||
107 | pixels /= lnumber; | ||
108 | if (rnumber) { | ||
109 | if ((sibling->width + pixels/2) < min_sane_w) { | ||
110 | valid = false; | ||
111 | break; | ||
112 | } | ||
113 | } else { | ||
114 | if ((sibling->width + pixels) < min_sane_w) { | ||
115 | valid = false; | ||
116 | break; | ||
117 | } | ||
118 | } | ||
119 | } else if (sibling->x > parent->x) { | ||
120 | double pixels = -1 * amount; | ||
121 | pixels /= rnumber; | ||
122 | if (lnumber) { | ||
123 | if ((sibling->width + pixels/2) < min_sane_w) { | ||
124 | valid = false; | ||
125 | break; | ||
126 | } | ||
127 | } else { | ||
128 | if ((sibling->width + pixels) < min_sane_w) { | ||
129 | valid = false; | ||
130 | break; | ||
131 | } | ||
132 | } | ||
133 | } | ||
134 | } else { | 96 | } else { |
135 | double pixels = amount; | 97 | nb_before = idx_focused - auto_group_start_index(parent, idx_focused); |
136 | if (parent->width + pixels < min_sane_w) { | 98 | nb_after = auto_group_end_index(parent, idx_focused) - idx_focused - 1; |
137 | valid = false; | 99 | sway_log(L_DEBUG, "+++ focused: %d, start: %d, end: %d, before: %d, after: %d", |
138 | break; | 100 | idx_focused, |
139 | } | 101 | (int)auto_group_start_index(parent, idx_focused), |
102 | (int)auto_group_end_index(parent, idx_focused), | ||
103 | (int)nb_before, (int)nb_after); | ||
104 | |||
140 | } | 105 | } |
141 | } | 106 | if (nb_before || nb_after) { |
142 | if (valid) { | 107 | break; |
143 | for (i = 0; i < parent->parent->children->length; i++) { | ||
144 | sibling = parent->parent->children->items[i]; | ||
145 | if (sibling->x != focused->x) { | ||
146 | if (sibling->x < parent->x) { | ||
147 | double pixels = -1 * amount; | ||
148 | pixels /= lnumber; | ||
149 | if (rnumber) { | ||
150 | recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_RIGHT); | ||
151 | } else { | ||
152 | recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_RIGHT); | ||
153 | } | ||
154 | } else if (sibling->x > parent->x) { | ||
155 | double pixels = -1 * amount; | ||
156 | pixels /= rnumber; | ||
157 | if (lnumber) { | ||
158 | recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_LEFT); | ||
159 | } else { | ||
160 | recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_LEFT); | ||
161 | } | ||
162 | } | ||
163 | } else { | ||
164 | if (rnumber != 0 && lnumber != 0) { | ||
165 | double pixels = amount; | ||
166 | pixels /= 2; | ||
167 | recursive_resize(parent, pixels, WLC_RESIZE_EDGE_LEFT); | ||
168 | recursive_resize(parent, pixels, WLC_RESIZE_EDGE_RIGHT); | ||
169 | } else if (rnumber) { | ||
170 | recursive_resize(parent, amount, WLC_RESIZE_EDGE_RIGHT); | ||
171 | } else if (lnumber) { | ||
172 | recursive_resize(parent, amount, WLC_RESIZE_EDGE_LEFT); | ||
173 | } | ||
174 | } | ||
175 | } | 108 | } |
176 | // Recursive resize does not handle positions, let arrange_windows | ||
177 | // take care of that. | ||
178 | arrange_windows(swayc_active_workspace(), -1, -1); | ||
179 | } | 109 | } |
110 | container = parent; /* continue up the tree to the next ancestor */ | ||
111 | } | ||
112 | if (parent == &root_container) { | ||
180 | return true; | 113 | return true; |
181 | } else { | 114 | } |
182 | int tnumber = 0; | 115 | sway_log(L_DEBUG, "Found the proper parent: %p. It has %zu before conts, " |
183 | int bnumber = 0; | 116 | "and %zu after conts", parent, nb_before, nb_after); |
184 | while (parent->parent) { | 117 | // 2. Ensure that the resize operation will not make one of the resized containers drop |
185 | if (parent->parent->layout == L_VERT) { | 118 | // below the "sane" size threshold. |
186 | for (i = 0; i < parent->parent->children->length; i++) { | 119 | bool valid = true; |
187 | sibling = parent->parent->children->items[i]; | 120 | swayc_t *focused = parent->children->items[idx_focused]; |
188 | if (sibling->y != focused->y) { | 121 | int start = use_major ? 0 : auto_group_start_index(parent, idx_focused); |
189 | if (sibling->y < parent->y) { | 122 | int end = use_major ? parent->children->length : auto_group_end_index(parent, idx_focused); |
190 | bnumber++; | 123 | sway_log(L_DEBUG, "Check children of container %p [%d,%d[", container, start, end); |
191 | } else if (sibling->y > parent->y) { | 124 | for (int i = start; i < end; ) { |
192 | tnumber++; | 125 | swayc_t *sibling = parent->children->items[i]; |
193 | } | 126 | double pixels = amount; |
194 | } | 127 | bool is_before = use_width ? sibling->x < focused->x : sibling->y < focused->y; |
195 | } | 128 | bool is_after = use_width ? sibling->x > focused->x : sibling->y > focused->y; |
196 | if (bnumber || tnumber) { | 129 | if (is_before || is_after) { |
197 | break; | 130 | pixels = -pixels; |
198 | } | 131 | pixels /= is_before ? nb_before : nb_after; |
132 | if (nb_after != 0 && nb_before != 0) { | ||
133 | pixels /= 2; | ||
199 | } | 134 | } |
200 | parent = parent->parent; | ||
201 | } | 135 | } |
202 | if (parent->parent == NULL || parent->parent->children == NULL) { | 136 | sway_log(L_DEBUG, "Check container %p: width %g vs %d, height %g vs %d", sibling, sibling->width + pixels, min_sane_w, sibling->height + pixels, min_sane_h); |
203 | return true; | 137 | if (use_width ? |
138 | sibling->width + pixels < min_sane_w : | ||
139 | sibling->height + pixels < min_sane_h) { | ||
140 | valid = false; | ||
141 | sway_log(L_DEBUG, "Container size no longer sane"); | ||
142 | break; | ||
204 | } | 143 | } |
205 | sway_log(L_DEBUG, "Found the proper parent: %p. It has %d b conts, and %d t conts", parent->parent, bnumber, tnumber); | 144 | i = use_major ? auto_group_end_index(parent, i) : (i + 1); |
206 | //TODO: Ensure rounding is done in such a way that there are NO pixel leaks | 145 | sway_log(L_DEBUG, "+++++ check %i", i); |
207 | bool valid = true; | 146 | } |
208 | for (i = 0; i < parent->parent->children->length; i++) { | 147 | // 3. Apply the size change |
209 | sibling = parent->parent->children->items[i]; | 148 | if (valid) { |
210 | if (sibling->y != focused->y) { | 149 | for (int i = start; i < end; ) { |
211 | if (sibling->y < parent->y) { | 150 | int next_i = use_major ? auto_group_end_index(parent, i) : (i + 1); |
212 | double pixels = -1 * amount; | 151 | swayc_t *sibling = parent->children->items[i]; |
213 | pixels /= bnumber; | 152 | double pixels = amount; |
214 | if (tnumber) { | 153 | bool is_before = use_width ? sibling->x < focused->x : sibling->y < focused->y; |
215 | if ((sibling->height + pixels/2) < min_sane_h) { | 154 | bool is_after = use_width ? sibling->x > focused->x : sibling->y > focused->y; |
216 | valid = false; | 155 | if (is_before || is_after) { |
217 | break; | 156 | pixels = -pixels; |
218 | } | 157 | pixels /= is_before ? nb_before : nb_after; |
219 | } else { | 158 | if (nb_after != 0 && nb_before != 0) { |
220 | if ((sibling->height + pixels) < min_sane_h) { | 159 | pixels /= 2; |
221 | valid = false; | 160 | } |
222 | break; | 161 | sway_log(L_DEBUG, "%p: %s", sibling, is_before ? "before" : "after"); |
223 | } | 162 | if (use_major) { |
224 | } | 163 | for (int j = i; j < next_i; ++j) { |
225 | } else if (sibling->y > parent->y) { | 164 | recursive_resize(parent->children->items[j], pixels, |
226 | double pixels = -1 * amount; | 165 | use_width ? |
227 | pixels /= tnumber; | 166 | (is_before ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_LEFT) : |
228 | if (bnumber) { | 167 | (is_before ? WLC_RESIZE_EDGE_BOTTOM : WLC_RESIZE_EDGE_TOP)); |
229 | if ((sibling->height + pixels/2) < min_sane_h) { | ||
230 | valid = false; | ||
231 | break; | ||
232 | } | ||
233 | } else { | ||
234 | if ((sibling->height + pixels) < min_sane_h) { | ||
235 | valid = false; | ||
236 | break; | ||
237 | } | ||
238 | } | 168 | } |
169 | } else { | ||
170 | recursive_resize(sibling, pixels, | ||
171 | use_width ? | ||
172 | (is_before ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_LEFT) : | ||
173 | (is_before ? WLC_RESIZE_EDGE_BOTTOM : WLC_RESIZE_EDGE_TOP)); | ||
239 | } | 174 | } |
240 | } else { | 175 | } else { |
241 | double pixels = amount; | 176 | if (use_major) { |
242 | if (parent->height + pixels < min_sane_h) { | 177 | for (int j = i; j < next_i; ++j) { |
243 | valid = false; | 178 | recursive_resize(parent->children->items[j], pixels / 2, |
244 | break; | 179 | use_width ? WLC_RESIZE_EDGE_LEFT : WLC_RESIZE_EDGE_TOP); |
245 | } | 180 | recursive_resize(parent->children->items[j], pixels / 2, |
246 | } | 181 | use_width ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_BOTTOM); |
247 | } | ||
248 | if (valid) { | ||
249 | for (i = 0; i < parent->parent->children->length; i++) { | ||
250 | sibling = parent->parent->children->items[i]; | ||
251 | if (sibling->y != focused->y) { | ||
252 | if (sibling->y < parent->y) { | ||
253 | double pixels = -1 * amount; | ||
254 | pixels /= bnumber; | ||
255 | if (tnumber) { | ||
256 | recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_BOTTOM); | ||
257 | } else { | ||
258 | recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_BOTTOM); | ||
259 | } | ||
260 | } else if (sibling->x > parent->x) { | ||
261 | double pixels = -1 * amount; | ||
262 | pixels /= tnumber; | ||
263 | if (bnumber) { | ||
264 | recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_TOP); | ||
265 | } else { | ||
266 | recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_TOP); | ||
267 | } | ||
268 | } | 182 | } |
269 | } else { | 183 | } else { |
270 | if (bnumber != 0 && tnumber != 0) { | 184 | recursive_resize(sibling, pixels / 2, |
271 | double pixels = amount/2; | 185 | use_width ? WLC_RESIZE_EDGE_LEFT : WLC_RESIZE_EDGE_TOP); |
272 | recursive_resize(parent, pixels, WLC_RESIZE_EDGE_TOP); | 186 | recursive_resize(sibling, pixels / 2, |
273 | recursive_resize(parent, pixels, WLC_RESIZE_EDGE_BOTTOM); | 187 | use_width ? WLC_RESIZE_EDGE_RIGHT : WLC_RESIZE_EDGE_BOTTOM); |
274 | } else if (tnumber) { | ||
275 | recursive_resize(parent, amount, WLC_RESIZE_EDGE_TOP); | ||
276 | } else if (bnumber) { | ||
277 | recursive_resize(parent, amount, WLC_RESIZE_EDGE_BOTTOM); | ||
278 | } | ||
279 | } | 188 | } |
280 | } | 189 | } |
281 | arrange_windows(swayc_active_workspace(), -1, -1); | 190 | i = next_i; |
282 | } | 191 | } |
283 | return true; | 192 | // Recursive resize does not handle positions, let arrange_windows |
193 | // take care of that. | ||
194 | arrange_windows(swayc_active_workspace(), -1, -1); | ||
284 | } | 195 | } |
285 | return true; | 196 | return true; |
286 | } | 197 | } |