diff options
Diffstat (limited to 'sway/desktop')
-rw-r--r-- | sway/desktop/desktop.c | 31 | ||||
-rw-r--r-- | sway/desktop/layer_shell.c | 23 | ||||
-rw-r--r-- | sway/desktop/output.c | 182 | ||||
-rw-r--r-- | sway/desktop/render.c | 259 | ||||
-rw-r--r-- | sway/desktop/transaction.c | 374 | ||||
-rw-r--r-- | sway/desktop/xdg_shell.c | 47 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 44 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 50 |
8 files changed, 547 insertions, 463 deletions
diff --git a/sway/desktop/desktop.c b/sway/desktop/desktop.c index 72650397..771b58fe 100644 --- a/sway/desktop/desktop.c +++ b/sway/desktop/desktop.c @@ -4,37 +4,32 @@ void desktop_damage_surface(struct wlr_surface *surface, double lx, double ly, bool whole) { - for (int i = 0; i < root_container.children->length; ++i) { - struct sway_container *cont = root_container.children->items[i]; - if (cont->type == C_OUTPUT) { - output_damage_surface(cont->sway_output, - lx - cont->current.swayc_x, ly - cont->current.swayc_y, - surface, whole); - } + for (int i = 0; i < root->outputs->length; ++i) { + struct sway_output *output = root->outputs->items[i]; + output_damage_surface(output, lx - output->wlr_output->lx, + ly - output->wlr_output->ly, surface, whole); } } void desktop_damage_whole_container(struct sway_container *con) { - for (int i = 0; i < root_container.children->length; ++i) { - struct sway_container *cont = root_container.children->items[i]; - if (cont->type == C_OUTPUT) { - output_damage_whole_container(cont->sway_output, con); - } + for (int i = 0; i < root->outputs->length; ++i) { + struct sway_output *output = root->outputs->items[i]; + output_damage_whole_container(output, con); } } void desktop_damage_box(struct wlr_box *box) { - for (int i = 0; i < root_container.children->length; ++i) { - struct sway_container *cont = root_container.children->items[i]; - output_damage_box(cont->sway_output, box); + for (int i = 0; i < root->outputs->length; ++i) { + struct sway_output *output = root->outputs->items[i]; + output_damage_box(output, box); } } void desktop_damage_view(struct sway_view *view) { - desktop_damage_whole_container(view->swayc); + desktop_damage_whole_container(view->container); struct wlr_box box = { - .x = view->swayc->current.view_x - view->geometry.x, - .y = view->swayc->current.view_y - view->geometry.y, + .x = view->container->current.view_x - view->geometry.x, + .y = view->container->current.view_y - view->geometry.y, .width = view->surface->current.width, .height = view->surface->current.height, }; diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index a4f7f928..7d254173 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -14,6 +14,7 @@ #include "sway/output.h" #include "sway/server.h" #include "sway/tree/arrange.h" +#include "sway/tree/workspace.h" #include "log.h" static void apply_exclusive(struct wlr_box *usable_area, @@ -176,7 +177,7 @@ void arrange_layers(struct sway_output *output) { sizeof(struct wlr_box)) != 0) { wlr_log(WLR_DEBUG, "Usable area changed, rearranging output"); memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); - arrange_output(output->swayc); + arrange_output(output); } // Arrange non-exlusive surfaces from top->bottom @@ -256,7 +257,7 @@ static void unmap(struct sway_layer_surface *sway_layer) { return; } struct sway_output *output = wlr_output->data; - if (output == NULL || output->swayc == NULL) { + if (output == NULL) { return; } output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y, @@ -283,9 +284,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&sway_layer->surface_commit.link); if (sway_layer->layer_surface->output != NULL) { struct sway_output *output = sway_layer->layer_surface->output->data; - if (output != NULL && output->swayc != NULL) { + if (output != NULL) { arrange_layers(output); - arrange_windows(output->swayc); + arrange_output(output); transaction_commit_dirty(); } wl_list_remove(&sway_layer->output_destroy.link); @@ -332,23 +333,21 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { if (!layer_surface->output) { // Assign last active output - struct sway_container *output = NULL; + struct sway_output *output = NULL; struct sway_seat *seat = input_manager_get_default_seat(input_manager); if (seat) { - output = seat_get_focus_inactive(seat, &root_container); + struct sway_workspace *ws = seat_get_focused_workspace(seat); + output = ws->output; } if (!output) { - if (!sway_assert(root_container.children->length, + if (!sway_assert(root->outputs->length, "cannot auto-assign output for layer")) { wlr_layer_surface_close(layer_surface); return; } - output = root_container.children->items[0]; + output = root->outputs->items[0]; } - if (output->type != C_OUTPUT) { - output = container_parent(output, C_OUTPUT); - } - layer_surface->output = output->sway_output->wlr_output; + layer_surface->output = output->wlr_output; } struct sway_layer_surface *sway_layer = diff --git a/sway/desktop/output.c b/sway/desktop/output.c index c30e52a1..c182bad6 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -28,10 +28,10 @@ #include "sway/tree/view.h" #include "sway/tree/workspace.h" -struct sway_container *output_by_name(const char *name) { - for (int i = 0; i < root_container.children->length; ++i) { - struct sway_container *output = root_container.children->items[i]; - if (strcasecmp(output->name, name) == 0) { +struct sway_output *output_by_name(const char *name) { + for (int i = 0; i < root->outputs->length; ++i) { + struct sway_output *output = root->outputs->items[i]; + if (strcasecmp(output->wlr_output->name, name) == 0) { return output; } } @@ -98,8 +98,8 @@ static bool get_surface_box(struct surface_iterator_data *data, wlr_box_rotated_bounds(&box, data->rotation, &rotated_box); struct wlr_box output_box = { - .width = output->swayc->current.swayc_width, - .height = output->swayc->current.swayc_height, + .width = output->wlr_output->width, + .height = output->wlr_output->height, }; struct wlr_box intersection; @@ -145,12 +145,12 @@ void output_view_for_each_surface(struct sway_output *output, .user_iterator = iterator, .user_data = user_data, .output = output, - .ox = view->swayc->current.view_x - output->swayc->current.swayc_x + .ox = view->container->current.view_x - output->wlr_output->lx - view->geometry.x, - .oy = view->swayc->current.view_y - output->swayc->current.swayc_y + .oy = view->container->current.view_y - output->wlr_output->ly - view->geometry.y, - .width = view->swayc->current.view_width, - .height = view->swayc->current.view_height, + .width = view->container->current.view_width, + .height = view->container->current.view_height, .rotation = 0, // TODO }; @@ -164,12 +164,12 @@ void output_view_for_each_popup(struct sway_output *output, .user_iterator = iterator, .user_data = user_data, .output = output, - .ox = view->swayc->current.view_x - output->swayc->current.swayc_x + .ox = view->container->current.view_x - output->wlr_output->lx - view->geometry.x, - .oy = view->swayc->current.view_y - output->swayc->current.swayc_y + .oy = view->container->current.view_y - output->wlr_output->ly - view->geometry.y, - .width = view->swayc->current.view_width, - .height = view->swayc->current.view_height, + .width = view->container->current.view_width, + .height = view->container->current.view_height, .rotation = 0, // TODO }; @@ -197,8 +197,8 @@ void output_unmanaged_for_each_surface(struct sway_output *output, wl_list_for_each(unmanaged_surface, unmanaged, link) { struct wlr_xwayland_surface *xsurface = unmanaged_surface->wlr_xwayland_surface; - double ox = unmanaged_surface->lx - output->swayc->current.swayc_x; - double oy = unmanaged_surface->ly - output->swayc->current.swayc_y; + double ox = unmanaged_surface->lx - output->wlr_output->lx; + double oy = unmanaged_surface->ly - output->wlr_output->ly; output_surface_for_each_surface(output, xsurface->surface, ox, oy, iterator, user_data); @@ -211,8 +211,8 @@ void output_drag_icons_for_each_surface(struct sway_output *output, void *user_data) { struct sway_drag_icon *drag_icon; wl_list_for_each(drag_icon, drag_icons, link) { - double ox = drag_icon->x - output->swayc->x; - double oy = drag_icon->y - output->swayc->y; + double ox = drag_icon->x - output->wlr_output->lx; + double oy = drag_icon->y - output->wlr_output->ly; if (drag_icon->wlr_drag_icon->mapped) { output_surface_for_each_surface(output, @@ -229,19 +229,13 @@ static void scale_box(struct wlr_box *box, float scale) { box->height *= scale; } -struct sway_container *output_get_active_workspace(struct sway_output *output) { +struct sway_workspace *output_get_active_workspace(struct sway_output *output) { struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = - seat_get_focus_inactive(seat, output->swayc); + struct sway_node *focus = seat_get_active_child(seat, &output->node); if (!focus) { - // We've never been to this output before - focus = output->swayc->current.children->items[0]; + return output->workspaces->items[0]; } - struct sway_container *workspace = focus; - if (workspace->type != C_WORKSPACE) { - workspace = container_parent(workspace, C_WORKSPACE); - } - return workspace; + return focus->sway_workspace; } bool output_has_opaque_overlay_layer_surface(struct sway_output *output) { @@ -255,8 +249,8 @@ bool output_has_opaque_overlay_layer_surface(struct sway_output *output) { struct sway_layer_surface *sway_layer_surface = layer_from_wlr_layer_surface(wlr_layer_surface); pixman_box32_t output_box = { - .x2 = output->swayc->current.swayc_width, - .y2 = output->swayc->current.swayc_height, + .x2 = output->wlr_output->width, + .y2 = output->wlr_output->height, }; pixman_region32_t surface_opaque_box; pixman_region32_init(&surface_opaque_box); @@ -307,15 +301,15 @@ struct send_frame_done_data { static void send_frame_done_container_iterator(struct sway_container *con, void *_data) { - if (con->type != C_VIEW) { + if (!con->view) { return; } - if (!view_is_visible(con->sway_view)) { + if (!view_is_visible(con->view)) { return; } struct send_frame_done_data *data = _data; - output_view_for_each_surface(data->output, con->sway_view, + output_view_for_each_surface(data->output, con->view, send_frame_done_iterator, data->when); } @@ -328,15 +322,14 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { .output = output, .when = when, }; - struct sway_container *workspace = output_get_active_workspace(output); - if (workspace->current.ws_fullscreen) { + struct sway_workspace *workspace = output_get_active_workspace(output); + if (workspace->current.fullscreen) { send_frame_done_container_iterator( - workspace->current.ws_fullscreen, &data); - container_for_each_child(workspace->current.ws_fullscreen, + workspace->current.fullscreen, &data); + container_for_each_child(workspace->current.fullscreen, send_frame_done_container_iterator, &data); #ifdef HAVE_XWAYLAND - send_frame_done_unmanaged(output, - &root_container.sway_root->xwayland_unmanaged, when); + send_frame_done_unmanaged(output, &root->xwayland_unmanaged, when); #endif } else { send_frame_done_layer(output, @@ -348,8 +341,7 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { send_frame_done_container_iterator, &data); #ifdef HAVE_XWAYLAND - send_frame_done_unmanaged(output, - &root_container.sway_root->xwayland_unmanaged, when); + send_frame_done_unmanaged(output, &root->xwayland_unmanaged, when); #endif send_frame_done_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when); @@ -358,8 +350,7 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { send_frame_overlay: send_frame_done_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when); - send_frame_done_drag_icons(output, &root_container.sway_root->drag_icons, - when); + send_frame_done_drag_icons(output, &root->drag_icons, when); } static void damage_handle_frame(struct wl_listener *listener, void *data) { @@ -391,7 +382,11 @@ static void damage_handle_frame(struct wl_listener *listener, void *data) { } void output_damage_whole(struct sway_output *output) { - wlr_output_damage_add_whole(output->damage); + // The output can exist with no wlr_output if it's just been disconnected + // and the transaction to evacuate it has't completed yet. + if (output && output->wlr_output) { + wlr_output_damage_add_whole(output->damage); + } } static void damage_surface_iterator(struct sway_output *output, @@ -446,14 +441,9 @@ void output_damage_surface(struct sway_output *output, double ox, double oy, static void output_damage_view(struct sway_output *output, struct sway_view *view, bool whole) { - if (!sway_assert(view->swayc != NULL, "expected a view in the tree")) { - return; - } - if (!view_is_visible(view)) { return; } - output_view_for_each_surface(output, view, damage_surface_iterator, &whole); } @@ -466,31 +456,29 @@ void output_damage_from_view(struct sway_output *output, void output_damage_box(struct sway_output *output, struct wlr_box *_box) { struct wlr_box box; memcpy(&box, _box, sizeof(struct wlr_box)); - box.x -= output->swayc->current.swayc_x; - box.y -= output->swayc->current.swayc_y; + box.x -= output->wlr_output->lx; + box.y -= output->wlr_output->ly; scale_box(&box, output->wlr_output->scale); wlr_output_damage_add_box(output->damage, &box); } static void output_damage_whole_container_iterator(struct sway_container *con, void *data) { - struct sway_output *output = data; - - if (!sway_assert(con->type == C_VIEW, "expected a view")) { + if (!sway_assert(con->view, "expected a view")) { return; } - - output_damage_view(output, con->sway_view, true); + struct sway_output *output = data; + output_damage_view(output, con->view, true); } void output_damage_whole_container(struct sway_output *output, struct sway_container *con) { // Pad the box by 1px, because the width is a double and might be a fraction struct wlr_box box = { - .x = con->current.swayc_x - output->wlr_output->lx - 1, - .y = con->current.swayc_y - output->wlr_output->ly - 1, - .width = con->current.swayc_width + 2, - .height = con->current.swayc_height + 2, + .x = con->current.con_x - output->wlr_output->lx - 1, + .y = con->current.con_y - output->wlr_output->ly - 1, + .width = con->current.con_width + 2, + .height = con->current.con_height + 2, }; scale_box(&box, output->wlr_output->scale); wlr_output_damage_add_box(output->damage, &box); @@ -499,44 +487,48 @@ void output_damage_whole_container(struct sway_output *output, static void damage_handle_destroy(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, damage_destroy); - output_begin_destroy(output->swayc); + output_disable(output); + transaction_commit_dirty(); } static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, destroy); wl_signal_emit(&output->events.destroy, output); - if (output->swayc) { - output_begin_destroy(output->swayc); + if (output->enabled) { + output_disable(output); } + output_begin_destroy(output); - wl_list_remove(&output->link); - wl_list_remove(&output->destroy.link); - output->wlr_output->data = NULL; - free(output); - - arrange_windows(&root_container); + transaction_commit_dirty(); } static void handle_mode(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, mode); arrange_layers(output); - arrange_windows(output->swayc); + arrange_output(output); transaction_commit_dirty(); } static void handle_transform(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, transform); arrange_layers(output); - arrange_windows(output->swayc); + arrange_output(output); transaction_commit_dirty(); } +static void update_textures(struct sway_container *con, void *data) { + container_update_title_textures(con); + if (con->view) { + view_update_marks_textures(con->view); + } +} + static void handle_scale(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, scale); arrange_layers(output); - container_update_textures_recursive(output->swayc); - arrange_windows(output->swayc); + output_for_each_container(output, update_textures, NULL); + arrange_output(output); transaction_commit_dirty(); } @@ -545,57 +537,27 @@ void handle_new_output(struct wl_listener *listener, void *data) { struct wlr_output *wlr_output = data; wlr_log(WLR_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); - struct sway_output *output = calloc(1, sizeof(struct sway_output)); + struct sway_output *output = output_create(wlr_output); if (!output) { return; } - output->wlr_output = wlr_output; - wlr_output->data = output; output->server = server; output->damage = wlr_output_damage_create(wlr_output); - - wl_signal_add(&wlr_output->events.destroy, &output->destroy); output->destroy.notify = handle_destroy; - wl_list_insert(&root_container.sway_root->all_outputs, &output->link); - - output_enable(output); -} - -void output_enable(struct sway_output *output) { - struct wlr_output *wlr_output = output->wlr_output; - - if (!sway_assert(output->swayc == NULL, "output is already enabled")) { - return; - } - - output->swayc = output_create(output); - if (!output->swayc) { - // Output is disabled - return; - } + struct output_config *oc = output_find_config(output); - size_t len = sizeof(output->layers) / sizeof(output->layers[0]); - for (size_t i = 0; i < len; ++i) { - wl_list_init(&output->layers[i]); + if (oc && oc->enabled) { + output_enable(output, oc); } - wl_signal_init(&output->events.destroy); - input_manager_configure_xcursor(input_manager); + transaction_commit_dirty(); +} - wl_signal_add(&wlr_output->events.mode, &output->mode); +void output_add_listeners(struct sway_output *output) { output->mode.notify = handle_mode; - wl_signal_add(&wlr_output->events.transform, &output->transform); output->transform.notify = handle_transform; - wl_signal_add(&wlr_output->events.scale, &output->scale); output->scale.notify = handle_scale; - - wl_signal_add(&output->damage->events.frame, &output->damage_frame); output->damage_frame.notify = damage_handle_frame; - wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); output->damage_destroy.notify = damage_handle_destroy; - - arrange_layers(output); - arrange_windows(&root_container); - transaction_commit_dirty(); } diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 695213eb..99b2cf3d 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -193,10 +193,10 @@ static void render_view_toplevels(struct sway_view *view, .alpha = alpha, }; // Render all toplevels without descending into popups - double ox = - view->swayc->current.view_x - output->wlr_output->lx - view->geometry.x; - double oy = - view->swayc->current.view_y - output->wlr_output->ly - view->geometry.y; + double ox = view->container->current.view_x - + output->wlr_output->lx - view->geometry.x; + double oy = view->container->current.view_y - + output->wlr_output->ly - view->geometry.y; output_surface_for_each_surface(output, view->surface, ox, oy, render_surface_iterator, &data); } @@ -229,17 +229,17 @@ static void render_saved_view(struct sway_view *view, return; } struct wlr_box box = { - .x = view->swayc->current.view_x - output->swayc->current.swayc_x - + .x = view->container->current.view_x - output->wlr_output->lx - view->saved_geometry.x, - .y = view->swayc->current.view_y - output->swayc->current.swayc_y - + .y = view->container->current.view_y - output->wlr_output->ly - view->saved_geometry.y, .width = view->saved_buffer_width, .height = view->saved_buffer_height, }; struct wlr_box output_box = { - .width = output->swayc->current.swayc_width, - .height = output->swayc->current.swayc_height, + .width = output->wlr_output->width, + .height = output->wlr_output->height, }; struct wlr_box intersection; @@ -263,14 +263,14 @@ static void render_saved_view(struct sway_view *view, */ static void render_view(struct sway_output *output, pixman_region32_t *damage, struct sway_container *con, struct border_colors *colors) { - struct sway_view *view = con->sway_view; + struct sway_view *view = con->view; if (view->saved_buffer) { - render_saved_view(view, output, damage, view->swayc->alpha); + render_saved_view(view, output, damage, view->container->alpha); } else { - render_view_toplevels(view, output, damage, view->swayc->alpha); + render_view_toplevels(view, output, damage, view->container->alpha); } - if (view->swayc->current.using_csd) { + if (view->container->current.using_csd) { return; } @@ -283,7 +283,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, if (state->border_left) { memcpy(&color, colors->child_border, sizeof(float) * 4); premultiply_alpha(color, con->alpha); - box.x = state->swayc_x; + box.x = state->con_x; box.y = state->view_y; box.width = state->border_thickness; box.height = state->view_height; @@ -291,9 +291,12 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, render_rect(output->wlr_output, damage, &box, color); } + list_t *siblings = container_get_current_siblings(con); + enum sway_container_layout layout = + container_current_parent_layout(con); + if (state->border_right) { - if (state->parent->current.children->length == 1 - && state->parent->current.layout == L_HORIZ) { + if (siblings->length == 1 && layout == L_HORIZ) { memcpy(&color, colors->indicator, sizeof(float) * 4); } else { memcpy(&color, colors->child_border, sizeof(float) * 4); @@ -308,16 +311,15 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, } if (state->border_bottom) { - if (state->parent->current.children->length == 1 - && con->current.parent->current.layout == L_VERT) { + if (siblings->length == 1 && layout == L_VERT) { memcpy(&color, colors->indicator, sizeof(float) * 4); } else { memcpy(&color, colors->child_border, sizeof(float) * 4); } premultiply_alpha(color, con->alpha); - box.x = state->swayc_x; + box.x = state->con_x; box.y = state->view_y + state->view_height; - box.width = state->swayc_width; + box.width = state->con_width; box.height = state->border_thickness; scale_box(&box, output_scale); render_rect(output->wlr_output, damage, &box, color); @@ -344,12 +346,12 @@ static void render_titlebar(struct sway_output *output, float color[4]; struct sway_container_state *state = &con->current; float output_scale = output->wlr_output->scale; - enum sway_container_layout layout = state->parent->current.layout; - list_t *children = state->parent->current.children; + enum sway_container_layout layout = container_current_parent_layout(con); + list_t *children = container_get_current_siblings(con); bool is_last_child = children->length == 0 || children->items[children->length - 1] == con; - double output_x = output->swayc->current.swayc_x; - double output_y = output->swayc->current.swayc_y; + double output_x = output->wlr_output->lx; + double output_y = output->wlr_output->ly; // Single pixel bar above title memcpy(&color, colors->border, sizeof(float) * 4); @@ -366,7 +368,7 @@ static void render_titlebar(struct sway_output *output, bool connects_sides = false; if (layout == L_HORIZ || layout == L_VERT || (layout == L_STACKED && is_last_child)) { - if (con->type == C_VIEW) { + if (con->view) { left_offset = state->border_left * state->border_thickness; right_offset = state->border_right * state->border_thickness; connects_sides = true; @@ -542,14 +544,22 @@ static void render_top_border(struct sway_output *output, // Child border - top edge memcpy(&color, colors->child_border, sizeof(float) * 4); premultiply_alpha(color, con->alpha); - box.x = state->swayc_x; - box.y = state->swayc_y; - box.width = state->swayc_width; + box.x = state->con_x; + box.y = state->con_y; + box.width = state->con_width; box.height = state->border_thickness; scale_box(&box, output_scale); render_rect(output->wlr_output, output_damage, &box, color); } +struct parent_data { + enum sway_container_layout layout; + struct wlr_box box; + list_t *children; + bool focused; + struct sway_container *active_child; +}; + static void render_container(struct sway_output *output, pixman_region32_t *damage, struct sway_container *con, bool parent_focused); @@ -559,14 +569,13 @@ static void render_container(struct sway_output *output, * Wrap child views in borders and leave child containers borderless because * they'll apply their own borders to their children. */ -static void render_container_simple(struct sway_output *output, - pixman_region32_t *damage, struct sway_container *con, - bool parent_focused) { - for (int i = 0; i < con->current.children->length; ++i) { - struct sway_container *child = con->current.children->items[i]; - - if (child->type == C_VIEW) { - struct sway_view *view = child->sway_view; +static void render_containers_linear(struct sway_output *output, + pixman_region32_t *damage, struct parent_data *parent) { + for (int i = 0; i < parent->children->length; ++i) { + struct sway_container *child = parent->children->items[i]; + + if (child->view) { + struct sway_view *view = child->view; struct border_colors *colors; struct wlr_texture *title_texture; struct wlr_texture *marks_texture; @@ -576,11 +585,11 @@ static void render_container_simple(struct sway_output *output, colors = &config->border_colors.urgent; title_texture = child->title_urgent; marks_texture = view->marks_urgent; - } else if (state->focused || parent_focused) { + } else if (state->focused || parent->focused) { colors = &config->border_colors.focused; title_texture = child->title_focused; marks_texture = view->marks_focused; - } else if (con->current.focused_inactive_child == child) { + } else if (child == parent->active_child) { colors = &config->border_colors.focused_inactive; title_texture = child->title_focused_inactive; marks_texture = view->marks_focused_inactive; @@ -590,10 +599,10 @@ static void render_container_simple(struct sway_output *output, marks_texture = view->marks_unfocused; } - if (!view->swayc->current.using_csd) { + if (!view->container->current.using_csd) { if (state->border == B_NORMAL) { - render_titlebar(output, damage, child, state->swayc_x, - state->swayc_y, state->swayc_width, colors, + render_titlebar(output, damage, child, state->con_x, + state->con_y, state->con_width, colors, title_texture, marks_texture); } else { render_top_border(output, damage, child, colors); @@ -602,7 +611,7 @@ static void render_container_simple(struct sway_output *output, render_view(output, damage, child, colors); } else { render_container(output, damage, child, - parent_focused || child->current.focused); + parent->focused || child->current.focused); } } } @@ -610,22 +619,19 @@ static void render_container_simple(struct sway_output *output, /** * Render a container's children using the L_TABBED layout. */ -static void render_container_tabbed(struct sway_output *output, - pixman_region32_t *damage, struct sway_container *con, - bool parent_focused) { - if (!con->current.children->length) { +static void render_containers_tabbed(struct sway_output *output, + pixman_region32_t *damage, struct parent_data *parent) { + if (!parent->children->length) { return; } - struct sway_container_state *pstate = &con->current; - struct sway_container *current = pstate->focused_inactive_child; + struct sway_container *current = parent->active_child; struct border_colors *current_colors = &config->border_colors.unfocused; - - int tab_width = (pstate->swayc_width) / pstate->children->length; + int tab_width = parent->box.width / parent->children->length; // Render tabs - for (int i = 0; i < pstate->children->length; ++i) { - struct sway_container *child = pstate->children->items[i]; - struct sway_view *view = child->type == C_VIEW ? child->sway_view : NULL; + for (int i = 0; i < parent->children->length; ++i) { + struct sway_container *child = parent->children->items[i]; + struct sway_view *view = child->view; struct sway_container_state *cstate = &child->current; struct border_colors *colors; struct wlr_texture *title_texture; @@ -637,11 +643,11 @@ static void render_container_tabbed(struct sway_output *output, colors = &config->border_colors.urgent; title_texture = child->title_urgent; marks_texture = view ? view->marks_urgent : NULL; - } else if (cstate->focused || parent_focused) { + } else if (cstate->focused || parent->focused) { colors = &config->border_colors.focused; title_texture = child->title_focused; marks_texture = view ? view->marks_focused : NULL; - } else if (child == pstate->focused_inactive_child) { + } else if (child == parent->active_child) { colors = &config->border_colors.focused_inactive; title_texture = child->title_focused_inactive; marks_texture = view ? view->marks_focused_inactive : NULL; @@ -651,14 +657,14 @@ static void render_container_tabbed(struct sway_output *output, marks_texture = view ? view->marks_unfocused : NULL; } - int x = cstate->swayc_x + tab_width * i; + int x = cstate->con_x + tab_width * i; // Make last tab use the remaining width of the parent - if (i == pstate->children->length - 1) { - tab_width = pstate->swayc_width - tab_width * i; + if (i == parent->children->length - 1) { + tab_width = parent->box.width - tab_width * i; } - render_titlebar(output, damage, child, x, pstate->swayc_y, tab_width, + render_titlebar(output, damage, child, x, parent->box.y, tab_width, colors, title_texture, marks_texture); if (child == current) { @@ -667,33 +673,30 @@ static void render_container_tabbed(struct sway_output *output, } // Render surface and left/right/bottom borders - if (current->type == C_VIEW) { + if (current->view) { render_view(output, damage, current, current_colors); } else { render_container(output, damage, current, - parent_focused || current->current.focused); + parent->focused || current->current.focused); } } /** * Render a container's children using the L_STACKED layout. */ -static void render_container_stacked(struct sway_output *output, - pixman_region32_t *damage, struct sway_container *con, - bool parent_focused) { - if (!con->current.children->length) { +static void render_containers_stacked(struct sway_output *output, + pixman_region32_t *damage, struct parent_data *parent) { + if (!parent->children->length) { return; } - struct sway_container_state *pstate = &con->current; - struct sway_container *current = pstate->focused_inactive_child; + struct sway_container *current = parent->active_child; struct border_colors *current_colors = &config->border_colors.unfocused; - size_t titlebar_height = container_titlebar_height(); // Render titles - for (int i = 0; i < pstate->children->length; ++i) { - struct sway_container *child = pstate->children->items[i]; - struct sway_view *view = child->type == C_VIEW ? child->sway_view : NULL; + for (int i = 0; i < parent->children->length; ++i) { + struct sway_container *child = parent->children->items[i]; + struct sway_view *view = child->view; struct sway_container_state *cstate = &child->current; struct border_colors *colors; struct wlr_texture *title_texture; @@ -705,11 +708,11 @@ static void render_container_stacked(struct sway_output *output, colors = &config->border_colors.urgent; title_texture = child->title_urgent; marks_texture = view ? view->marks_urgent : NULL; - } else if (cstate->focused || parent_focused) { + } else if (cstate->focused || parent->focused) { colors = &config->border_colors.focused; title_texture = child->title_focused; marks_texture = view ? view->marks_focused : NULL; - } else if (child == pstate->focused_inactive_child) { + } else if (child == parent->active_child) { colors = &config->border_colors.focused_inactive; title_texture = child->title_focused_inactive; marks_texture = view ? view->marks_focused_inactive : NULL; @@ -719,9 +722,9 @@ static void render_container_stacked(struct sway_output *output, marks_texture = view ? view->marks_unfocused : NULL; } - int y = pstate->swayc_y + titlebar_height * i; - render_titlebar(output, damage, child, pstate->swayc_x, y, - pstate->swayc_width, colors, title_texture, marks_texture); + int y = parent->box.y + titlebar_height * i; + render_titlebar(output, damage, child, parent->box.x, y, + parent->box.width, colors, title_texture, marks_texture); if (child == current) { current_colors = colors; @@ -729,36 +732,69 @@ static void render_container_stacked(struct sway_output *output, } // Render surface and left/right/bottom borders - if (current->type == C_VIEW) { + if (current->view) { render_view(output, damage, current, current_colors); } else { render_container(output, damage, current, - parent_focused || current->current.focused); + parent->focused || current->current.focused); } } -static void render_container(struct sway_output *output, - pixman_region32_t *damage, struct sway_container *con, - bool parent_focused) { - switch (con->current.layout) { +static void render_containers(struct sway_output *output, + pixman_region32_t *damage, struct parent_data *parent) { + switch (parent->layout) { case L_NONE: case L_HORIZ: case L_VERT: - render_container_simple(output, damage, con, parent_focused); + render_containers_linear(output, damage, parent); break; case L_STACKED: - render_container_stacked(output, damage, con, parent_focused); + render_containers_stacked(output, damage, parent); break; case L_TABBED: - render_container_tabbed(output, damage, con, parent_focused); + render_containers_tabbed(output, damage, parent); break; } } +static void render_container(struct sway_output *output, + pixman_region32_t *damage, struct sway_container *con, bool focused) { + struct parent_data data = { + .layout = con->current.layout, + .box = { + .x = con->current.con_x, + .y = con->current.con_y, + .width = con->current.con_width, + .height = con->current.con_height, + }, + .children = con->current.children, + .focused = focused, + .active_child = con->current.focused_inactive_child, + }; + render_containers(output, damage, &data); +} + +static void render_workspace(struct sway_output *output, + pixman_region32_t *damage, struct sway_workspace *ws, bool focused) { + struct parent_data data = { + .layout = ws->current.layout, + .box = { + .x = ws->current.x, + .y = ws->current.y, + .width = ws->current.width, + .height = ws->current.height, + }, + .children = ws->current.tiling, + .focused = focused, + .active_child = ws->current.focused_inactive_child, + }; + render_containers(output, damage, &data); +} + static void render_floating_container(struct sway_output *soutput, pixman_region32_t *damage, struct sway_container *con) { - if (con->type == C_VIEW) { - struct sway_view *view = con->sway_view; + if (con->view) { + struct sway_view *view = con->view; struct border_colors *colors; struct wlr_texture *title_texture; struct wlr_texture *marks_texture; @@ -777,10 +813,10 @@ static void render_floating_container(struct sway_output *soutput, marks_texture = view->marks_unfocused; } - if (!view->swayc->current.using_csd) { + if (!view->container->current.using_csd) { if (con->current.border == B_NORMAL) { - render_titlebar(soutput, damage, con, con->current.swayc_x, - con->current.swayc_y, con->current.swayc_width, colors, + render_titlebar(soutput, damage, con, con->current.con_x, + con->current.con_y, con->current.con_width, colors, title_texture, marks_texture); } else if (con->current.border != B_NONE) { render_top_border(soutput, damage, con, colors); @@ -794,17 +830,15 @@ static void render_floating_container(struct sway_output *soutput, static void render_floating(struct sway_output *soutput, pixman_region32_t *damage) { - for (int i = 0; i < root_container.current.children->length; ++i) { - struct sway_container *output = - root_container.current.children->items[i]; - for (int j = 0; j < output->current.children->length; ++j) { - struct sway_container *ws = output->current.children->items[j]; + for (int i = 0; i < root->outputs->length; ++i) { + struct sway_output *output = root->outputs->items[i]; + for (int j = 0; j < output->current.workspaces->length; ++j) { + struct sway_workspace *ws = output->current.workspaces->items[j]; if (!workspace_is_visible(ws)) { continue; } - list_t *floating = ws->current.ws_floating; - for (int k = 0; k < floating->length; ++k) { - struct sway_container *floater = floating->items[k]; + for (int k = 0; k < ws->current.floating->length; ++k) { + struct sway_container *floater = ws->current.floating->items[k]; render_floating_container(soutput, damage, floater); } } @@ -837,8 +871,8 @@ void output_render(struct sway_output *output, struct timespec *when, pixman_region32_union_rect(damage, damage, 0, 0, width, height); } - struct sway_container *workspace = output_get_active_workspace(output); - struct sway_container *fullscreen_con = workspace->current.ws_fullscreen; + struct sway_workspace *workspace = output_get_active_workspace(output); + struct sway_container *fullscreen_con = workspace->current.fullscreen; if (output_has_opaque_overlay_layer_surface(output)) { goto render_overlay; @@ -855,12 +889,11 @@ void output_render(struct sway_output *output, struct timespec *when, } // TODO: handle views smaller than the output - if (fullscreen_con->type == C_VIEW) { - if (fullscreen_con->sway_view->saved_buffer) { - render_saved_view(fullscreen_con->sway_view, - output, damage, 1.0f); + if (fullscreen_con->view) { + if (fullscreen_con->view->saved_buffer) { + render_saved_view(fullscreen_con->view, output, damage, 1.0f); } else { - render_view_toplevels(fullscreen_con->sway_view, + render_view_toplevels(fullscreen_con->view, output, damage, 1.0f); } } else { @@ -868,8 +901,7 @@ void output_render(struct sway_output *output, struct timespec *when, fullscreen_con->current.focused); } #ifdef HAVE_XWAYLAND - render_unmanaged(output, damage, - &root_container.sway_root->xwayland_unmanaged); + render_unmanaged(output, damage, &root->xwayland_unmanaged); #endif } else { float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; @@ -886,31 +918,30 @@ void output_render(struct sway_output *output, struct timespec *when, render_layer(output, damage, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); - render_container(output, damage, workspace, workspace->current.focused); + render_workspace(output, damage, workspace, workspace->current.focused); render_floating(output, damage); #ifdef HAVE_XWAYLAND - render_unmanaged(output, damage, - &root_container.sway_root->xwayland_unmanaged); + render_unmanaged(output, damage, &root->xwayland_unmanaged); #endif render_layer(output, damage, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); } struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = seat_get_focus(seat); - if (focus && focus->type == C_VIEW) { - render_view_popups(focus->sway_view, output, damage, focus->alpha); + struct sway_container *focus = seat_get_focused_container(seat); + if (focus && focus->view) { + render_view_popups(focus->view, output, damage, focus->alpha); } render_overlay: render_layer(output, damage, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); - render_drag_icons(output, damage, &root_container.sway_root->drag_icons); + render_drag_icons(output, damage, &root->drag_icons); renderer_end: if (debug.render_tree) { wlr_renderer_scissor(renderer, NULL); - wlr_render_texture(renderer, root_container.sway_root->debug_tree, + wlr_render_texture(renderer, root->debug_tree, wlr_output->transform_matrix, 0, 40, 1); } if (debug.damage == DAMAGE_HIGHLIGHT) { diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 145c5f92..b4eec933 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -12,6 +12,7 @@ #include "sway/desktop/transaction.h" #include "sway/output.h" #include "sway/tree/container.h" +#include "sway/tree/node.h" #include "sway/tree/view.h" #include "sway/tree/workspace.h" #include "list.h" @@ -27,8 +28,12 @@ struct sway_transaction { struct sway_transaction_instruction { struct sway_transaction *transaction; - struct sway_container *container; - struct sway_container_state state; + struct sway_node *node; + union { + struct sway_output_state *output_state; + struct sway_workspace_state *workspace_state; + struct sway_container_state *container_state; + }; uint32_t serial; }; @@ -47,26 +52,24 @@ static void transaction_destroy(struct sway_transaction *transaction) { for (int i = 0; i < transaction->instructions->length; ++i) { struct sway_transaction_instruction *instruction = transaction->instructions->items[i]; - struct sway_container *con = instruction->container; - con->ntxnrefs--; - if (con->instruction == instruction) { - con->instruction = NULL; + struct sway_node *node = instruction->node; + node->ntxnrefs--; + if (node->instruction == instruction) { + node->instruction = NULL; } - if (con->destroying && con->ntxnrefs == 0) { - switch (con->type) { - case C_ROOT: + if (node->destroying && node->ntxnrefs == 0) { + switch (node->type) { + case N_ROOT: + sway_assert(false, "Never reached"); break; - case C_OUTPUT: - output_destroy(con); + case N_OUTPUT: + output_destroy(node->sway_output); break; - case C_WORKSPACE: - workspace_destroy(con); + case N_WORKSPACE: + workspace_destroy(node->sway_workspace); break; - case C_CONTAINER: - case C_VIEW: - container_destroy(con); - break; - case C_TYPES: + case N_CONTAINER: + container_destroy(node->sway_container); break; } } @@ -80,22 +83,79 @@ static void transaction_destroy(struct sway_transaction *transaction) { free(transaction); } -static void copy_pending_state(struct sway_container *container, - struct sway_container_state *state) { +static void copy_output_state(struct sway_output *output, + struct sway_transaction_instruction *instruction) { + struct sway_output_state *state = + calloc(1, sizeof(struct sway_output_state)); + if (!state) { + wlr_log(WLR_ERROR, "Could not allocate output state"); + return; + } + instruction->output_state = state; + + state->workspaces = create_list(); + list_cat(state->workspaces, output->workspaces); + + state->active_workspace = output_get_active_workspace(output); +} + +static void copy_workspace_state(struct sway_workspace *ws, + struct sway_transaction_instruction *instruction) { + struct sway_workspace_state *state = + calloc(1, sizeof(struct sway_workspace_state)); + if (!state) { + wlr_log(WLR_ERROR, "Could not allocate workspace state"); + return; + } + instruction->workspace_state = state; + + state->fullscreen = ws->fullscreen; + state->x = ws->x; + state->y = ws->y; + state->width = ws->width; + state->height = ws->height; + state->layout = ws->layout; + + state->output = ws->output; + state->floating = create_list(); + state->tiling = create_list(); + list_cat(state->floating, ws->floating); + list_cat(state->tiling, ws->tiling); + + struct sway_seat *seat = input_manager_current_seat(input_manager); + state->focused = seat_get_focus(seat) == &ws->node; + + // Set focused_inactive_child to the direct tiling child + struct sway_container *focus = seat_get_focus_inactive_tiling(seat, ws); + if (focus) { + while (focus->parent) { + focus = focus->parent; + } + } + state->focused_inactive_child = focus; +} + +static void copy_container_state(struct sway_container *container, + struct sway_transaction_instruction *instruction) { + struct sway_container_state *state = + calloc(1, sizeof(struct sway_container_state)); + if (!state) { + wlr_log(WLR_ERROR, "Could not allocate container state"); + return; + } + instruction->container_state = state; + state->layout = container->layout; - state->swayc_x = container->x; - state->swayc_y = container->y; - state->swayc_width = container->width; - state->swayc_height = container->height; + state->con_x = container->x; + state->con_y = container->y; + state->con_width = container->width; + state->con_height = container->height; state->is_fullscreen = container->is_fullscreen; - state->has_gaps = container->has_gaps; - state->current_gaps = container->current_gaps; - state->gaps_inner = container->gaps_inner; - state->gaps_outer = container->gaps_outer; state->parent = container->parent; + state->workspace = container->workspace; - if (container->type == C_VIEW) { - struct sway_view *view = container->sway_view; + if (container->view) { + struct sway_view *view = container->view; state->view_x = view->x; state->view_y = view->y; state->view_width = view->width; @@ -107,50 +167,111 @@ static void copy_pending_state(struct sway_container *container, state->border_right = view->border_right; state->border_bottom = view->border_bottom; state->using_csd = view->using_csd; - } else if (container->type == C_WORKSPACE) { - state->ws_fullscreen = container->sway_workspace->fullscreen; - state->ws_floating = create_list(); - state->children = create_list(); - list_cat(state->ws_floating, container->sway_workspace->floating); - list_cat(state->children, container->children); } else { state->children = create_list(); list_cat(state->children, container->children); } struct sway_seat *seat = input_manager_current_seat(input_manager); - state->focused = seat_get_focus(seat) == container; - - if (container->type == C_WORKSPACE) { - // Set focused_inactive_child to the direct tiling child - struct sway_container *focus = - seat_get_focus_inactive_tiling(seat, container); - if (focus && focus->type > C_WORKSPACE) { - while (focus->parent->type != C_WORKSPACE) { - focus = focus->parent; - } - } - state->focused_inactive_child = focus; - } else if (container->type != C_VIEW) { - state->focused_inactive_child = - seat_get_active_child(seat, container); + state->focused = seat_get_focus(seat) == &container->node; + + if (!container->view) { + struct sway_node *focus = seat_get_active_child(seat, &container->node); + state->focused_inactive_child = focus ? focus->sway_container : NULL; } } -static void transaction_add_container(struct sway_transaction *transaction, - struct sway_container *container) { +static void transaction_add_node(struct sway_transaction *transaction, + struct sway_node *node) { struct sway_transaction_instruction *instruction = calloc(1, sizeof(struct sway_transaction_instruction)); if (!sway_assert(instruction, "Unable to allocate instruction")) { return; } instruction->transaction = transaction; - instruction->container = container; - - copy_pending_state(container, &instruction->state); + instruction->node = node; + + switch (node->type) { + case N_ROOT: + break; + case N_OUTPUT: + copy_output_state(node->sway_output, instruction); + break; + case N_WORKSPACE: + copy_workspace_state(node->sway_workspace, instruction); + break; + case N_CONTAINER: + copy_container_state(node->sway_container, instruction); + break; + } list_add(transaction->instructions, instruction); - container->ntxnrefs++; + node->ntxnrefs++; +} + +static void apply_output_state(struct sway_output *output, + struct sway_output_state *state) { + output_damage_whole(output); + list_free(output->current.workspaces); + memcpy(&output->current, state, sizeof(struct sway_output_state)); + output_damage_whole(output); +} + +static void apply_workspace_state(struct sway_workspace *ws, + struct sway_workspace_state *state) { + output_damage_whole(ws->current.output); + list_free(ws->current.floating); + list_free(ws->current.tiling); + memcpy(&ws->current, state, sizeof(struct sway_workspace_state)); + output_damage_whole(ws->current.output); +} + +static void apply_container_state(struct sway_container *container, + struct sway_container_state *state) { + struct sway_view *view = container->view; + // Damage the old location + desktop_damage_whole_container(container); + if (view && view->saved_buffer) { + struct wlr_box box = { + .x = container->current.view_x - view->saved_geometry.x, + .y = container->current.view_y - view->saved_geometry.y, + .width = view->saved_buffer_width, + .height = view->saved_buffer_height, + }; + desktop_damage_box(&box); + } + + // There are separate children lists for each instruction state, the + // container's current state and the container's pending state + // (ie. con->children). The list itself needs to be freed here. + // Any child containers which are being deleted will be cleaned up in + // transaction_destroy(). + list_free(container->current.children); + + memcpy(&container->current, state, sizeof(struct sway_container_state)); + + if (view && view->saved_buffer) { + if (!container->node.destroying || container->node.ntxnrefs == 1) { + view_remove_saved_buffer(view); + } + } + + // Damage the new location + desktop_damage_whole_container(container); + if (view && view->surface) { + struct wlr_surface *surface = view->surface; + struct wlr_box box = { + .x = container->current.view_x - view->geometry.x, + .y = container->current.view_y - view->geometry.y, + .width = surface->current.width, + .height = surface->current.height, + }; + desktop_damage_box(&box); + } + + if (!container->node.destroying) { + container_discover_outputs(container); + } } /** @@ -168,67 +289,36 @@ static void transaction_apply(struct sway_transaction *transaction) { "(%.1f frames if 60Hz)", transaction, ms, ms / (1000.0f / 60)); } - // Apply the instruction state to the container's current state + // Apply the instruction state to the node's current state for (int i = 0; i < transaction->instructions->length; ++i) { struct sway_transaction_instruction *instruction = transaction->instructions->items[i]; - struct sway_container *container = instruction->container; - - // Damage the old location - desktop_damage_whole_container(container); - if (container->type == C_VIEW && container->sway_view->saved_buffer) { - struct sway_view *view = container->sway_view; - struct wlr_box box = { - .x = container->current.view_x - view->saved_geometry.x, - .y = container->current.view_y - view->saved_geometry.y, - .width = view->saved_buffer_width, - .height = view->saved_buffer_height, - }; - desktop_damage_box(&box); - } - - // There are separate children lists for each instruction state, the - // container's current state and the container's pending state - // (ie. con->children). The list itself needs to be freed here. - // Any child containers which are being deleted will be cleaned up in - // transaction_destroy(). - list_free(container->current.children); - list_free(container->current.ws_floating); - - memcpy(&container->current, &instruction->state, - sizeof(struct sway_container_state)); - - if (container->type == C_VIEW && container->sway_view->saved_buffer) { - if (!container->destroying || container->ntxnrefs == 1) { - view_remove_saved_buffer(container->sway_view); - } - } + struct sway_node *node = instruction->node; - // Damage the new location - desktop_damage_whole_container(container); - if (container->type == C_VIEW && container->sway_view->surface) { - struct sway_view *view = container->sway_view; - struct wlr_surface *surface = view->surface; - struct wlr_box box = { - .x = container->current.view_x - view->geometry.x, - .y = container->current.view_y - view->geometry.y, - .width = surface->current.width, - .height = surface->current.height, - }; - desktop_damage_box(&box); + switch (node->type) { + case N_ROOT: + break; + case N_OUTPUT: + apply_output_state(node->sway_output, instruction->output_state); + break; + case N_WORKSPACE: + apply_workspace_state(node->sway_workspace, + instruction->workspace_state); + break; + case N_CONTAINER: + apply_container_state(node->sway_container, + instruction->container_state); + break; } - container->instruction = NULL; - if (container->type == C_CONTAINER || container->type == C_VIEW) { - container_discover_outputs(container); - } + node->instruction = NULL; } } static void transaction_commit(struct sway_transaction *transaction); -// Return true if both transactions operate on the same containers -static bool transaction_same_containers(struct sway_transaction *a, +// Return true if both transactions operate on the same nodes +static bool transaction_same_nodes(struct sway_transaction *a, struct sway_transaction *b) { if (a->instructions->length != b->instructions->length) { return false; @@ -236,7 +326,7 @@ static bool transaction_same_containers(struct sway_transaction *a, for (int i = 0; i < a->instructions->length; ++i) { struct sway_transaction_instruction *a_inst = a->instructions->items[i]; struct sway_transaction_instruction *b_inst = b->instructions->items[i]; - if (a_inst->container != b_inst->container) { + if (a_inst->node != b_inst->node) { return false; } } @@ -267,7 +357,7 @@ static void transaction_progress_queue() { while (server.transactions->length >= 2) { struct sway_transaction *a = server.transactions->items[0]; struct sway_transaction *b = server.transactions->items[1]; - if (transaction_same_containers(a, b)) { + if (transaction_same_nodes(a, b)) { list_del(server.transactions, 0); transaction_destroy(a); } else { @@ -289,16 +379,18 @@ static int handle_timeout(void *data) { return 0; } -static bool should_configure(struct sway_container *con, +static bool should_configure(struct sway_node *node, struct sway_transaction_instruction *instruction) { - if (con->type != C_VIEW) { + if (!node_is_view(node)) { return false; } - if (con->destroying) { + if (node->destroying) { return false; } - if (con->current.view_width == instruction->state.view_width && - con->current.view_height == instruction->state.view_height) { + struct sway_container_state *cstate = &node->sway_container->current; + struct sway_container_state *istate = instruction->container_state; + if (cstate->view_width == istate->view_width && + cstate->view_height == istate->view_height) { return false; } return true; @@ -311,13 +403,13 @@ static void transaction_commit(struct sway_transaction *transaction) { for (int i = 0; i < transaction->instructions->length; ++i) { struct sway_transaction_instruction *instruction = transaction->instructions->items[i]; - struct sway_container *con = instruction->container; - if (should_configure(con, instruction)) { - instruction->serial = view_configure(con->sway_view, - instruction->state.view_x, - instruction->state.view_y, - instruction->state.view_width, - instruction->state.view_height); + struct sway_node *node = instruction->node; + if (should_configure(node, instruction)) { + instruction->serial = view_configure(node->sway_container->view, + instruction->container_state->view_x, + instruction->container_state->view_y, + instruction->container_state->view_width, + instruction->container_state->view_height); ++transaction->num_waiting; // From here on we are rendering a saved buffer of the view, which @@ -325,14 +417,16 @@ static void transaction_commit(struct sway_transaction *transaction) { // as soon as possible. Additionally, this is required if a view is // mapping and its default geometry doesn't intersect an output. struct timespec when; - wlr_surface_send_frame_done(con->sway_view->surface, &when); + wlr_surface_send_frame_done( + node->sway_container->view->surface, &when); } - if (con->type == C_VIEW && !con->sway_view->saved_buffer) { - view_save_buffer(con->sway_view); - memcpy(&con->sway_view->saved_geometry, &con->sway_view->geometry, + if (node_is_view(node) && !node->sway_container->view->saved_buffer) { + view_save_buffer(node->sway_container->view); + memcpy(&node->sway_container->view->saved_geometry, + &node->sway_container->view->geometry, sizeof(struct wlr_box)); } - con->instruction = instruction; + node->instruction = instruction; } transaction->num_configures = transaction->num_waiting; if (debug.txn_timings) { @@ -381,7 +475,7 @@ static void set_instruction_ready( transaction, transaction->num_configures - transaction->num_waiting + 1, transaction->num_configures, ms, - instruction->container->name); + instruction->node->sway_container->title); } // If the transaction has timed out then its num_waiting will be 0 already. @@ -390,41 +484,43 @@ static void set_instruction_ready( wl_event_source_timer_update(transaction->timer, 0); } - instruction->container->instruction = NULL; + instruction->node->instruction = NULL; transaction_progress_queue(); } void transaction_notify_view_ready_by_serial(struct sway_view *view, uint32_t serial) { - struct sway_transaction_instruction *instruction = view->swayc->instruction; - if (view->swayc->instruction->serial == serial) { + struct sway_transaction_instruction *instruction = + view->container->node.instruction; + if (instruction->serial == serial) { set_instruction_ready(instruction); } } void transaction_notify_view_ready_by_size(struct sway_view *view, int width, int height) { - struct sway_transaction_instruction *instruction = view->swayc->instruction; - if (instruction->state.view_width == width && - instruction->state.view_height == height) { + struct sway_transaction_instruction *instruction = + view->container->node.instruction; + if (instruction->container_state->view_width == width && + instruction->container_state->view_height == height) { set_instruction_ready(instruction); } } void transaction_commit_dirty(void) { - if (!server.dirty_containers->length) { + if (!server.dirty_nodes->length) { return; } struct sway_transaction *transaction = transaction_create(); if (!transaction) { return; } - for (int i = 0; i < server.dirty_containers->length; ++i) { - struct sway_container *container = server.dirty_containers->items[i]; - transaction_add_container(transaction, container); - container->dirty = false; + for (int i = 0; i < server.dirty_nodes->length; ++i) { + struct sway_node *node = server.dirty_nodes->items[i]; + transaction_add_node(transaction, node); + node->dirty = false; } - server.dirty_containers->length = 0; + server.dirty_nodes->length = 0; list_add(server.transactions, transaction); diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 587deb0f..e19d8e18 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -11,10 +11,12 @@ #include "sway/desktop/transaction.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" +#include "sway/output.h" #include "sway/server.h" #include "sway/tree/arrange.h" #include "sway/tree/container.h" #include "sway/tree/view.h" +#include "sway/tree/workspace.h" static const struct sway_view_child_impl popup_impl; @@ -52,15 +54,15 @@ static void popup_unconstrain(struct sway_xdg_popup *popup) { struct sway_view *view = popup->child.view; struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_surface->popup; - struct sway_container *output = container_parent(view->swayc, C_OUTPUT); + struct sway_output *output = view->container->workspace->output; // the output box expressed in the coordinate system of the toplevel parent // of the popup struct wlr_box output_toplevel_sx_box = { - .x = output->x - view->x, - .y = output->y - view->y, - .width = output->width, - .height = output->height, + .x = output->wlr_output->lx - view->x, + .y = output->wlr_output->ly - view->y, + .width = output->wlr_output->width, + .height = output->wlr_output->height, }; wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); @@ -252,11 +254,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct sway_view *view = &xdg_shell_view->view; struct wlr_xdg_surface *xdg_surface = view->wlr_xdg_surface; - if (!view->swayc) { - return; - } - - if (view->swayc->instruction) { + if (view->container->node.instruction) { wlr_xdg_surface_get_geometry(xdg_surface, &view->geometry); transaction_notify_view_ready_by_serial(view, xdg_surface->configure_serial); @@ -265,7 +263,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { wlr_xdg_surface_get_geometry(xdg_surface, &new_geo); if ((new_geo.width != view->width || new_geo.height != view->height) && - container_is_floating(view->swayc)) { + container_is_floating(view->container)) { // A floating view has unexpectedly sent a new size desktop_damage_view(view); view_update_size(view, new_geo.width, new_geo.height); @@ -319,10 +317,9 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) return; } - container_set_fullscreen(view->swayc, e->fullscreen); + container_set_fullscreen(view->container, e->fullscreen); - struct sway_container *output = container_parent(view->swayc, C_OUTPUT); - arrange_windows(output); + arrange_workspace(view->container->workspace); transaction_commit_dirty(); } @@ -330,13 +327,13 @@ static void handle_request_move(struct wl_listener *listener, void *data) { struct sway_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, request_move); struct sway_view *view = &xdg_shell_view->view; - if (!container_is_floating(view->swayc)) { + if (!container_is_floating(view->container)) { return; } struct wlr_xdg_toplevel_move_event *e = data; struct sway_seat *seat = e->seat->seat->data; if (e->serial == seat->last_button_serial) { - seat_begin_move(seat, view->swayc, seat->last_button); + seat_begin_move(seat, view->container, seat->last_button); } } @@ -344,13 +341,13 @@ static void handle_request_resize(struct wl_listener *listener, void *data) { struct sway_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, request_resize); struct sway_view *view = &xdg_shell_view->view; - if (!container_is_floating(view->swayc)) { + if (!container_is_floating(view->container)) { return; } struct wlr_xdg_toplevel_resize_event *e = data; struct sway_seat *seat = e->seat->seat->data; if (e->serial == seat->last_button_serial) { - seat_begin_resize_floating(seat, view->swayc, + seat_begin_resize_floating(seat, view->container, seat->last_button, e->edges); } } @@ -399,11 +396,14 @@ static void handle_map(struct wl_listener *listener, void *data) { view_map(view, view->wlr_xdg_surface->surface); if (xdg_surface->toplevel->client_pending.fullscreen) { - container_set_fullscreen(view->swayc, true); - struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); - arrange_windows(ws); + container_set_fullscreen(view->container, true); + arrange_workspace(view->container->workspace); } else { - arrange_windows(view->swayc->parent); + if (view->container->parent) { + arrange_container(view->container->parent); + } else { + arrange_workspace(view->container->workspace); + } } transaction_commit_dirty(); @@ -440,8 +440,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, destroy); struct sway_view *view = &xdg_shell_view->view; - if (!sway_assert(view->swayc == NULL || view->swayc->destroying, - "Tried to destroy a mapped view")) { + if (!sway_assert(view->surface == NULL, "Tried to destroy a mapped view")) { return; } wl_list_remove(&xdg_shell_view->destroy.link); diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 175416f3..b23d4577 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -10,10 +10,12 @@ #include "sway/desktop/transaction.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" +#include "sway/output.h" #include "sway/server.h" #include "sway/tree/arrange.h" #include "sway/tree/container.h" #include "sway/tree/view.h" +#include "sway/tree/workspace.h" static const struct sway_view_child_impl popup_impl; @@ -51,15 +53,15 @@ static void popup_unconstrain(struct sway_xdg_popup_v6 *popup) { struct sway_view *view = popup->child.view; struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_xdg_surface_v6->popup; - struct sway_container *output = container_parent(view->swayc, C_OUTPUT); + struct sway_output *output = view->container->workspace->output; // the output box expressed in the coordinate system of the toplevel parent // of the popup struct wlr_box output_toplevel_sx_box = { - .x = output->x - view->x, - .y = output->y - view->y, - .width = output->width, - .height = output->height, + .x = output->wlr_output->lx - view->x, + .y = output->wlr_output->ly - view->y, + .width = output->wlr_output->width, + .height = output->wlr_output->height, }; wlr_xdg_popup_v6_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); @@ -249,11 +251,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct sway_view *view = &xdg_shell_v6_view->view; struct wlr_xdg_surface_v6 *xdg_surface_v6 = view->wlr_xdg_surface_v6; - if (!view->swayc) { - return; - } - - if (view->swayc->instruction) { + if (view->container->node.instruction) { wlr_xdg_surface_v6_get_geometry(xdg_surface_v6, &view->geometry); transaction_notify_view_ready_by_serial(view, xdg_surface_v6->configure_serial); @@ -262,7 +260,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { wlr_xdg_surface_v6_get_geometry(xdg_surface_v6, &new_geo); if ((new_geo.width != view->width || new_geo.height != view->height) && - container_is_floating(view->swayc)) { + container_is_floating(view->container)) { // A floating view has unexpectedly sent a new size desktop_damage_view(view); view_update_size(view, new_geo.width, new_geo.height); @@ -316,10 +314,9 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) return; } - container_set_fullscreen(view->swayc, e->fullscreen); + container_set_fullscreen(view->container, e->fullscreen); - struct sway_container *output = container_parent(view->swayc, C_OUTPUT); - arrange_windows(output); + arrange_workspace(view->container->workspace); transaction_commit_dirty(); } @@ -327,13 +324,13 @@ static void handle_request_move(struct wl_listener *listener, void *data) { struct sway_xdg_shell_v6_view *xdg_shell_v6_view = wl_container_of(listener, xdg_shell_v6_view, request_move); struct sway_view *view = &xdg_shell_v6_view->view; - if (!container_is_floating(view->swayc)) { + if (!container_is_floating(view->container)) { return; } struct wlr_xdg_toplevel_v6_move_event *e = data; struct sway_seat *seat = e->seat->seat->data; if (e->serial == seat->last_button_serial) { - seat_begin_move(seat, view->swayc, seat->last_button); + seat_begin_move(seat, view->container, seat->last_button); } } @@ -341,13 +338,13 @@ static void handle_request_resize(struct wl_listener *listener, void *data) { struct sway_xdg_shell_v6_view *xdg_shell_v6_view = wl_container_of(listener, xdg_shell_v6_view, request_resize); struct sway_view *view = &xdg_shell_v6_view->view; - if (!container_is_floating(view->swayc)) { + if (!container_is_floating(view->container)) { return; } struct wlr_xdg_toplevel_v6_resize_event *e = data; struct sway_seat *seat = e->seat->seat->data; if (e->serial == seat->last_button_serial) { - seat_begin_resize_floating(seat, view->swayc, + seat_begin_resize_floating(seat, view->container, seat->last_button, e->edges); } } @@ -396,11 +393,14 @@ static void handle_map(struct wl_listener *listener, void *data) { view_map(view, view->wlr_xdg_surface_v6->surface); if (xdg_surface->toplevel->client_pending.fullscreen) { - container_set_fullscreen(view->swayc, true); - struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); - arrange_windows(ws); + container_set_fullscreen(view->container, true); + arrange_workspace(view->container->workspace); } else { - arrange_windows(view->swayc->parent); + if (view->container->parent) { + arrange_container(view->container->parent); + } else { + arrange_workspace(view->container->workspace); + } } transaction_commit_dirty(); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 94a30239..0d192b76 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -59,8 +59,7 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) { wl_container_of(listener, surface, map); struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; - wl_list_insert(root_container.sway_root->xwayland_unmanaged.prev, - &surface->link); + wl_list_insert(root->xwayland_unmanaged.prev, &surface->link); wl_signal_add(&xsurface->surface->events.commit, &surface->commit); surface->commit.notify = unmanaged_handle_commit; @@ -90,11 +89,10 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { if (seat->wlr_seat->keyboard_state.focused_surface == xsurface->surface) { // Restore focus - struct sway_container *previous = - seat_get_focus_inactive(seat, &root_container); + struct sway_node *previous = seat_get_focus_inactive(seat, &root->node); if (previous) { // Hack to get seat to re-focus the return value of get_focus - seat_set_focus(seat, previous->parent); + seat_set_focus(seat, NULL); seat_set_focus(seat, previous); } } @@ -299,7 +297,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_surface_state *state = &xsurface->surface->current; - if (view->swayc->instruction) { + if (view->container->node.instruction) { get_geometry(view, &view->geometry); transaction_notify_view_ready_by_size(view, state->width, state->height); @@ -308,7 +306,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { get_geometry(view, &new_geo); if ((new_geo.width != view->width || new_geo.height != view->height) && - container_is_floating(view->swayc)) { + container_is_floating(view->container)) { // A floating view has unexpectedly sent a new size // eg. The Firefox "Save As" dialog when downloading a file desktop_damage_view(view); @@ -391,11 +389,14 @@ static void handle_map(struct wl_listener *listener, void *data) { view_map(view, xsurface->surface); if (xsurface->fullscreen) { - container_set_fullscreen(view->swayc, true); - struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); - arrange_windows(ws); + container_set_fullscreen(view->container, true); + arrange_workspace(view->container->workspace); } else { - arrange_windows(view->swayc->parent); + if (view->container->parent) { + arrange_container(view->container->parent); + } else { + arrange_workspace(view->container->workspace); + } } transaction_commit_dirty(); } @@ -411,13 +412,14 @@ static void handle_request_configure(struct wl_listener *listener, void *data) { ev->width, ev->height); return; } - if (container_is_floating(view->swayc)) { - configure(view, view->swayc->current.view_x, - view->swayc->current.view_y, ev->width, ev->height); + if (container_is_floating(view->container)) { + configure(view, view->container->current.view_x, + view->container->current.view_y, ev->width, ev->height); } else { - configure(view, view->swayc->current.view_x, - view->swayc->current.view_y, view->swayc->current.view_width, - view->swayc->current.view_height); + configure(view, view->container->current.view_x, + view->container->current.view_y, + view->container->current.view_width, + view->container->current.view_height); } } @@ -429,10 +431,9 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) if (!xsurface->mapped) { return; } - container_set_fullscreen(view->swayc, xsurface->fullscreen); + container_set_fullscreen(view->container, xsurface->fullscreen); - struct sway_container *output = container_parent(view->swayc, C_OUTPUT); - arrange_windows(output); + arrange_workspace(view->container->workspace); transaction_commit_dirty(); } @@ -444,11 +445,11 @@ static void handle_request_move(struct wl_listener *listener, void *data) { if (!xsurface->mapped) { return; } - if (!container_is_floating(view->swayc)) { + if (!container_is_floating(view->container)) { return; } struct sway_seat *seat = input_manager_current_seat(input_manager); - seat_begin_move(seat, view->swayc, seat->last_button); + seat_begin_move(seat, view->container, seat->last_button); } static void handle_request_resize(struct wl_listener *listener, void *data) { @@ -459,12 +460,13 @@ static void handle_request_resize(struct wl_listener *listener, void *data) { if (!xsurface->mapped) { return; } - if (!container_is_floating(view->swayc)) { + if (!container_is_floating(view->container)) { return; } struct wlr_xwayland_resize_event *e = data; struct sway_seat *seat = input_manager_current_seat(input_manager); - seat_begin_resize_floating(seat, view->swayc, seat->last_button, e->edges); + seat_begin_resize_floating(seat, view->container, + seat->last_button, e->edges); } static void handle_request_activate(struct wl_listener *listener, void *data) { |