aboutsummaryrefslogtreecommitdiff
path: root/sway/tree
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree')
-rw-r--r--sway/tree/container.c37
-rw-r--r--sway/tree/output.c28
-rw-r--r--sway/tree/root.c15
-rw-r--r--sway/tree/view.c73
-rw-r--r--sway/tree/workspace.c79
5 files changed, 162 insertions, 70 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 9b671c1d..a069b177 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -593,7 +593,7 @@ void container_update_representation(struct sway_container *con) {
}
}
-size_t container_titlebar_height() {
+size_t container_titlebar_height(void) {
return config->font_height + TITLEBAR_V_PADDING * 2;
}
@@ -829,9 +829,16 @@ void container_floating_move_to_center(struct sway_container *con) {
return;
}
struct sway_workspace *ws = con->workspace;
+ bool full = con->is_fullscreen;
+ if (full) {
+ container_set_fullscreen(con, false);
+ }
double new_lx = ws->x + (ws->width - con->width) / 2;
double new_ly = ws->y + (ws->height - con->height) / 2;
container_floating_translate(con, new_lx - con->x, new_ly - con->y);
+ if (full) {
+ container_set_fullscreen(con, true);
+ }
}
static bool find_urgent_iterator(struct sway_container *con, void *data) {
@@ -1020,15 +1027,33 @@ void container_add_gaps(struct sway_container *c) {
if (!c->view && c->layout != L_TABBED && c->layout != L_STACKED) {
return;
}
- // Children of tabbed/stacked containers re-use the gaps of the container
- enum sway_container_layout layout = container_parent_layout(c);
- if (layout == L_TABBED || layout == L_STACKED) {
- return;
+ // Descendants of tabbed/stacked containers re-use the gaps of the container
+ struct sway_container *temp = c;
+ while (temp) {
+ enum sway_container_layout layout = container_parent_layout(temp);
+ if (layout == L_TABBED || layout == L_STACKED) {
+ return;
+ }
+ temp = temp->parent;
+ }
+ // If smart gaps is on, don't add gaps if there is only one view visible
+ if (config->smart_gaps) {
+ struct sway_view *view = c->view;
+ if (!view) {
+ struct sway_seat *seat =
+ input_manager_get_default_seat(input_manager);
+ struct sway_container *focus =
+ seat_get_focus_inactive_view(seat, &c->node);
+ view = focus ? focus->view : NULL;
+ }
+ if (view && view_is_only_visible(view)) {
+ return;
+ }
}
struct sway_workspace *ws = c->workspace;
- c->current_gaps = ws->has_gaps ? ws->gaps_inner : config->gaps_inner;
+ c->current_gaps = ws->gaps_inner;
c->x += c->current_gaps;
c->y += c->current_gaps;
c->width -= 2 * c->current_gaps;
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 06933dc4..c3176325 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -113,6 +113,20 @@ void output_enable(struct sway_output *output, struct output_config *oc) {
arrange_root();
}
+static void evacuate_sticky(struct sway_workspace *old_ws,
+ struct sway_output *new_output) {
+ struct sway_workspace *new_ws = output_get_active_workspace(new_output);
+ while (old_ws->floating->length) {
+ struct sway_container *sticky = old_ws->floating->items[0];
+ container_detach(sticky);
+ workspace_add_floating(new_ws, sticky);
+ container_handle_fullscreen_reparent(sticky);
+ container_floating_move_to_center(sticky);
+ ipc_event_window(sticky, "move");
+ }
+ workspace_detect_urgent(new_ws);
+}
+
static void output_evacuate(struct sway_output *output) {
if (!output->workspaces->length) {
return;
@@ -130,17 +144,21 @@ static void output_evacuate(struct sway_output *output) {
workspace_detach(workspace);
- if (workspace_is_empty(workspace)) {
- workspace_begin_destroy(workspace);
- continue;
- }
-
struct sway_output *new_output =
workspace_output_get_highest_available(workspace, output);
if (!new_output) {
new_output = fallback_output;
}
+ if (workspace_is_empty(workspace)) {
+ // If floating is not empty, there are sticky containers to move
+ if (workspace->floating->length) {
+ evacuate_sticky(workspace, new_output);
+ }
+ workspace_begin_destroy(workspace);
+ continue;
+ }
+
if (new_output) {
workspace_output_add_priority(workspace, new_output);
output_add_workspace(new_output, workspace);
diff --git a/sway/tree/root.c b/sway/tree/root.c
index d6f67bd7..6748e9c9 100644
--- a/sway/tree/root.c
+++ b/sway/tree/root.c
@@ -273,6 +273,12 @@ void root_for_each_container(void (*f)(struct sway_container *con, void *data),
container_for_each_child(container, f, data);
}
}
+
+ // Saved workspaces
+ for (int i = 0; i < root->saved_workspaces->length; ++i) {
+ struct sway_workspace *ws = root->saved_workspaces->items[i];
+ workspace_for_each_container(ws, f, data);
+ }
}
struct sway_output *root_find_output(
@@ -320,6 +326,15 @@ struct sway_container *root_find_container(
}
}
}
+
+ // Saved workspaces
+ for (int i = 0; i < root->saved_workspaces->length; ++i) {
+ struct sway_workspace *ws = root->saved_workspaces->items[i];
+ if ((result = workspace_find_container(ws, test, data))) {
+ return result;
+ }
+ }
+
return NULL;
}
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 9ffcf206..9c7c44e9 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -165,6 +165,34 @@ uint32_t view_configure(struct sway_view *view, double lx, double ly, int width,
return 0;
}
+bool view_is_only_visible(struct sway_view *view) {
+ bool only_view = true;
+ struct sway_container *con = view->container;
+ while (con) {
+ enum sway_container_layout layout = container_parent_layout(con);
+ if (layout != L_TABBED && layout != L_STACKED) {
+ list_t *siblings = container_get_siblings(con);
+ if (siblings && siblings->length > 1) {
+ only_view = false;
+ break;
+ }
+ }
+ con = con->parent;
+ }
+ return only_view;
+}
+
+static bool gaps_to_edge(struct sway_view *view) {
+ struct sway_container *con = view->container;
+ while (con) {
+ if (con->current_gaps > 0) {
+ return true;
+ }
+ con = con->parent;
+ }
+ return view->container->workspace->current_gaps > 0;
+}
+
void view_autoconfigure(struct sway_view *view) {
if (!view->container->workspace) {
// Hidden in the scratchpad
@@ -181,39 +209,28 @@ void view_autoconfigure(struct sway_view *view) {
}
struct sway_workspace *ws = view->container->workspace;
-
- bool other_views = false;
- if (config->hide_edge_borders == E_SMART) {
- struct sway_container *con = view->container;
- while (con) {
- enum sway_container_layout layout = container_parent_layout(con);
- if (layout != L_TABBED && layout != L_STACKED) {
- list_t *siblings = container_get_siblings(con);
- if (siblings && siblings->length > 1) {
- other_views = true;
- break;
- }
- }
- con = con->parent;
- }
- }
-
struct sway_container *con = view->container;
+ bool smart = config->hide_edge_borders == E_SMART ||
+ config->hide_edge_borders == E_SMART_NO_GAPS;
+ bool other_views = smart && !view_is_only_visible(view);
+ bool no_gaps = config->hide_edge_borders != E_SMART_NO_GAPS
+ || !gaps_to_edge(view);
+
view->border_top = view->border_bottom = true;
view->border_left = view->border_right = true;
if (config->hide_edge_borders == E_BOTH
|| config->hide_edge_borders == E_VERTICAL
- || (config->hide_edge_borders == E_SMART && !other_views)) {
- view->border_left = con->x != ws->x;
- int right_x = con->x + con->width;
+ || (smart && !other_views && no_gaps)) {
+ view->border_left = con->x - con->current_gaps != ws->x;
+ int right_x = con->x + con->width + con->current_gaps;
view->border_right = right_x != ws->x + ws->width;
}
if (config->hide_edge_borders == E_BOTH
|| config->hide_edge_borders == E_HORIZONTAL
- || (config->hide_edge_borders == E_SMART && !other_views)) {
- view->border_top = con->y != ws->y;
- int bottom_y = con->y + con->height;
+ || (smart && !other_views && no_gaps)) {
+ view->border_top = con->y - con->current_gaps != ws->y;
+ int bottom_y = con->y + con->height + con->current_gaps;
view->border_bottom = bottom_y != ws->y + ws->height;
}
@@ -1004,12 +1021,16 @@ bool view_is_visible(struct sway_view *view) {
floater = floater->parent;
}
bool is_sticky = container_is_floating(floater) && floater->is_sticky;
+ if (!is_sticky && !workspace_is_visible(workspace)) {
+ return false;
+ }
// Check view isn't in a tabbed or stacked container on an inactive tab
struct sway_seat *seat = input_manager_current_seat(input_manager);
struct sway_container *con = view->container;
while (con) {
enum sway_container_layout layout = container_parent_layout(con);
- if (layout == L_TABBED || layout == L_STACKED) {
+ if ((layout == L_TABBED || layout == L_STACKED)
+ && !container_is_floating(con)) {
struct sway_node *parent = con->parent ?
&con->parent->node : &con->workspace->node;
if (seat_get_active_tiling_child(seat, parent) != &con->node) {
@@ -1023,10 +1044,6 @@ bool view_is_visible(struct sway_view *view) {
!container_is_fullscreen_or_child(view->container)) {
return false;
}
- // Check the workspace is visible
- if (!is_sticky) {
- return workspace_is_visible(workspace);
- }
return true;
}
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index 16031e87..e9e5dfa2 100644
--- a/sway/tree/workspace.c
+++ b/sway/tree/workspace.c
@@ -20,17 +20,23 @@
#include "log.h"
#include "util.h"
+struct workspace_config *workspace_find_config(const char *ws_name) {
+ for (int i = 0; i < config->workspace_configs->length; ++i) {
+ struct workspace_config *wsc = config->workspace_configs->items[i];
+ if (strcmp(wsc->workspace, ws_name) == 0) {
+ return wsc;
+ }
+ }
+ return NULL;
+}
+
struct sway_output *workspace_get_initial_output(const char *name) {
- // Search for workspace<->output pair
- for (int i = 0; i < config->workspace_outputs->length; ++i) {
- struct workspace_output *wso = config->workspace_outputs->items[i];
- if (strcasecmp(wso->workspace, name) == 0) {
- // Find output to use if it exists
- struct sway_output *output = output_by_name(wso->output);
- if (output) {
- return output;
- }
- break;
+ // 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) {
+ return output;
}
}
// Otherwise put it on the focused output
@@ -62,6 +68,20 @@ struct sway_workspace *workspace_create(struct sway_output *output,
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 != -1) {
+ ws->gaps_outer = wsc->gaps_outer;
+ }
+ if (wsc->gaps_inner != -1) {
+ ws->gaps_inner = wsc->gaps_inner;
+ }
+ }
+ }
+
output_add_workspace(output, ws);
output_sort_workspaces(output);
@@ -121,17 +141,8 @@ void next_name_map(struct sway_container *ws, void *data) {
static bool workspace_valid_on_output(const char *output_name,
const char *ws_name) {
- int i;
- for (i = 0; i < config->workspace_outputs->length; ++i) {
- struct workspace_output *wso = config->workspace_outputs->items[i];
- if (strcasecmp(wso->workspace, ws_name) == 0) {
- if (strcasecmp(wso->output, output_name) != 0) {
- return false;
- }
- }
- }
-
- return true;
+ struct workspace_config *wsc = workspace_find_config(ws_name);
+ return !wsc || !wsc->output || strcmp(wsc->output, output_name) == 0;
}
static void workspace_name_from_binding(const struct sway_binding * binding,
@@ -231,13 +242,13 @@ char *workspace_next_name(const char *output_name) {
workspace_name_from_binding(mode->keycode_bindings->items[i],
output_name, &order, &target);
}
- for (int i = 0; i < config->workspace_outputs->length; ++i) {
+ for (int i = 0; i < config->workspace_configs->length; ++i) {
// Unlike with bindings, this does not guarantee order
- const struct workspace_output *wso = config->workspace_outputs->items[i];
- if (strcmp(wso->output, output_name) == 0
- && workspace_by_name(wso->workspace) == NULL) {
+ 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(wso->workspace);
+ target = strdup(wsc->workspace);
break;
}
}
@@ -629,19 +640,25 @@ void workspace_add_gaps(struct sway_workspace *ws) {
if (ws->current_gaps > 0) {
return;
}
- bool should_apply =
- config->edge_gaps || (config->smart_gaps && ws->tiling->length > 1);
- if (!should_apply) {
+ if (!config->edge_gaps) {
return;
}
+ if (config->smart_gaps) {
+ struct sway_seat *seat = input_manager_get_default_seat(input_manager);
+ struct sway_container *focus =
+ seat_get_focus_inactive_view(seat, &ws->node);
+ if (focus && focus->view && view_is_only_visible(focus->view)) {
+ return;
+ }
+ }
- ws->current_gaps = ws->has_gaps ? ws->gaps_outer : config->gaps_outer;
+ 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->has_gaps ? ws->gaps_inner : config->gaps_inner;
+ ws->current_gaps += ws->gaps_inner;
}
ws->x += ws->current_gaps;