aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/layout.c
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2017-11-25 10:59:49 -0500
committerLibravatar Drew DeVault <sir@cmpwn.com>2017-11-25 11:19:25 -0500
commitce1936bc65d01502e3a5f8681bb039cb95e82e0c (patch)
treefcdeb554df5aaf30aff7723171e0dfe0bf097420 /sway/tree/layout.c
parentRemove IPC_GET_PIXELS (diff)
downloadsway-ce1936bc65d01502e3a5f8681bb039cb95e82e0c.tar.gz
sway-ce1936bc65d01502e3a5f8681bb039cb95e82e0c.tar.zst
sway-ce1936bc65d01502e3a5f8681bb039cb95e82e0c.zip
Arrange windows on desktop
Diffstat (limited to 'sway/tree/layout.c')
-rw-r--r--sway/tree/layout.c205
1 files changed, 205 insertions, 0 deletions
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index 5a70c570..3d6b404d 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -1,10 +1,14 @@
1#define _POSIX_C_SOURCE 200809L 1#define _POSIX_C_SOURCE 200809L
2#include <ctype.h> 2#include <ctype.h>
3#include <math.h>
3#include <stdbool.h> 4#include <stdbool.h>
4#include <stdlib.h> 5#include <stdlib.h>
5#include <string.h> 6#include <string.h>
7#include <wlr/types/wlr_output.h>
6#include <wlr/types/wlr_output_layout.h> 8#include <wlr/types/wlr_output_layout.h>
7#include "sway/container.h" 9#include "sway/container.h"
10#include "sway/output.h"
11#include "sway/view.h"
8#include "list.h" 12#include "list.h"
9#include "log.h" 13#include "log.h"
10 14
@@ -70,3 +74,204 @@ static int sort_workspace_cmp_qsort(const void *_a, const void *_b) {
70void sort_workspaces(swayc_t *output) { 74void sort_workspaces(swayc_t *output) {
71 list_stable_sort(output->children, sort_workspace_cmp_qsort); 75 list_stable_sort(output->children, sort_workspace_cmp_qsort);
72} 76}
77
78static void apply_horiz_layout(swayc_t *container, const double x,
79 const double y, const double width,
80 const double height, const int start,
81 const int end);
82
83static void apply_vert_layout(swayc_t *container, const double x,
84 const double y, const double width,
85 const double height, const int start,
86 const int end);
87
88void arrange_windows(swayc_t *container, double width, double height) {
89 int i;
90 if (width == -1 || height == -1) {
91 width = container->width;
92 height = container->height;
93 }
94 // pixels are indivisible. if we don't round the pixels, then the view
95 // calculations will be off (e.g. 50.5 + 50.5 = 101, but in reality it's
96 // 50 + 50 = 100). doing it here cascades properly to all width/height/x/y.
97 width = floor(width);
98 height = floor(height);
99
100 sway_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", container,
101 container->name, container->width, container->height, container->x,
102 container->y);
103
104 double x = 0, y = 0;
105 switch (container->type) {
106 case C_ROOT:
107 // TODO: wlr_output_layout probably
108 for (i = 0; i < container->children->length; ++i) {
109 swayc_t *output = container->children->items[i];
110 sway_log(L_DEBUG, "Arranging output '%s' at %f,%f",
111 output->name, output->x, output->y);
112 arrange_windows(output, -1, -1);
113 }
114 return;
115 case C_OUTPUT:
116 {
117 int _width, _height;
118 wlr_output_effective_resolution(
119 container->sway_output->wlr_output, &_width, &_height);
120 width = container->width = _width;
121 height = container->height = _height;
122 }
123 // arrange all workspaces:
124 for (i = 0; i < container->children->length; ++i) {
125 swayc_t *child = container->children->items[i];
126 arrange_windows(child, -1, -1);
127 }
128 return;
129 case C_WORKSPACE:
130 {
131 swayc_t *output = swayc_parent_by_type(container, C_OUTPUT);
132 width = output->width, height = output->height;
133 container->x = x;
134 container->y = y;
135 width = container->width;
136 height = container->height;
137 sway_log(L_DEBUG, "Arranging workspace '%s' at %f, %f",
138 container->name, container->x, container->y);
139 }
140 // children are properly handled below
141 break;
142 case C_VIEW:
143 {
144 container->width = width;
145 container->height = height;
146 container->sway_view->iface.set_dimensions(container->sway_view,
147 container->width, container->height);
148 sway_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f",
149 container->width, container->height,
150 container->x, container->y);
151 }
152 return;
153 default:
154 container->width = width;
155 container->height = height;
156 x = container->x;
157 y = container->y;
158 break;
159 }
160
161 switch (container->layout) {
162 case L_HORIZ:
163 apply_horiz_layout(container, x, y, width, height, 0,
164 container->children->length);
165 break;
166 case L_VERT:
167 apply_vert_layout(container, x, y, width, height, 0,
168 container->children->length);
169 break;
170 default:
171 sway_log(L_DEBUG, "TODO: arrange layout type %d", container->layout);
172 apply_horiz_layout(container, x, y, width, height, 0,
173 container->children->length);
174 break;
175 }
176}
177
178static void apply_horiz_layout(swayc_t *container,
179 const double x, const double y,
180 const double width, const double height,
181 const int start, const int end) {
182 double scale = 0;
183 // Calculate total width
184 for (int i = start; i < end; ++i) {
185 double *old_width = &((swayc_t *)container->children->items[i])->width;
186 if (*old_width <= 0) {
187 if (end - start > 1) {
188 *old_width = width / (end - start - 1);
189 } else {
190 *old_width = width;
191 }
192 }
193 scale += *old_width;
194 }
195 scale = width / scale;
196
197 // Resize windows
198 double child_x = x;
199 if (scale > 0.1) {
200 sway_log(L_DEBUG, "Arranging %p horizontally", container);
201 for (int i = start; i < end; ++i) {
202 swayc_t *child = container->children->items[i];
203 sway_log(L_DEBUG,
204 "Calculating arrangement for %p:%d (will scale %f by %f)",
205 child, child->type, width, scale);
206 child->x = child_x;
207 child->y = y;
208
209 if (i == end - 1) {
210 double remaining_width = x + width - child_x;
211 arrange_windows(child, remaining_width, height);
212 } else {
213 arrange_windows(child, child->width * scale, height);
214 }
215 child_x += child->width;
216 }
217
218 // update focused view border last because it may
219 // depend on the title bar geometry of its siblings.
220 /* TODO WLR
221 if (focused && container->children->length > 1) {
222 update_container_border(focused);
223 }
224 */
225 }
226}
227
228void apply_vert_layout(swayc_t *container,
229 const double x, const double y,
230 const double width, const double height, const int start,
231 const int end) {
232 int i;
233 double scale = 0;
234 // Calculate total height
235 for (i = start; i < end; ++i) {
236 double *old_height = &((swayc_t *)container->children->items[i])->height;
237 if (*old_height <= 0) {
238 if (end - start > 1) {
239 *old_height = height / (end - start - 1);
240 } else {
241 *old_height = height;
242 }
243 }
244 scale += *old_height;
245 }
246 scale = height / scale;
247
248 // Resize
249 double child_y = y;
250 if (scale > 0.1) {
251 sway_log(L_DEBUG, "Arranging %p vertically", container);
252 for (i = start; i < end; ++i) {
253 swayc_t *child = container->children->items[i];
254 sway_log(L_DEBUG,
255 "Calculating arrangement for %p:%d (will scale %f by %f)",
256 child, child->type, height, scale);
257 child->x = x;
258 child->y = child_y;
259
260 if (i == end - 1) {
261 double remaining_height = y + height - child_y;
262 arrange_windows(child, width, remaining_height);
263 } else {
264 arrange_windows(child, width, child->height * scale);
265 }
266 child_y += child->height;
267 }
268
269 // update focused view border last because it may
270 // depend on the title bar geometry of its siblings.
271 /* TODO WLR
272 if (focused && container->children->length > 1) {
273 update_container_border(focused);
274 }
275 */
276 }
277}