aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/server.h1
-rw-r--r--include/sway/tree/container.h8
-rw-r--r--include/sway/tree/layout.h3
-rw-r--r--sway/desktop/output.c25
-rw-r--r--sway/desktop/xwayland.c36
-rw-r--r--sway/input/seat.c4
-rw-r--r--sway/server.c18
-rw-r--r--sway/tree/container.c55
-rw-r--r--sway/tree/layout.c37
9 files changed, 138 insertions, 49 deletions
diff --git a/include/sway/server.h b/include/sway/server.h
index 25eb64fe..db81932f 100644
--- a/include/sway/server.h
+++ b/include/sway/server.h
@@ -18,7 +18,6 @@ struct sway_server {
18 const char *socket; 18 const char *socket;
19 19
20 struct wlr_backend *backend; 20 struct wlr_backend *backend;
21 struct wlr_renderer *renderer;
22 21
23 struct wlr_compositor *compositor; 22 struct wlr_compositor *compositor;
24 struct wlr_data_device_manager *data_device_manager; 23 struct wlr_data_device_manager *data_device_manager;
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index 3bb497db..24e8468e 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -99,8 +99,13 @@ struct sway_container *container_view_create(
99 99
100struct sway_container *container_output_destroy(struct sway_container *output); 100struct sway_container *container_output_destroy(struct sway_container *output);
101 101
102struct sway_container *container_workspace_destroy(
103 struct sway_container *workspace);
104
102struct sway_container *container_view_destroy(struct sway_container *view); 105struct sway_container *container_view_destroy(struct sway_container *view);
103 106
107void container_destroy(struct sway_container *cont);
108
104struct sway_container *container_set_layout(struct sway_container *container, 109struct sway_container *container_set_layout(struct sway_container *container,
105 enum sway_container_layout layout); 110 enum sway_container_layout layout);
106 111
@@ -140,4 +145,7 @@ void container_for_each_descendant_bfs(struct sway_container *container,
140void container_for_each_descendant_dfs(struct sway_container *container, 145void container_for_each_descendant_dfs(struct sway_container *container,
141 void (*f)(struct sway_container *container, void *data), void *data); 146 void (*f)(struct sway_container *container, void *data), void *data);
142 147
148bool container_has_anscestor(struct sway_container *descendant,
149 struct sway_container *anscestor);
150
143#endif 151#endif
diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h
index ad52bdb0..8239366b 100644
--- a/include/sway/tree/layout.h
+++ b/include/sway/tree/layout.h
@@ -39,6 +39,9 @@ struct sway_container *container_add_sibling(struct sway_container *parent,
39 39
40struct sway_container *container_remove_child(struct sway_container *child); 40struct sway_container *container_remove_child(struct sway_container *child);
41 41
42void container_move_to(struct sway_container* container,
43 struct sway_container* destination);
44
42enum sway_container_layout container_get_default_layout(struct sway_container *output); 45enum sway_container_layout container_get_default_layout(struct sway_container *output);
43 46
44void container_sort_workspaces(struct sway_container *output); 47void container_sort_workspaces(struct sway_container *output);
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 87eb80fe..f3416c03 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -41,6 +41,9 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh,
41static void render_surface(struct wlr_surface *surface, 41static void render_surface(struct wlr_surface *surface,
42 struct wlr_output *wlr_output, struct timespec *when, 42 struct wlr_output *wlr_output, struct timespec *when,
43 double lx, double ly, float rotation) { 43 double lx, double ly, float rotation) {
44 struct wlr_renderer *renderer =
45 wlr_backend_get_renderer(wlr_output->backend);
46
44 if (!wlr_surface_has_buffer(surface)) { 47 if (!wlr_surface_has_buffer(surface)) {
45 return; 48 return;
46 } 49 }
@@ -65,8 +68,8 @@ static void render_surface(struct wlr_surface *surface,
65 float matrix[9]; 68 float matrix[9];
66 wlr_matrix_project_box(matrix, &render_box, surface->current->transform, 69 wlr_matrix_project_box(matrix, &render_box, surface->current->transform,
67 0, wlr_output->transform_matrix); 70 0, wlr_output->transform_matrix);
68 wlr_render_texture_with_matrix(server.renderer, surface->texture, 71 wlr_render_texture_with_matrix(renderer, surface->texture, matrix,
69 matrix, 1.0f); // TODO: configurable alpha 72 1.0f); // TODO: configurable alpha
70 73
71 wlr_surface_send_frame_done(surface, when); 74 wlr_surface_send_frame_done(surface, when);
72 } 75 }
@@ -192,15 +195,14 @@ static void render_layer(struct sway_output *output,
192 } 195 }
193} 196}
194 197
195static void output_frame_notify(struct wl_listener *listener, void *data) { 198static void handle_output_frame(struct wl_listener *listener, void *data) {
196 struct sway_output *soutput = wl_container_of(listener, soutput, frame); 199 struct sway_output *soutput = wl_container_of(listener, soutput, frame);
197 struct wlr_output *wlr_output = data; 200 struct wlr_output *wlr_output = data;
198 struct sway_server *server = soutput->server; 201 struct wlr_renderer *renderer =
199 struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); 202 wlr_backend_get_renderer(wlr_output->backend);
200 203
201 int buffer_age = -1; 204 wlr_output_make_current(wlr_output, NULL);
202 wlr_output_make_current(wlr_output, &buffer_age); 205 wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height);
203 wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height);
204 206
205 float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; 207 float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
206 wlr_renderer_clear(renderer, clear_color); 208 wlr_renderer_clear(renderer, clear_color);
@@ -218,7 +220,8 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
218 &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); 220 &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
219 221
220 struct sway_seat *seat = input_manager_current_seat(input_manager); 222 struct sway_seat *seat = input_manager_current_seat(input_manager);
221 struct sway_container *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); 223 struct sway_container *focus =
224 sway_seat_get_focus_inactive(seat, soutput->swayc);
222 struct sway_container *workspace = (focus->type == C_WORKSPACE ? 225 struct sway_container *workspace = (focus->type == C_WORKSPACE ?
223 focus : 226 focus :
224 container_parent(focus, C_WORKSPACE)); 227 container_parent(focus, C_WORKSPACE));
@@ -248,7 +251,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
248 render_layer(soutput, output_box, &now, 251 render_layer(soutput, output_box, &now,
249 &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); 252 &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
250 253
251 wlr_renderer_end(server->renderer); 254 wlr_renderer_end(renderer);
252 wlr_output_swap_buffers(wlr_output, &now, NULL); 255 wlr_output_swap_buffers(wlr_output, &now, NULL);
253 soutput->last_frame = now; 256 soutput->last_frame = now;
254} 257}
@@ -306,7 +309,7 @@ void handle_new_output(struct wl_listener *listener, void *data) {
306 sway_input_manager_configure_xcursor(input_manager); 309 sway_input_manager_configure_xcursor(input_manager);
307 310
308 wl_signal_add(&wlr_output->events.frame, &output->frame); 311 wl_signal_add(&wlr_output->events.frame, &output->frame);
309 output->frame.notify = output_frame_notify; 312 output->frame.notify = handle_output_frame;
310 wl_signal_add(&wlr_output->events.destroy, &output->destroy); 313 wl_signal_add(&wlr_output->events.destroy, &output->destroy);
311 output->destroy.notify = handle_output_destroy; 314 output->destroy.notify = handle_output_destroy;
312 wl_signal_add(&wlr_output->events.mode, &output->mode); 315 wl_signal_add(&wlr_output->events.mode, &output->mode);
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 38ee4656..d608c8b6 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -104,14 +104,11 @@ static void handle_commit(struct wl_listener *listener, void *data) {
104static void handle_destroy(struct wl_listener *listener, void *data) { 104static void handle_destroy(struct wl_listener *listener, void *data) {
105 struct sway_xwayland_surface *sway_surface = 105 struct sway_xwayland_surface *sway_surface =
106 wl_container_of(listener, sway_surface, destroy); 106 wl_container_of(listener, sway_surface, destroy);
107 struct wlr_xwayland_surface *xsurface = data; 107
108 wl_list_remove(&sway_surface->commit.link); 108 wl_list_remove(&sway_surface->commit.link);
109 wl_list_remove(&sway_surface->destroy.link); 109 wl_list_remove(&sway_surface->destroy.link);
110 wl_list_remove(&sway_surface->request_configure.link); 110 wl_list_remove(&sway_surface->request_configure.link);
111 if (xsurface->override_redirect && xsurface->mapped) { 111 wl_list_remove(&sway_surface->view->unmanaged_view_link);
112 wl_list_remove(&sway_surface->view->unmanaged_view_link);
113 wl_list_init(&sway_surface->view->unmanaged_view_link);
114 }
115 112
116 struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); 113 struct sway_container *parent = container_view_destroy(sway_surface->view->swayc);
117 if (parent) { 114 if (parent) {
@@ -125,11 +122,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
125static void handle_unmap_notify(struct wl_listener *listener, void *data) { 122static void handle_unmap_notify(struct wl_listener *listener, void *data) {
126 struct sway_xwayland_surface *sway_surface = 123 struct sway_xwayland_surface *sway_surface =
127 wl_container_of(listener, sway_surface, unmap_notify); 124 wl_container_of(listener, sway_surface, unmap_notify);
128 struct wlr_xwayland_surface *xsurface = data; 125
129 if (xsurface->override_redirect && xsurface->mapped) { 126 wl_list_remove(&sway_surface->view->unmanaged_view_link);
130 wl_list_remove(&sway_surface->view->unmanaged_view_link); 127 wl_list_init(&sway_surface->view->unmanaged_view_link);
131 wl_list_init(&sway_surface->view->unmanaged_view_link);
132 }
133 128
134 // take it out of the tree 129 // take it out of the tree
135 struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); 130 struct sway_container *parent = container_view_destroy(sway_surface->view->swayc);
@@ -150,7 +145,9 @@ static void handle_map_notify(struct wl_listener *listener, void *data) {
150 sway_surface->view->surface = xsurface->surface; 145 sway_surface->view->surface = xsurface->surface;
151 146
152 // put it back into the tree 147 // put it back into the tree
153 if (xsurface->override_redirect) { 148 if (wlr_xwayland_surface_is_unmanaged(xsurface) ||
149 xsurface->override_redirect) {
150 wl_list_remove(&sway_surface->view->unmanaged_view_link);
154 wl_list_insert(&root_container.sway_root->unmanaged_views, 151 wl_list_insert(&root_container.sway_root->unmanaged_views,
155 &sway_surface->view->unmanaged_view_link); 152 &sway_surface->view->unmanaged_view_link);
156 } else { 153 } else {
@@ -209,6 +206,8 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
209 sway_view->surface = xsurface->surface; 206 sway_view->surface = xsurface->surface;
210 sway_surface->view = sway_view; 207 sway_surface->view = sway_view;
211 208
209 wl_list_init(&sway_view->unmanaged_view_link);
210
212 // TODO: 211 // TODO:
213 // - Look up pid and open on appropriate workspace 212 // - Look up pid and open on appropriate workspace
214 // - Set new view to maximized so it behaves nicely 213 // - Set new view to maximized so it behaves nicely
@@ -230,18 +229,5 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
230 wl_signal_add(&xsurface->events.map_notify, &sway_surface->map_notify); 229 wl_signal_add(&xsurface->events.map_notify, &sway_surface->map_notify);
231 sway_surface->map_notify.notify = handle_map_notify; 230 sway_surface->map_notify.notify = handle_map_notify;
232 231
233 if (wlr_xwayland_surface_is_unmanaged(xsurface)) { 232 handle_map_notify(&sway_surface->map_notify, xsurface);
234 // these don't get a container in the tree
235 wl_list_insert(&root_container.sway_root->unmanaged_views,
236 &sway_view->unmanaged_view_link);
237 return;
238 }
239
240 struct sway_seat *seat = input_manager_current_seat(input_manager);
241 struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container);
242 struct sway_container *cont = container_view_create(focus, sway_view);
243 sway_view->swayc = cont;
244
245 arrange_windows(cont->parent, -1, -1);
246 sway_input_manager_set_focus(input_manager, cont);
247} 233}
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 7cf0dd08..ae536264 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -8,6 +8,7 @@
8#include "sway/input/keyboard.h" 8#include "sway/input/keyboard.h"
9#include "sway/ipc-server.h" 9#include "sway/ipc-server.h"
10#include "sway/output.h" 10#include "sway/output.h"
11#include "sway/tree/container.h"
11#include "sway/tree/view.h" 12#include "sway/tree/view.h"
12#include "log.h" 13#include "log.h"
13 14
@@ -331,6 +332,9 @@ void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *containe
331 if (last_ws) { 332 if (last_ws) {
332 wlr_log(L_DEBUG, "sending workspace event"); 333 wlr_log(L_DEBUG, "sending workspace event");
333 ipc_event_workspace(last_ws, container, "focus"); 334 ipc_event_workspace(last_ws, container, "focus");
335 if (last_ws->children->length == 0) {
336 container_workspace_destroy(last_ws);
337 }
334 } 338 }
335 } 339 }
336 340
diff --git a/sway/server.c b/sway/server.c
index 3fba019d..728e624e 100644
--- a/sway/server.c
+++ b/sway/server.c
@@ -1,19 +1,19 @@
1#define _POSIX_C_SOURCE 200112L 1#define _POSIX_C_SOURCE 200112L
2#include <stdlib.h> 2#include <assert.h>
3#include <stdbool.h> 3#include <stdbool.h>
4#include <stdlib.h>
4#include <wayland-server.h> 5#include <wayland-server.h>
5#include <wlr/backend.h> 6#include <wlr/backend.h>
6#include <wlr/backend/session.h> 7#include <wlr/backend/session.h>
7#include <wlr/render/wlr_renderer.h> 8#include <wlr/render/wlr_renderer.h>
8#include <wlr/render/gles2.h>
9#include <wlr/types/wlr_compositor.h> 9#include <wlr/types/wlr_compositor.h>
10#include <wlr/types/wlr_gamma_control.h>
10#include <wlr/types/wlr_layer_shell.h> 11#include <wlr/types/wlr_layer_shell.h>
11#include <wlr/types/wlr_screenshooter.h> 12#include <wlr/types/wlr_screenshooter.h>
12#include <wlr/types/wlr_gamma_control.h>
13#include <wlr/types/wlr_wl_shell.h> 13#include <wlr/types/wlr_wl_shell.h>
14#include <wlr/util/log.h>
14// TODO WLR: make Xwayland optional 15// TODO WLR: make Xwayland optional
15#include <wlr/xwayland.h> 16#include <wlr/xwayland.h>
16#include <wlr/util/log.h>
17#include "sway/commands.h" 17#include "sway/commands.h"
18#include "sway/config.h" 18#include "sway/config.h"
19#include "sway/server.h" 19#include "sway/server.h"
@@ -42,11 +42,12 @@ bool server_init(struct sway_server *server) {
42 server->wl_event_loop = wl_display_get_event_loop(server->wl_display); 42 server->wl_event_loop = wl_display_get_event_loop(server->wl_display);
43 server->backend = wlr_backend_autocreate(server->wl_display); 43 server->backend = wlr_backend_autocreate(server->wl_display);
44 44
45 server->renderer = wlr_gles2_renderer_create(server->backend); 45 struct wlr_renderer *renderer = wlr_backend_get_renderer(server->backend);
46 assert(renderer);
47
46 wl_display_init_shm(server->wl_display); 48 wl_display_init_shm(server->wl_display);
47 49
48 server->compositor = wlr_compositor_create( 50 server->compositor = wlr_compositor_create(server->wl_display, renderer);
49 server->wl_display, server->renderer);
50 server->data_device_manager = 51 server->data_device_manager =
51 wlr_data_device_manager_create(server->wl_display); 52 wlr_data_device_manager_create(server->wl_display);
52 53
@@ -95,8 +96,7 @@ bool server_init(struct sway_server *server) {
95} 96}
96 97
97void server_fini(struct sway_server *server) { 98void server_fini(struct sway_server *server) {
98 // TODO WLR: tear down more stuff 99 // TODO
99 wlr_backend_destroy(server->backend);
100} 100}
101 101
102void server_run(struct sway_server *server) { 102void server_run(struct sway_server *server) {
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 2eac812e..ed39a154 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -58,7 +58,7 @@ static struct sway_container *container_create(enum sway_container_type type) {
58 return c; 58 return c;
59} 59}
60 60
61static void container_destroy(struct sway_container *cont) { 61void container_destroy(struct sway_container *cont) {
62 if (cont == NULL) { 62 if (cont == NULL) {
63 return; 63 return;
64 } 64 }
@@ -203,8 +203,7 @@ struct sway_container *container_view_create(struct sway_container *sibling,
203} 203}
204 204
205struct sway_container *container_output_destroy(struct sway_container *output) { 205struct sway_container *container_output_destroy(struct sway_container *output) {
206 if (!sway_assert(output, 206 if (!sway_assert(output, "cannot destroy null output")) {
207 "null output passed to container_output_destroy")) {
208 return NULL; 207 return NULL;
209 } 208 }
210 209
@@ -236,6 +235,45 @@ struct sway_container *container_output_destroy(struct sway_container *output) {
236 return &root_container; 235 return &root_container;
237} 236}
238 237
238struct sway_container *container_workspace_destroy(
239 struct sway_container *workspace) {
240 if (!sway_assert(workspace, "cannot destroy null workspace")) {
241 return NULL;
242 }
243
244 // Do not destroy this if it's the last workspace on this output
245 struct sway_container *output = container_parent(workspace, C_OUTPUT);
246 if (output && output->children->length == 1) {
247 return NULL;
248 }
249
250 struct sway_container *parent = workspace->parent;
251 if (workspace->children->length == 0) {
252 // destroy the WS if there are no children (TODO check for floating)
253 wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name);
254 ipc_event_workspace(workspace, NULL, "empty");
255 } else {
256 // Move children to a different workspace on this output
257 struct sway_container *new_workspace = NULL;
258 // TODO move floating
259 for (int i = 0; i < output->children->length; i++) {
260 if (output->children->items[i] != workspace) {
261 new_workspace = output->children->items[i];
262 break;
263 }
264 }
265
266 wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'",
267 workspace->name, new_workspace->name);
268 for (int i = 0; i < workspace->children->length; i++) {
269 container_move_to(workspace->children->items[i], new_workspace);
270 }
271 }
272
273 container_destroy(workspace);
274 return parent;
275}
276
239struct sway_container *container_view_destroy(struct sway_container *view) { 277struct sway_container *container_view_destroy(struct sway_container *view) {
240 if (!view) { 278 if (!view) {
241 return NULL; 279 return NULL;
@@ -438,3 +476,14 @@ void container_for_each_descendant_bfs(struct sway_container *con,
438 list_cat(queue, current->children); 476 list_cat(queue, current->children);
439 } 477 }
440} 478}
479
480bool container_has_anscestor(struct sway_container *descendant,
481 struct sway_container *anscestor) {
482 while (descendant->type != C_ROOT) {
483 descendant = descendant->parent;
484 if (descendant == anscestor) {
485 return true;
486 }
487 }
488 return false;
489}
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index c7cf16e6..73c4849b 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -11,6 +11,7 @@
11#include "sway/output.h" 11#include "sway/output.h"
12#include "sway/tree/view.h" 12#include "sway/tree/view.h"
13#include "sway/input/seat.h" 13#include "sway/input/seat.h"
14#include "sway/ipc-server.h"
14#include "list.h" 15#include "list.h"
15#include "log.h" 16#include "log.h"
16 17
@@ -121,6 +122,42 @@ struct sway_container *container_remove_child(struct sway_container *child) {
121 return parent; 122 return parent;
122} 123}
123 124
125struct sway_container *container_reap_empty(struct sway_container *container) {
126 if (!sway_assert(container, "reaping null container")) {
127 return NULL;
128 }
129 while (container->children->length == 0 && container->type == C_CONTAINER) {
130 wlr_log(L_DEBUG, "Container: Destroying container '%p'", container);
131 struct sway_container *parent = container->parent;
132 container_destroy(container);
133 container = parent;
134 }
135 return container;
136}
137
138void container_move_to(struct sway_container* container,
139 struct sway_container* destination) {
140 if (container == destination
141 || container_has_anscestor(container, destination)) {
142 return;
143 }
144 struct sway_container *old_parent = container_remove_child(container);
145 container->width = container->height = 0;
146 struct sway_container *new_parent =
147 container_add_sibling(destination, container);
148 if (destination->type == C_WORKSPACE) {
149 // If the workspace only has one child after adding one, it
150 // means that the workspace was just initialized.
151 // TODO: Consider floating views in this test
152 if (destination->children->length == 1) {
153 ipc_event_workspace(NULL, destination, "init");
154 }
155 }
156 old_parent = container_reap_empty(old_parent);
157 arrange_windows(old_parent, -1, -1);
158 arrange_windows(new_parent, -1, -1);
159}
160
124enum sway_container_layout container_get_default_layout( 161enum sway_container_layout container_get_default_layout(
125 struct sway_container *output) { 162 struct sway_container *output) {
126 if (config->default_layout != L_NONE) { 163 if (config->default_layout != L_NONE) {