summaryrefslogtreecommitdiffstats
path: root/sway/commands/resize.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/commands/resize.c')
-rw-r--r--sway/commands/resize.c313
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
65static bool resize_tiled(int amount, bool use_width) { 65static 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}