aboutsummaryrefslogtreecommitdiff
path: root/sway/tree
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree')
-rw-r--r--sway/tree/container.c80
-rw-r--r--sway/tree/output.c7
-rw-r--r--sway/tree/root.c2
-rw-r--r--sway/tree/view.c61
-rw-r--r--sway/tree/workspace.c126
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,