aboutsummaryrefslogtreecommitdiff
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 {
const char *socket;
struct wlr_backend *backend;
- struct wlr_renderer *renderer;
struct wlr_compositor *compositor;
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(
struct sway_container *container_output_destroy(struct sway_container *output);
+struct sway_container *container_workspace_destroy(
+ struct sway_container *workspace);
+
struct sway_container *container_view_destroy(struct sway_container *view);
+void container_destroy(struct sway_container *cont);
+
struct sway_container *container_set_layout(struct sway_container *container,
enum sway_container_layout layout);
@@ -140,4 +145,7 @@ void container_for_each_descendant_bfs(struct sway_container *container,
void container_for_each_descendant_dfs(struct sway_container *container,
void (*f)(struct sway_container *container, void *data), void *data);
+bool container_has_anscestor(struct sway_container *descendant,
+ struct sway_container *anscestor);
+
#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,
struct sway_container *container_remove_child(struct sway_container *child);
+void container_move_to(struct sway_container* container,
+ struct sway_container* destination);
+
enum sway_container_layout container_get_default_layout(struct sway_container *output);
void 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,
static void render_surface(struct wlr_surface *surface,
struct wlr_output *wlr_output, struct timespec *when,
double lx, double ly, float rotation) {
+ struct wlr_renderer *renderer =
+ wlr_backend_get_renderer(wlr_output->backend);
+
if (!wlr_surface_has_buffer(surface)) {
return;
}
@@ -65,8 +68,8 @@ static void render_surface(struct wlr_surface *surface,
float matrix[9];
wlr_matrix_project_box(matrix, &render_box, surface->current->transform,
0, wlr_output->transform_matrix);
- wlr_render_texture_with_matrix(server.renderer, surface->texture,
- matrix, 1.0f); // TODO: configurable alpha
+ wlr_render_texture_with_matrix(renderer, surface->texture, matrix,
+ 1.0f); // TODO: configurable alpha
wlr_surface_send_frame_done(surface, when);
}
@@ -192,15 +195,14 @@ static void render_layer(struct sway_output *output,
}
}
-static void output_frame_notify(struct wl_listener *listener, void *data) {
+static void handle_output_frame(struct wl_listener *listener, void *data) {
struct sway_output *soutput = wl_container_of(listener, soutput, frame);
struct wlr_output *wlr_output = data;
- struct sway_server *server = soutput->server;
- struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend);
+ struct wlr_renderer *renderer =
+ wlr_backend_get_renderer(wlr_output->backend);
- int buffer_age = -1;
- wlr_output_make_current(wlr_output, &buffer_age);
- wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height);
+ wlr_output_make_current(wlr_output, NULL);
+ wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height);
float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
wlr_renderer_clear(renderer, clear_color);
@@ -218,7 +220,8 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
&soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *focus = sway_seat_get_focus_inactive(seat, soutput->swayc);
+ struct sway_container *focus =
+ sway_seat_get_focus_inactive(seat, soutput->swayc);
struct sway_container *workspace = (focus->type == C_WORKSPACE ?
focus :
container_parent(focus, C_WORKSPACE));
@@ -248,7 +251,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
render_layer(soutput, output_box, &now,
&soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
- wlr_renderer_end(server->renderer);
+ wlr_renderer_end(renderer);
wlr_output_swap_buffers(wlr_output, &now, NULL);
soutput->last_frame = now;
}
@@ -306,7 +309,7 @@ void handle_new_output(struct wl_listener *listener, void *data) {
sway_input_manager_configure_xcursor(input_manager);
wl_signal_add(&wlr_output->events.frame, &output->frame);
- output->frame.notify = output_frame_notify;
+ output->frame.notify = handle_output_frame;
wl_signal_add(&wlr_output->events.destroy, &output->destroy);
output->destroy.notify = handle_output_destroy;
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) {
static void handle_destroy(struct wl_listener *listener, void *data) {
struct sway_xwayland_surface *sway_surface =
wl_container_of(listener, sway_surface, destroy);
- struct wlr_xwayland_surface *xsurface = data;
+
wl_list_remove(&sway_surface->commit.link);
wl_list_remove(&sway_surface->destroy.link);
wl_list_remove(&sway_surface->request_configure.link);
- if (xsurface->override_redirect && xsurface->mapped) {
- wl_list_remove(&sway_surface->view->unmanaged_view_link);
- wl_list_init(&sway_surface->view->unmanaged_view_link);
- }
+ wl_list_remove(&sway_surface->view->unmanaged_view_link);
struct sway_container *parent = container_view_destroy(sway_surface->view->swayc);
if (parent) {
@@ -125,11 +122,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
static void handle_unmap_notify(struct wl_listener *listener, void *data) {
struct sway_xwayland_surface *sway_surface =
wl_container_of(listener, sway_surface, unmap_notify);
- struct wlr_xwayland_surface *xsurface = data;
- if (xsurface->override_redirect && xsurface->mapped) {
- wl_list_remove(&sway_surface->view->unmanaged_view_link);
- wl_list_init(&sway_surface->view->unmanaged_view_link);
- }
+
+ wl_list_remove(&sway_surface->view->unmanaged_view_link);
+ wl_list_init(&sway_surface->view->unmanaged_view_link);
// take it out of the tree
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) {
sway_surface->view->surface = xsurface->surface;
// put it back into the tree
- if (xsurface->override_redirect) {
+ if (wlr_xwayland_surface_is_unmanaged(xsurface) ||
+ xsurface->override_redirect) {
+ wl_list_remove(&sway_surface->view->unmanaged_view_link);
wl_list_insert(&root_container.sway_root->unmanaged_views,
&sway_surface->view->unmanaged_view_link);
} else {
@@ -209,6 +206,8 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
sway_view->surface = xsurface->surface;
sway_surface->view = sway_view;
+ wl_list_init(&sway_view->unmanaged_view_link);
+
// TODO:
// - Look up pid and open on appropriate workspace
// - Set new view to maximized so it behaves nicely
@@ -230,18 +229,5 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
wl_signal_add(&xsurface->events.map_notify, &sway_surface->map_notify);
sway_surface->map_notify.notify = handle_map_notify;
- if (wlr_xwayland_surface_is_unmanaged(xsurface)) {
- // these don't get a container in the tree
- wl_list_insert(&root_container.sway_root->unmanaged_views,
- &sway_view->unmanaged_view_link);
- return;
- }
-
- struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container);
- struct sway_container *cont = container_view_create(focus, sway_view);
- sway_view->swayc = cont;
-
- arrange_windows(cont->parent, -1, -1);
- sway_input_manager_set_focus(input_manager, cont);
+ handle_map_notify(&sway_surface->map_notify, xsurface);
}
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 @@
#include "sway/input/keyboard.h"
#include "sway/ipc-server.h"
#include "sway/output.h"
+#include "sway/tree/container.h"
#include "sway/tree/view.h"
#include "log.h"
@@ -331,6 +332,9 @@ void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *containe
if (last_ws) {
wlr_log(L_DEBUG, "sending workspace event");
ipc_event_workspace(last_ws, container, "focus");
+ if (last_ws->children->length == 0) {
+ container_workspace_destroy(last_ws);
+ }
}
}
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 @@
#define _POSIX_C_SOURCE 200112L
-#include <stdlib.h>
+#include <assert.h>
#include <stdbool.h>
+#include <stdlib.h>
#include <wayland-server.h>
#include <wlr/backend.h>
#include <wlr/backend/session.h>
#include <wlr/render/wlr_renderer.h>
-#include <wlr/render/gles2.h>
#include <wlr/types/wlr_compositor.h>
+#include <wlr/types/wlr_gamma_control.h>
#include <wlr/types/wlr_layer_shell.h>
#include <wlr/types/wlr_screenshooter.h>
-#include <wlr/types/wlr_gamma_control.h>
#include <wlr/types/wlr_wl_shell.h>
+#include <wlr/util/log.h>
// TODO WLR: make Xwayland optional
#include <wlr/xwayland.h>
-#include <wlr/util/log.h>
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/server.h"
@@ -42,11 +42,12 @@ bool server_init(struct sway_server *server) {
server->wl_event_loop = wl_display_get_event_loop(server->wl_display);
server->backend = wlr_backend_autocreate(server->wl_display);
- server->renderer = wlr_gles2_renderer_create(server->backend);
+ struct wlr_renderer *renderer = wlr_backend_get_renderer(server->backend);
+ assert(renderer);
+
wl_display_init_shm(server->wl_display);
- server->compositor = wlr_compositor_create(
- server->wl_display, server->renderer);
+ server->compositor = wlr_compositor_create(server->wl_display, renderer);
server->data_device_manager =
wlr_data_device_manager_create(server->wl_display);
@@ -95,8 +96,7 @@ bool server_init(struct sway_server *server) {
}
void server_fini(struct sway_server *server) {
- // TODO WLR: tear down more stuff
- wlr_backend_destroy(server->backend);
+ // TODO
}
void 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) {
return c;
}
-static void container_destroy(struct sway_container *cont) {
+void container_destroy(struct sway_container *cont) {
if (cont == NULL) {
return;
}
@@ -203,8 +203,7 @@ struct sway_container *container_view_create(struct sway_container *sibling,
}
struct sway_container *container_output_destroy(struct sway_container *output) {
- if (!sway_assert(output,
- "null output passed to container_output_destroy")) {
+ if (!sway_assert(output, "cannot destroy null output")) {
return NULL;
}
@@ -236,6 +235,45 @@ struct sway_container *container_output_destroy(struct sway_container *output) {
return &root_container;
}
+struct sway_container *container_workspace_destroy(
+ struct sway_container *workspace) {
+ if (!sway_assert(workspace, "cannot destroy null workspace")) {
+ return NULL;
+ }
+
+ // Do not destroy this if it's the last workspace on this output
+ struct sway_container *output = container_parent(workspace, C_OUTPUT);
+ if (output && output->children->length == 1) {
+ return NULL;
+ }
+
+ struct sway_container *parent = workspace->parent;
+ if (workspace->children->length == 0) {
+ // destroy the WS if there are no children (TODO check for floating)
+ wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name);
+ ipc_event_workspace(workspace, NULL, "empty");
+ } else {
+ // Move children to a different workspace on this output
+ struct sway_container *new_workspace = NULL;
+ // TODO move floating
+ for (int i = 0; i < output->children->length; i++) {
+ if (output->children->items[i] != workspace) {
+ new_workspace = output->children->items[i];
+ break;
+ }
+ }
+
+ wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'",
+ workspace->name, new_workspace->name);
+ for (int i = 0; i < workspace->children->length; i++) {
+ container_move_to(workspace->children->items[i], new_workspace);
+ }
+ }
+
+ container_destroy(workspace);
+ return parent;
+}
+
struct sway_container *container_view_destroy(struct sway_container *view) {
if (!view) {
return NULL;
@@ -438,3 +476,14 @@ void container_for_each_descendant_bfs(struct sway_container *con,
list_cat(queue, current->children);
}
}
+
+bool container_has_anscestor(struct sway_container *descendant,
+ struct sway_container *anscestor) {
+ while (descendant->type != C_ROOT) {
+ descendant = descendant->parent;
+ if (descendant == anscestor) {
+ return true;
+ }
+ }
+ return false;
+}
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 @@
#include "sway/output.h"
#include "sway/tree/view.h"
#include "sway/input/seat.h"
+#include "sway/ipc-server.h"
#include "list.h"
#include "log.h"
@@ -121,6 +122,42 @@ struct sway_container *container_remove_child(struct sway_container *child) {
return parent;
}
+struct sway_container *container_reap_empty(struct sway_container *container) {
+ if (!sway_assert(container, "reaping null container")) {
+ return NULL;
+ }
+ while (container->children->length == 0 && container->type == C_CONTAINER) {
+ wlr_log(L_DEBUG, "Container: Destroying container '%p'", container);
+ struct sway_container *parent = container->parent;
+ container_destroy(container);
+ container = parent;
+ }
+ return container;
+}
+
+void container_move_to(struct sway_container* container,
+ struct sway_container* destination) {
+ if (container == destination
+ || container_has_anscestor(container, destination)) {
+ return;
+ }
+ struct sway_container *old_parent = container_remove_child(container);
+ container->width = container->height = 0;
+ struct sway_container *new_parent =
+ container_add_sibling(destination, container);
+ if (destination->type == C_WORKSPACE) {
+ // If the workspace only has one child after adding one, it
+ // means that the workspace was just initialized.
+ // TODO: Consider floating views in this test
+ if (destination->children->length == 1) {
+ ipc_event_workspace(NULL, destination, "init");
+ }
+ }
+ old_parent = container_reap_empty(old_parent);
+ arrange_windows(old_parent, -1, -1);
+ arrange_windows(new_parent, -1, -1);
+}
+
enum sway_container_layout container_get_default_layout(
struct sway_container *output) {
if (config->default_layout != L_NONE) {