diff options
Diffstat (limited to 'sway/tree')
-rw-r--r-- | sway/tree/container.c | 80 | ||||
-rw-r--r-- | sway/tree/output.c | 7 | ||||
-rw-r--r-- | sway/tree/root.c | 2 | ||||
-rw-r--r-- | sway/tree/view.c | 61 | ||||
-rw-r--r-- | sway/tree/workspace.c | 126 |
5 files changed, 180 insertions, 96 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c index 458ed7ff..cf6f5b54 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -165,13 +165,13 @@ static struct sway_container *surface_at_view(struct sway_container *con, double return NULL; } struct sway_view *view = con->view; - double view_sx = lx - view->x + view->geometry.x; - double view_sy = ly - view->y + view->geometry.y; + double view_sx = lx - con->content_x + view->geometry.x; + double view_sy = ly - con->content_y + view->geometry.y; double _sx, _sy; struct wlr_surface *_surface = NULL; switch (view->type) { -#ifdef HAVE_XWAYLAND +#if HAVE_XWAYLAND case SWAY_VIEW_XWAYLAND: _surface = wlr_surface_surface_at(view->surface, view_sx, view_sy, &_sx, &_sy); @@ -641,16 +641,18 @@ void container_init_floating(struct sway_container *con) { con->y = ws->y + (ws->height - con->height) / 2; } else { struct sway_view *view = con->view; - view->width = fmax(min_width, fmin(view->natural_width, max_width)); - view->height = fmax(min_height, fmin(view->natural_height, max_height)); - view->x = ws->x + (ws->width - view->width) / 2; - view->y = ws->y + (ws->height - view->height) / 2; + con->content_width = + fmax(min_width, fmin(view->natural_width, max_width)); + con->content_height = + fmax(min_height, fmin(view->natural_height, max_height)); + con->content_x = ws->x + (ws->width - con->content_width) / 2; + con->content_y = ws->y + (ws->height - con->content_height) / 2; // If the view's border is B_NONE then these properties are ignored. con->border_top = con->border_bottom = true; con->border_left = con->border_right = true; - container_set_geometry_from_floating_view(con); + container_set_geometry_from_content(con); } } @@ -707,14 +709,13 @@ void container_set_floating(struct sway_container *container, bool enable) { ipc_event_window(container, "floating"); } -void container_set_geometry_from_floating_view(struct sway_container *con) { +void container_set_geometry_from_content(struct sway_container *con) { if (!sway_assert(con->view, "Expected a view")) { return; } if (!sway_assert(container_is_floating(con), "Expected a floating view")) { return; } - struct sway_view *view = con->view; size_t border_width = 0; size_t top = 0; @@ -724,10 +725,10 @@ void container_set_geometry_from_floating_view(struct sway_container *con) { container_titlebar_height() : border_width; } - con->x = view->x - border_width; - con->y = view->y - top; - con->width = view->width + border_width * 2; - con->height = top + view->height + border_width; + con->x = con->content_x - border_width; + con->y = con->content_y - top; + con->width = con->content_width + border_width * 2; + con->height = top + con->content_height + border_width; node_set_dirty(&con->node); } @@ -756,15 +757,16 @@ void container_floating_translate(struct sway_container *con, double x_amount, double y_amount) { con->x += x_amount; con->y += y_amount; - if (con->view) { - con->view->x += x_amount; - con->view->y += y_amount; - } else { + con->content_x += x_amount; + con->content_y += y_amount; + + if (con->children) { for (int i = 0; i < con->children->length; ++i) { struct sway_container *child = con->children->items[i]; container_floating_translate(child, x_amount, y_amount); } } + node_set_dirty(&con->node); } @@ -964,10 +966,10 @@ static void surface_send_leave_iterator(struct wlr_surface *surface, void container_discover_outputs(struct sway_container *con) { struct wlr_box con_box = { - .x = con->current.con_x, - .y = con->current.con_y, - .width = con->current.con_width, - .height = con->current.con_height, + .x = con->current.x, + .y = con->current.y, + .width = con->current.width, + .height = con->current.height, }; struct sway_output *old_output = container_get_effective_output(con); @@ -1009,19 +1011,25 @@ void container_discover_outputs(struct sway_container *con) { } void container_remove_gaps(struct sway_container *c) { - if (c->current_gaps == 0) { + if (c->current_gaps.top == 0 && c->current_gaps.right == 0 && + c->current_gaps.bottom == 0 && c->current_gaps.left == 0) { return; } - c->width += c->current_gaps * 2; - c->height += c->current_gaps * 2; - c->x -= c->current_gaps; - c->y -= c->current_gaps; - c->current_gaps = 0; + c->width += c->current_gaps.left + c->current_gaps.right; + c->height += c->current_gaps.top + c->current_gaps.bottom; + c->x -= c->current_gaps.left; + c->y -= c->current_gaps.top; + + c->current_gaps.top = 0; + c->current_gaps.right = 0; + c->current_gaps.bottom = 0; + c->current_gaps.left = 0; } void container_add_gaps(struct sway_container *c) { - if (c->current_gaps > 0) { + if (c->current_gaps.top > 0 || c->current_gaps.right > 0 || + c->current_gaps.bottom > 0 || c->current_gaps.left > 0) { return; } // Linear containers don't have gaps because it'd create double gaps @@ -1054,11 +1062,15 @@ void container_add_gaps(struct sway_container *c) { struct sway_workspace *ws = c->workspace; - c->current_gaps = ws->gaps_inner; - c->x += c->current_gaps; - c->y += c->current_gaps; - c->width -= 2 * c->current_gaps; - c->height -= 2 * c->current_gaps; + c->current_gaps.top = c->y == ws->y ? ws->gaps_inner : 0; + c->current_gaps.right = ws->gaps_inner; + c->current_gaps.bottom = ws->gaps_inner; + c->current_gaps.left = c->x == ws->x ? ws->gaps_inner : 0; + + c->x += c->current_gaps.left; + c->y += c->current_gaps.top; + c->width -= c->current_gaps.left + c->current_gaps.right; + c->height -= c->current_gaps.top + c->current_gaps.bottom; } enum sway_container_layout container_parent_layout(struct sway_container *con) { diff --git a/sway/tree/output.c b/sway/tree/output.c index 2704920d..3c4614a8 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -31,6 +31,13 @@ static void restore_workspaces(struct sway_output *output) { j--; } } + + if (other->workspaces->length == 0) { + char *next = workspace_next_name(other->wlr_output->name); + struct sway_workspace *ws = workspace_create(other, next); + free(next); + ipc_event_workspace(NULL, ws, "init"); + } } // Saved workspaces diff --git a/sway/tree/root.c b/sway/tree/root.c index 9bda7c28..544d666a 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -31,7 +31,7 @@ struct sway_root *root_create(void) { node_init(&root->node, N_ROOT, root); root->output_layout = wlr_output_layout_create(); wl_list_init(&root->all_outputs); -#ifdef HAVE_XWAYLAND +#if HAVE_XWAYLAND wl_list_init(&root->xwayland_unmanaged); #endif wl_list_init(&root->drag_icons); diff --git a/sway/tree/view.c b/sway/tree/view.c index 1aa59e68..d7110619 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -8,7 +8,7 @@ #include <wlr/types/wlr_server_decoration.h> #include <wlr/types/wlr_xdg_decoration_v1.h> #include "config.h" -#ifdef HAVE_XWAYLAND +#if HAVE_XWAYLAND #include <wlr/xwayland.h> #endif #include "list.h" @@ -101,7 +101,7 @@ const char *view_get_instance(struct sway_view *view) { } return NULL; } -#ifdef HAVE_XWAYLAND +#if HAVE_XWAYLAND uint32_t view_get_x11_window_id(struct sway_view *view) { if (view->impl->get_int_prop) { return view->impl->get_int_prop(view, VIEW_PROP_X11_WINDOW_ID); @@ -136,7 +136,7 @@ const char *view_get_shell(struct sway_view *view) { return "xdg_shell_v6"; case SWAY_VIEW_XDG_SHELL: return "xdg_shell"; -#ifdef HAVE_XWAYLAND +#if HAVE_XWAYLAND case SWAY_VIEW_XWAYLAND: return "xwayland"; #endif @@ -185,31 +185,33 @@ bool view_is_only_visible(struct sway_view *view) { static bool gaps_to_edge(struct sway_view *view) { struct sway_container *con = view->container; while (con) { - if (con->current_gaps > 0) { + if (con->current_gaps.top > 0 || con->current_gaps.right > 0 || + con->current_gaps.bottom > 0 || con->current_gaps.left > 0) { return true; } con = con->parent; } - return view->container->workspace->current_gaps > 0; + struct side_gaps gaps = view->container->workspace->current_gaps; + return gaps.top > 0 || gaps.right > 0 || gaps.bottom > 0 || gaps.left > 0; } void view_autoconfigure(struct sway_view *view) { - if (!view->container->workspace) { + struct sway_container *con = view->container; + if (!con->workspace) { // Hidden in the scratchpad return; } - struct sway_output *output = view->container->workspace->output; + struct sway_output *output = con->workspace->output; - if (view->container->is_fullscreen) { - view->x = output->lx; - view->y = output->ly; - view->width = output->width; - view->height = output->height; + if (con->is_fullscreen) { + con->content_x = output->lx; + con->content_y = output->ly; + con->content_width = output->width; + con->content_height = output->height; return; } struct sway_workspace *ws = view->container->workspace; - struct sway_container *con = view->container; bool smart = config->hide_edge_borders == E_SMART || config->hide_edge_borders == E_SMART_NO_GAPS; @@ -222,15 +224,15 @@ void view_autoconfigure(struct sway_view *view) { if (config->hide_edge_borders == E_BOTH || config->hide_edge_borders == E_VERTICAL || (smart && !other_views && no_gaps)) { - con->border_left = con->x - con->current_gaps != ws->x; - int right_x = con->x + con->width + con->current_gaps; + con->border_left = con->x - con->current_gaps.left != ws->x; + int right_x = con->x + con->width + con->current_gaps.right; con->border_right = right_x != ws->x + ws->width; } if (config->hide_edge_borders == E_BOTH || config->hide_edge_borders == E_HORIZONTAL || (smart && !other_views && no_gaps)) { - con->border_top = con->y - con->current_gaps != ws->y; - int bottom_y = con->y + con->height + con->current_gaps; + con->border_top = con->y - con->current_gaps.top != ws->y; + int bottom_y = con->y + con->height + con->current_gaps.bottom; con->border_bottom = bottom_y != ws->y + ws->height; } @@ -287,10 +289,10 @@ void view_autoconfigure(struct sway_view *view) { break; } - view->x = x; - view->y = y; - view->width = width; - view->height = height; + con->content_x = x; + con->content_y = y; + con->content_width = width; + con->content_height = height; } void view_set_activated(struct sway_view *view, bool activated) { @@ -482,7 +484,7 @@ static struct sway_workspace *select_workspace(struct sway_view *view) { // Check if there's a PID mapping pid_t pid; -#ifdef HAVE_XWAYLAND +#if HAVE_XWAYLAND if (view->type == SWAY_VIEW_XWAYLAND) { struct wlr_xwayland_surface *surf = wlr_xwayland_surface_from_wlr_surface(view->surface); @@ -665,11 +667,11 @@ void view_update_size(struct sway_view *view, int width, int height) { "Expected a floating container")) { return; } - view->width = width; - view->height = height; - view->container->current.view_width = width; - view->container->current.view_height = height; - container_set_geometry_from_floating_view(view->container); + view->container->content_width = width; + view->container->content_height = height; + view->container->current.content_width = width; + view->container->current.content_height = height; + container_set_geometry_from_content(view->container); } static void subsurface_get_root_coords(struct sway_view_child *child, @@ -705,7 +707,8 @@ static void view_child_damage(struct sway_view_child *child, bool whole) { int sx, sy; child->impl->get_root_coords(child, &sx, &sy); desktop_damage_surface(child->surface, - child->view->x + sx, child->view->y + sy, whole); + child->view->container->content_x + sx, + child->view->container->content_y + sy, whole); } static void view_child_handle_surface_commit(struct wl_listener *listener, @@ -799,7 +802,7 @@ struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) { wlr_xdg_surface_v6_from_wlr_surface(wlr_surface); return view_from_wlr_xdg_surface_v6(xdg_surface_v6); } -#ifdef HAVE_XWAYLAND +#if HAVE_XWAYLAND if (wlr_surface_is_xwayland_surface(wlr_surface)) { struct wlr_xwayland_surface *xsurface = wlr_xwayland_surface_from_wlr_surface(wlr_surface); diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 05cda5c0..4be63311 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -33,14 +33,15 @@ struct workspace_config *workspace_find_config(const char *ws_name) { struct sway_output *workspace_get_initial_output(const char *name) { // Check workspace configs for a workspace<->output pair struct workspace_config *wsc = workspace_find_config(name); - if (wsc && wsc->output) { - struct sway_output *output = output_by_name(wsc->output); - if (!output) { - output = output_by_identifier(wsc->output); - } - - if (output) { - return output; + if (wsc) { + for (int i = 0; i < wsc->outputs->length; i++) { + struct sway_output *output = output_by_name(wsc->outputs->items[i]); + if (!output) { + output = output_by_identifier(wsc->outputs->items[i]); + } + if (output) { + return output; + } } } // Otherwise put it on the focused output @@ -49,6 +50,21 @@ struct sway_output *workspace_get_initial_output(const char *name) { return focus->output; } +static void prevent_invalid_outer_gaps(struct sway_workspace *ws) { + if (ws->gaps_outer.top < -ws->gaps_inner) { + ws->gaps_outer.top = -ws->gaps_inner; + } + if (ws->gaps_outer.right < -ws->gaps_inner) { + ws->gaps_outer.right = -ws->gaps_inner; + } + if (ws->gaps_outer.bottom < -ws->gaps_inner) { + ws->gaps_outer.bottom = -ws->gaps_inner; + } + if (ws->gaps_outer.left < -ws->gaps_inner) { + ws->gaps_outer.left = -ws->gaps_inner; + } +} + struct sway_workspace *workspace_create(struct sway_output *output, const char *name) { if (output == NULL) { @@ -70,22 +86,41 @@ struct sway_workspace *workspace_create(struct sway_output *output, ws->floating = create_list(); ws->tiling = create_list(); ws->output_priority = create_list(); - workspace_output_add_priority(ws, output); ws->gaps_outer = config->gaps_outer; ws->gaps_inner = config->gaps_inner; if (name) { struct workspace_config *wsc = workspace_find_config(name); if (wsc) { - if (wsc->gaps_outer != INT_MIN) { - ws->gaps_outer = wsc->gaps_outer; + if (wsc->gaps_outer.top != INT_MIN) { + ws->gaps_outer.top = wsc->gaps_outer.top; + } + if (wsc->gaps_outer.right != INT_MIN) { + ws->gaps_outer.right = wsc->gaps_outer.right; + } + if (wsc->gaps_outer.bottom != INT_MIN) { + ws->gaps_outer.bottom = wsc->gaps_outer.bottom; + } + if (wsc->gaps_outer.left != INT_MIN) { + ws->gaps_outer.left = wsc->gaps_outer.left; } if (wsc->gaps_inner != INT_MIN) { ws->gaps_inner = wsc->gaps_inner; } + // Since default outer gaps can be smaller than the negation of + // workspace specific inner gaps, check outer gaps again + prevent_invalid_outer_gaps(ws); + + // Add output priorities + for (int i = 0; i < wsc->outputs->length; ++i) { + list_add(ws->output_priority, strdup(wsc->outputs->items[i])); + } } } + // If not already added, add the output to the lowest priority + workspace_output_add_priority(ws, output); + output_add_workspace(output, ws); output_sort_workspaces(output); @@ -107,8 +142,7 @@ void workspace_destroy(struct sway_workspace *workspace) { free(workspace->name); free(workspace->representation); - list_foreach(workspace->output_priority, free); - list_free(workspace->output_priority); + free_flat_list(workspace->output_priority); list_free(workspace->floating); list_free(workspace->tiling); list_free(workspace->current.floating); @@ -150,8 +184,19 @@ static bool workspace_valid_on_output(const char *output_name, char identifier[128]; struct sway_output *output = output_by_name(output_name); output_get_identifier(identifier, sizeof(identifier), output); - - return !wsc || !wsc->output || strcmp(wsc->output, output_name) == 0 || strcasecmp(identifier, output_name) == 0; + + if (!wsc) { + return true; + } + + for (int i = 0; i < wsc->outputs->length; i++) { + if (strcmp(wsc->outputs->items[i], output_name) == 0 || + strcmp(wsc->outputs->items[i], identifier) == 0) { + return true; + } + } + + return false; } static void workspace_name_from_binding(const struct sway_binding * binding, @@ -254,10 +299,19 @@ char *workspace_next_name(const char *output_name) { for (int i = 0; i < config->workspace_configs->length; ++i) { // Unlike with bindings, this does not guarantee order const struct workspace_config *wsc = config->workspace_configs->items[i]; - if (wsc->output && strcmp(wsc->output, output_name) == 0 - && workspace_by_name(wsc->workspace) == NULL) { - free(target); - target = strdup(wsc->workspace); + if (workspace_by_name(wsc->workspace)) { + continue; + } + bool found = false; + for (int j = 0; j < wsc->outputs->length; ++j) { + if (strcmp(wsc->outputs->items[j], output_name) == 0) { + found = true; + free(target); + target = strdup(wsc->workspace); + break; + } + } + if (found) { break; } } @@ -615,19 +669,25 @@ void workspace_insert_tiling(struct sway_workspace *workspace, } void workspace_remove_gaps(struct sway_workspace *ws) { - if (ws->current_gaps == 0) { + if (ws->current_gaps.top == 0 && ws->current_gaps.right == 0 && + ws->current_gaps.bottom == 0 && ws->current_gaps.left == 0) { return; } - ws->width += ws->current_gaps * 2; - ws->height += ws->current_gaps * 2; - ws->x -= ws->current_gaps; - ws->y -= ws->current_gaps; - ws->current_gaps = 0; + ws->width += ws->current_gaps.left + ws->current_gaps.right; + ws->height += ws->current_gaps.top + ws->current_gaps.bottom; + ws->x -= ws->current_gaps.left; + ws->y -= ws->current_gaps.top; + + ws->current_gaps.top = 0; + ws->current_gaps.right = 0; + ws->current_gaps.bottom = 0; + ws->current_gaps.left = 0; } void workspace_add_gaps(struct sway_workspace *ws) { - if (ws->current_gaps > 0) { + if (ws->current_gaps.top > 0 || ws->current_gaps.right > 0 || + ws->current_gaps.bottom > 0 || ws->current_gaps.left > 0) { return; } if (config->smart_gaps) { @@ -643,18 +703,20 @@ void workspace_add_gaps(struct sway_workspace *ws) { } ws->current_gaps = ws->gaps_outer; - if (ws->layout == L_TABBED || ws->layout == L_STACKED) { // We have to add inner gaps for this, because children of tabbed and // stacked containers don't apply their own gaps - they assume the // tabbed/stacked container is using gaps. - ws->current_gaps += ws->gaps_inner; + ws->current_gaps.top += ws->gaps_inner; + ws->current_gaps.right += ws->gaps_inner; + ws->current_gaps.bottom += ws->gaps_inner; + ws->current_gaps.left += ws->gaps_inner; } - ws->x += ws->current_gaps; - ws->y += ws->current_gaps; - ws->width -= 2 * ws->current_gaps; - ws->height -= 2 * ws->current_gaps; + ws->x += ws->current_gaps.left; + ws->y += ws->current_gaps.top; + ws->width -= ws->current_gaps.left + ws->current_gaps.right; + ws->height -= ws->current_gaps.top + ws->current_gaps.bottom; } struct sway_container *workspace_split(struct sway_workspace *workspace, |