diff options
-rw-r--r-- | include/sway/server.h | 1 | ||||
-rw-r--r-- | include/sway/tree/container.h | 8 | ||||
-rw-r--r-- | include/sway/tree/layout.h | 3 | ||||
-rw-r--r-- | sway/desktop/output.c | 25 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 36 | ||||
-rw-r--r-- | sway/input/seat.c | 4 | ||||
-rw-r--r-- | sway/server.c | 18 | ||||
-rw-r--r-- | sway/tree/container.c | 55 | ||||
-rw-r--r-- | sway/tree/layout.c | 37 |
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) { |