aboutsummaryrefslogtreecommitdiffstats
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
parentRemove IPC_GET_PIXELS (diff)
downloadsway-ce1936bc65d01502e3a5f8681bb039cb95e82e0c.tar.gz
sway-ce1936bc65d01502e3a5f8681bb039cb95e82e0c.tar.zst
sway-ce1936bc65d01502e3a5f8681bb039cb95e82e0c.zip
Arrange windows on desktop
-rw-r--r--include/sway/container.h2
-rw-r--r--include/sway/layout.h1
-rw-r--r--include/sway/output.h1
-rw-r--r--include/sway/view.h2
-rw-r--r--sway/desktop/output.c15
-rw-r--r--sway/desktop/xdg_shell_v6.c20
-rw-r--r--sway/tree/container.c13
-rw-r--r--sway/tree/layout.c205
8 files changed, 253 insertions, 6 deletions
diff --git a/include/sway/container.h b/include/sway/container.h
index 96e4db69..1a173f3e 100644
--- a/include/sway/container.h
+++ b/include/sway/container.h
@@ -132,4 +132,6 @@ swayc_t *new_output(struct sway_output *sway_output);
132swayc_t *new_workspace(swayc_t *output, const char *name); 132swayc_t *new_workspace(swayc_t *output, const char *name);
133swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view); 133swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view);
134 134
135swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type);
136
135#endif 137#endif
diff --git a/include/sway/layout.h b/include/sway/layout.h
index 6356ad00..505036a0 100644
--- a/include/sway/layout.h
+++ b/include/sway/layout.h
@@ -7,5 +7,6 @@ void init_layout(void);
7void add_child(struct sway_container *parent, struct sway_container *child); 7void add_child(struct sway_container *parent, struct sway_container *child);
8enum swayc_layouts default_layout(struct sway_container *output); 8enum swayc_layouts default_layout(struct sway_container *output);
9void sort_workspaces(struct sway_container *output); 9void sort_workspaces(struct sway_container *output);
10void arrange_windows(struct sway_container *container, double width, double height);
10 11
11#endif 12#endif
diff --git a/include/sway/output.h b/include/sway/output.h
index e2f81bcb..895cb07d 100644
--- a/include/sway/output.h
+++ b/include/sway/output.h
@@ -13,6 +13,7 @@ struct sway_output {
13 struct sway_server *server; 13 struct sway_server *server;
14 struct timespec last_frame; 14 struct timespec last_frame;
15 struct wl_listener frame; 15 struct wl_listener frame;
16 struct wl_listener resolution;
16}; 17};
17 18
18#endif 19#endif
diff --git a/include/sway/view.h b/include/sway/view.h
index 2675a6f5..9d503674 100644
--- a/include/sway/view.h
+++ b/include/sway/view.h
@@ -52,6 +52,8 @@ struct sway_view {
52 struct { 52 struct {
53 const char *(*get_prop)(struct sway_view *view, 53 const char *(*get_prop)(struct sway_view *view,
54 enum sway_view_prop prop); 54 enum sway_view_prop prop);
55 void (*set_dimensions)(struct sway_view *view,
56 int width, int height);
55 } iface; 57 } iface;
56}; 58};
57 59
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 9e0c18e4..033a4c44 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -8,6 +8,7 @@
8#include <wlr/render/matrix.h> 8#include <wlr/render/matrix.h>
9#include "log.h" 9#include "log.h"
10#include "sway/container.h" 10#include "sway/container.h"
11#include "sway/layout.h"
11#include "sway/output.h" 12#include "sway/output.h"
12#include "sway/server.h" 13#include "sway/server.h"
13#include "sway/view.h" 14#include "sway/view.h"
@@ -25,10 +26,9 @@ static void output_frame_view(swayc_t *view, void *data) {
25 return; 26 return;
26 } 27 }
27 // TODO 28 // TODO
28 // - Force sway's resolution
29 // - Deal with wlr_output_layout 29 // - Deal with wlr_output_layout
30 int width = surface->current->width; 30 int width = sway_view->swayc->width;
31 int height = surface->current->height; 31 int height = sway_view->swayc->height;
32 int render_width = width * wlr_output->scale; 32 int render_width = width * wlr_output->scale;
33 int render_height = height * wlr_output->scale; 33 int render_height = height * wlr_output->scale;
34 double ox = view->x, oy = view->y; 34 double ox = view->x, oy = view->y;
@@ -101,6 +101,12 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
101 soutput->last_frame = now; 101 soutput->last_frame = now;
102} 102}
103 103
104static void output_resolution_notify(struct wl_listener *listener, void *data) {
105 struct sway_output *soutput = wl_container_of(
106 listener, soutput, resolution);
107 arrange_windows(soutput->swayc, -1, -1);
108}
109
104void output_add_notify(struct wl_listener *listener, void *data) { 110void output_add_notify(struct wl_listener *listener, void *data) {
105 struct sway_server *server = wl_container_of(listener, server, output_add); 111 struct sway_server *server = wl_container_of(listener, server, output_add);
106 struct wlr_output *wlr_output = data; 112 struct wlr_output *wlr_output = data;
@@ -113,6 +119,9 @@ void output_add_notify(struct wl_listener *listener, void *data) {
113 119
114 output->frame.notify = output_frame_notify; 120 output->frame.notify = output_frame_notify;
115 wl_signal_add(&wlr_output->events.frame, &output->frame); 121 wl_signal_add(&wlr_output->events.frame, &output->frame);
122
123 output->resolution.notify = output_resolution_notify;
124 wl_signal_add(&wlr_output->events.resolution, &output->resolution);
116} 125}
117 126
118void output_remove_notify(struct wl_listener *listener, void *data) { 127void output_remove_notify(struct wl_listener *listener, void *data) {
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index e2a61ebf..8f1885c1 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -1,15 +1,21 @@
1#define _POSIX_C_SOURCE 199309L 1#define _POSIX_C_SOURCE 199309L
2#include <stdbool.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <wayland-server.h> 4#include <wayland-server.h>
4#include <wlr/types/wlr_xdg_shell_v6.h> 5#include <wlr/types/wlr_xdg_shell_v6.h>
5#include "sway/container.h" 6#include "sway/container.h"
7#include "sway/layout.h"
6#include "sway/server.h" 8#include "sway/server.h"
7#include "sway/view.h" 9#include "sway/view.h"
8#include "log.h" 10#include "log.h"
9 11
12static bool assert_xdg(struct sway_view *view) {
13 return sway_assert(view->type == SWAY_XDG_SHELL_V6_VIEW,
14 "Expected xdg shell v6 view!");
15}
16
10static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { 17static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
11 if (!sway_assert(view->type == SWAY_XDG_SHELL_V6_VIEW, 18 if (!assert_xdg(view)) {
12 "xdg get_prop for non-xdg view!")) {
13 return NULL; 19 return NULL;
14 } 20 }
15 switch (prop) { 21 switch (prop) {
@@ -22,6 +28,12 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
22 } 28 }
23} 29}
24 30
31static void set_dimensions(struct sway_view *view, int width, int height) {
32 if (assert_xdg(view)) {
33 wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height);
34 }
35}
36
25void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { 37void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
26 struct sway_server *server = wl_container_of( 38 struct sway_server *server = wl_container_of(
27 listener, server, xdg_shell_v6_surface); 39 listener, server, xdg_shell_v6_surface);
@@ -48,13 +60,13 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
48 } 60 }
49 sway_view->type = SWAY_XDG_SHELL_V6_VIEW; 61 sway_view->type = SWAY_XDG_SHELL_V6_VIEW;
50 sway_view->iface.get_prop = get_prop; 62 sway_view->iface.get_prop = get_prop;
63 sway_view->iface.set_dimensions = set_dimensions;
51 sway_view->wlr_xdg_surface_v6 = xdg_surface; 64 sway_view->wlr_xdg_surface_v6 = xdg_surface;
52 sway_view->sway_xdg_surface_v6 = sway_surface; 65 sway_view->sway_xdg_surface_v6 = sway_surface;
53 sway_view->surface = xdg_surface->surface; 66 sway_view->surface = xdg_surface->surface;
54 sway_surface->view = sway_view; 67 sway_surface->view = sway_view;
55 68
56 // TODO: 69 // TODO:
57 // - Add to tree
58 // - Wire up listeners 70 // - Wire up listeners
59 // - Handle popups 71 // - Handle popups
60 // - Look up pid and open on appropriate workspace 72 // - Look up pid and open on appropriate workspace
@@ -67,4 +79,6 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
67 79
68 swayc_t *cont = new_view(parent, sway_view); 80 swayc_t *cont = new_view(parent, sway_view);
69 sway_view->swayc = cont; 81 sway_view->swayc = cont;
82
83 arrange_windows(cont->parent, -1, -1);
70} 84}
diff --git a/sway/tree/container.c b/sway/tree/container.c
index d3931612..a83c0f6b 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -108,3 +108,16 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) {
108 } 108 }
109 return swayc; 109 return swayc;
110} 110}
111
112swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) {
113 if (!sway_assert(container, "container is NULL")) {
114 return NULL;
115 }
116 if (!sway_assert(type < C_TYPES && type >= C_ROOT, "invalid type")) {
117 return NULL;
118 }
119 do {
120 container = container->parent;
121 } while (container && container->type != type);
122 return container;
123}
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}