aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Dwyer <ryandwyer1@gmail.com>2019-01-25 08:29:21 +1000
committerRyan Dwyer <ryandwyer1@gmail.com>2019-01-25 08:29:21 +1000
commit20aa8ee67dc528299dbc8735220a1c081c7ff9f6 (patch)
tree685de48be3db51fc01510ccf051e2b63a4655fba
parent75406bb93b96091d30e52922d0f319530fe65471 (diff)
Implement fullscreen global
-rw-r--r--include/sway/tree/container.h18
-rw-r--r--include/sway/tree/root.h2
-rw-r--r--sway/commands/focus.c26
-rw-r--r--sway/commands/fullscreen.c34
-rw-r--r--sway/commands/move.c44
-rw-r--r--sway/commands/split.c6
-rw-r--r--sway/commands/swap.c27
-rw-r--r--sway/commands/workspace.c5
-rw-r--r--sway/desktop/output.c30
-rw-r--r--sway/desktop/render.c10
-rw-r--r--sway/desktop/transaction.c2
-rw-r--r--sway/desktop/xdg_shell.c2
-rw-r--r--sway/desktop/xdg_shell_v6.c2
-rw-r--r--sway/desktop/xwayland.c2
-rw-r--r--sway/input/cursor.c12
-rw-r--r--sway/input/seat.c12
-rw-r--r--sway/ipc-json.c4
-rw-r--r--sway/sway.5.scd5
-rw-r--r--sway/tree/arrange.c16
-rw-r--r--sway/tree/container.c174
-rw-r--r--sway/tree/root.c5
-rw-r--r--sway/tree/view.c26
22 files changed, 332 insertions, 132 deletions
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index 9a432cb2..f0d0b3ce 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -25,6 +25,12 @@ enum sway_container_border {
B_CSD,
};
+enum sway_fullscreen_mode {
+ FULLSCREEN_NONE,
+ FULLSCREEN_WORKSPACE,
+ FULLSCREEN_GLOBAL,
+};
+
struct sway_root;
struct sway_output;
struct sway_workspace;
@@ -38,7 +44,7 @@ struct sway_container_state {
double x, y;
double width, height;
- bool is_fullscreen;
+ enum sway_fullscreen_mode fullscreen_mode;
struct sway_workspace *workspace;
struct sway_container *parent;
@@ -85,7 +91,7 @@ struct sway_container {
double content_x, content_y;
int content_width, content_height;
- bool is_fullscreen;
+ enum sway_fullscreen_mode fullscreen_mode;
enum sway_container_border border;
@@ -249,7 +255,13 @@ bool container_has_urgent_child(struct sway_container *container);
*/
void container_end_mouse_operation(struct sway_container *container);
-void container_set_fullscreen(struct sway_container *container, bool enable);
+void container_set_fullscreen(struct sway_container *con,
+ enum sway_fullscreen_mode mode);
+
+/**
+ * Convenience function.
+ */
+void container_fullscreen_disable(struct sway_container *con);
/**
* Return true if the container is floating, or a child of a floating split
diff --git a/include/sway/tree/root.h b/include/sway/tree/root.h
index 8f4deaa7..9ff45eb5 100644
--- a/include/sway/tree/root.h
+++ b/include/sway/tree/root.h
@@ -35,6 +35,8 @@ struct sway_root {
// For when there's no connected outputs
struct sway_output *noop_output;
+ struct sway_container *fullscreen_global;
+
struct {
struct wl_signal new_node;
} events;
diff --git a/sway/commands/focus.c b/sway/commands/focus.c
index 0622f2e8..87fe6cf3 100644
--- a/sway/commands/focus.c
+++ b/sway/commands/focus.c
@@ -89,19 +89,23 @@ static struct sway_node *get_node_in_output_direction(
static struct sway_node *node_get_in_direction(struct sway_container *container,
struct sway_seat *seat, enum wlr_direction dir) {
- if (container->is_fullscreen) {
- // Fullscreen container with a direction - go straight to outputs
- struct sway_output *output = container->workspace->output;
- struct sway_output *new_output = output_get_in_direction(output, dir);
- if (!new_output) {
- return NULL;
- }
- return get_node_in_output_direction(new_output, dir);
- }
-
struct sway_container *wrap_candidate = NULL;
struct sway_container *current = container;
while (current) {
+ if (current->fullscreen_mode == FULLSCREEN_WORKSPACE) {
+ // Fullscreen container with a direction - go straight to outputs
+ struct sway_output *output = current->workspace->output;
+ struct sway_output *new_output =
+ output_get_in_direction(output, dir);
+ if (!new_output) {
+ return NULL;
+ }
+ return get_node_in_output_direction(new_output, dir);
+ }
+ if (current->fullscreen_mode == FULLSCREEN_GLOBAL) {
+ return NULL;
+ }
+
bool can_move = false;
int desired;
int idx = container_sibling_index(current);
@@ -227,7 +231,7 @@ static struct cmd_results *focus_output(struct sway_seat *seat,
static struct cmd_results *focus_parent(void) {
struct sway_seat *seat = config->handler_context.seat;
struct sway_container *con = config->handler_context.container;
- if (!con || con->is_fullscreen) {
+ if (!con || con->fullscreen_mode) {
return cmd_results_new(CMD_SUCCESS, NULL);
}
struct sway_node *parent = node_get_parent(&con->node);
diff --git a/sway/commands/fullscreen.c b/sway/commands/fullscreen.c
index 920b9bd0..52248ce4 100644
--- a/sway/commands/fullscreen.c
+++ b/sway/commands/fullscreen.c
@@ -1,3 +1,4 @@
+#include <strings.h>
#include "log.h"
#include "sway/commands.h"
#include "sway/config.h"
@@ -7,9 +8,10 @@
#include "sway/tree/workspace.h"
#include "util.h"
+// fullscreen [enable|disable|toggle] [global]
struct cmd_results *cmd_fullscreen(int argc, char **argv) {
struct cmd_results *error = NULL;
- if ((error = checkarg(argc, "fullscreen", EXPECTED_AT_MOST, 1))) {
+ if ((error = checkarg(argc, "fullscreen", EXPECTED_AT_MOST, 2))) {
return error;
}
if (!root->outputs->length) {
@@ -23,20 +25,38 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) {
return cmd_results_new(CMD_FAILURE,
"Can't fullscreen an empty workspace");
}
- if (node->type == N_WORKSPACE) {
+
+ bool is_fullscreen = container &&
+ container->fullscreen_mode != FULLSCREEN_NONE;
+ bool global = false;
+ bool enable = !is_fullscreen;
+
+ if (argc >= 1) {
+ if (strcasecmp(argv[0], "global") == 0) {
+ global = true;
+ } else {
+ enable = parse_boolean(argv[0], is_fullscreen);
+ }
+ }
+
+ if (argc >= 2) {
+ global = strcasecmp(argv[1], "global") == 0;
+ }
+
+ if (enable && node->type == N_WORKSPACE) {
// Wrap the workspace's children in a container so we can fullscreen it
container = workspace_wrap_children(workspace);
workspace->layout = L_HORIZ;
seat_set_focus_container(config->handler_context.seat, container);
}
- bool enable = !container->is_fullscreen;
- if (argc) {
- enable = parse_boolean(argv[0], container->is_fullscreen);
+ enum sway_fullscreen_mode mode = FULLSCREEN_NONE;
+ if (enable) {
+ mode = global ? FULLSCREEN_GLOBAL : FULLSCREEN_WORKSPACE;
}
- container_set_fullscreen(container, enable);
- arrange_workspace(workspace);
+ container_set_fullscreen(container, mode);
+ arrange_root();
return cmd_results_new(CMD_SUCCESS, NULL);
}
diff --git a/sway/commands/move.c b/sway/commands/move.c
index acb5f44f..aa06b168 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -191,7 +191,7 @@ static void container_move_to_workspace(struct sway_container *container,
workspace_add_floating(workspace, container);
container_handle_fullscreen_reparent(container);
// If changing output, center it within the workspace
- if (old_output != workspace->output && !container->is_fullscreen) {
+ if (old_output != workspace->output && !container->fullscreen_mode) {
container_floating_move_to_center(container);
}
} else {
@@ -276,7 +276,7 @@ static void workspace_rejigger(struct sway_workspace *ws,
static bool container_move_in_direction(struct sway_container *container,
enum wlr_direction move_dir) {
// If moving a fullscreen view, only consider outputs
- if (container->is_fullscreen) {
+ if (container->fullscreen_mode == FULLSCREEN_WORKSPACE) {
struct sway_output *new_output =
output_get_in_direction(container->workspace->output, move_dir);
if (!new_output) {
@@ -286,6 +286,9 @@ static bool container_move_in_direction(struct sway_container *container,
container_move_to_workspace(container, ws);
return true;
}
+ if (container->fullscreen_mode == FULLSCREEN_GLOBAL) {
+ return false;
+ }
// If container is in a split container by itself, move out of the split
if (container->parent) {
@@ -309,13 +312,19 @@ static bool container_move_in_direction(struct sway_container *container,
int index = list_find(siblings, current);
int desired = index + offs;
+ // Don't allow containers to move out of their
+ // fullscreen or floating parent
+ if (current->fullscreen_mode || container_is_floating(current)) {
+ return false;
+ }
+
if (is_parallel(layout, move_dir)) {
if (desired == -1 || desired == siblings->length) {
if (current->parent == container->parent) {
current = current->parent;
continue;
} else {
- // Special case
+ // Reparenting
if (current->parent) {
container_insert_child(current->parent, container,
index + (offs < 0 ? 0 : 1));
@@ -334,13 +343,6 @@ static bool container_move_in_direction(struct sway_container *container,
}
current = current->parent;
-
- // Don't allow containers to move out of their
- // fullscreen or floating parent
- if (current &&
- (current->is_fullscreen || container_is_floating(current))) {
- return false;
- }
}
// Maybe rejigger the workspace
@@ -563,10 +565,14 @@ static struct cmd_results *cmd_move_container(int argc, char **argv) {
}
// arrange windows
- if (old_ws && !old_ws->node.destroying) {
- arrange_workspace(old_ws);
+ if (root->fullscreen_global) {
+ arrange_root();
+ } else {
+ if (old_ws && !old_ws->node.destroying) {
+ arrange_workspace(old_ws);
+ }
+ arrange_node(node_get_parent(destination));
}
- arrange_node(node_get_parent(destination));
return cmd_results_new(CMD_SUCCESS, NULL);
}
@@ -658,7 +664,7 @@ static struct cmd_results *cmd_move_in_direction(
"Cannot move a hidden scratchpad container");
}
if (container_is_floating(container)) {
- if (container->is_fullscreen) {
+ if (container->fullscreen_mode) {
return cmd_results_new(CMD_FAILURE,
"Cannot move fullscreen floating container");
}
@@ -690,9 +696,13 @@ static struct cmd_results *cmd_move_in_direction(
struct sway_workspace *new_ws = container->workspace;
- arrange_workspace(old_ws);
- if (new_ws != old_ws) {
- arrange_workspace(new_ws);
+ if (root->fullscreen_global) {
+ arrange_root();
+ } else {
+ arrange_workspace(old_ws);
+ if (new_ws != old_ws) {
+ arrange_workspace(new_ws);
+ }
}
if (container->view) {
diff --git a/sway/commands/split.c b/sway/commands/split.c
index 06b7df5e..b7ab7b79 100644
--- a/sway/commands/split.c
+++ b/sway/commands/split.c
@@ -26,7 +26,11 @@ static struct cmd_results *do_split(int layout) {
container_flatten(con->parent->parent);
}
- arrange_workspace(ws);
+ if (root->fullscreen_global) {
+ arrange_root();
+ } else {
+ arrange_workspace(ws);
+ }
return cmd_results_new(CMD_SUCCESS, NULL);
}
diff --git a/sway/commands/swap.c b/sway/commands/swap.c
index 0d8d1116..0e2c2d10 100644
--- a/sway/commands/swap.c
+++ b/sway/commands/swap.c
@@ -77,6 +77,11 @@ static void swap_focus(struct sway_container *con1,
} else {
seat_set_focus_container(seat, focus);
}
+
+ if (root->fullscreen_global) {
+ seat_set_focus(seat,
+ seat_get_focus_inactive(seat, &root->fullscreen_global->node));
+ }
}
static void container_swap(struct sway_container *con1,
@@ -98,13 +103,13 @@ static void container_swap(struct sway_container *con1,
sway_log(SWAY_DEBUG, "Swapping containers %zu and %zu",
con1->node.id, con2->node.id);
- bool fs1 = con1->is_fullscreen;
- bool fs2 = con2->is_fullscreen;
+ enum sway_fullscreen_mode fs1 = con1->fullscreen_mode;
+ enum sway_fullscreen_mode fs2 = con2->fullscreen_mode;
if (fs1) {
- container_set_fullscreen(con1, false);
+ container_fullscreen_disable(con1);
}
if (fs2) {
- container_set_fullscreen(con2, false);
+ container_fullscreen_disable(con2);
}
struct sway_seat *seat = config->handler_context.seat;
@@ -136,10 +141,10 @@ static void container_swap(struct sway_container *con1,
}
if (fs1) {
- container_set_fullscreen(con2, true);
+ container_set_fullscreen(con2, fs1);
}
if (fs2) {
- container_set_fullscreen(con1, true);
+ container_set_fullscreen(con1, fs2);
}
}
@@ -220,9 +225,13 @@ struct cmd_results *cmd_swap(int argc, char **argv) {
container_swap(current, other);
- arrange_node(node_get_parent(&current->node));
- if (node_get_parent(&other->node) != node_get_parent(&current->node)) {
- arrange_node(node_get_parent(&other->node));
+ if (root->fullscreen_global) {
+ arrange_root();
+ } else {
+ arrange_node(node_get_parent(&current->node));
+ if (node_get_parent(&other->node) != node_get_parent(&current->node)) {
+ arrange_node(node_get_parent(&other->node));
+ }
}
return cmd_results_new(CMD_SUCCESS, NULL);
diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c
index 6bfca506..c5d6435a 100644
--- a/sway/commands/workspace.c
+++ b/sway/commands/workspace.c
@@ -168,6 +168,11 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
"Can't run this command while there's no outputs connected.");
}
+ if (root->fullscreen_global) {
+ return cmd_results_new(CMD_FAILURE, "workspace",
+ "Can't switch workspaces while fullscreen global");
+ }
+
bool no_auto_back_and_forth = false;
while (strcasecmp(argv[0], "--no-auto-back-and-forth") == 0) {
no_auto_back_and_forth = true;
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index f18a118f..b5f164cb 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -251,17 +251,27 @@ static void output_for_each_surface(struct sway_output *output,
};
struct sway_workspace *workspace = output_get_active_workspace(output);
- if (workspace->current.fullscreen) {
- for_each_surface_container_iterator(
- workspace->current.fullscreen, &data);
- container_for_each_child(workspace->current.fullscreen,
+ struct sway_container *fullscreen_con = root->fullscreen_global;
+ if (fullscreen_con && fullscreen_con->scratchpad &&
+ !fullscreen_con->workspace) {
+ fullscreen_con = NULL;
+ }
+ if (!fullscreen_con) {
+ fullscreen_con = workspace->current.fullscreen;
+ }
+ if (fullscreen_con) {
+ for_each_surface_container_iterator(fullscreen_con, &data);
+ container_for_each_child(fullscreen_con,
for_each_surface_container_iterator, &data);
- for (int i = 0; i < workspace->current.floating->length; ++i) {
- struct sway_container *floater =
- workspace->current.floating->items[i];
- if (container_is_transient_for(floater,
- workspace->current.fullscreen)) {
- for_each_surface_container_iterator(floater, &data);
+
+ // TODO: Show transient containers for fullscreen global
+ if (fullscreen_con == workspace->current.fullscreen) {
+ for (int i = 0; i < workspace->current.floating->length; ++i) {
+ struct sway_container *floater =
+ workspace->current.floating->items[i];
+ if (container_is_transient_for(floater, fullscreen_con)) {
+ for_each_surface_container_iterator(floater, &data);
+ }
}
}
#if HAVE_XWAYLAND
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index a38c6a07..fa27500e 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -985,7 +985,15 @@ void output_render(struct sway_output *output, struct timespec *when,
goto render_overlay;
}
- struct sway_container *fullscreen_con = workspace->current.fullscreen;
+ struct sway_container *fullscreen_con = root->fullscreen_global;
+ if (fullscreen_con && fullscreen_con->scratchpad &&
+ !fullscreen_con->workspace) {
+ fullscreen_con = NULL;
+ }
+ if (!fullscreen_con) {
+ fullscreen_con = workspace->current.fullscreen;
+ }
+
if (fullscreen_con) {
float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c
index 55cf1c5e..b06ac9cc 100644
--- a/sway/desktop/transaction.c
+++ b/sway/desktop/transaction.c
@@ -134,7 +134,7 @@ static void copy_container_state(struct sway_container *container,
state->y = container->y;
state->width = container->width;
state->height = container->height;
- state->is_fullscreen = container->is_fullscreen;
+ state->fullscreen_mode = container->fullscreen_mode;
state->parent = container->parent;
state->workspace = container->workspace;
state->border = container->border;
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index e2c614b3..007b0a94 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -349,7 +349,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
container_set_fullscreen(view->container, e->fullscreen);
- arrange_workspace(view->container->workspace);
+ arrange_root();
transaction_commit_dirty();
}
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index f11c00b1..386e350e 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -342,7 +342,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
container_set_fullscreen(view->container, e->fullscreen);
- arrange_workspace(view->container->workspace);
+ arrange_root();
transaction_commit_dirty();
}
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 4ea661f8..d9e1b0a9 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -453,7 +453,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
}
container_set_fullscreen(view->container, xsurface->fullscreen);
- arrange_workspace(view->container->workspace);
+ arrange_root();
transaction_commit_dirty();
}
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index bf9bf2da..4b2d99e6 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -90,6 +90,16 @@ struct sway_node *node_at_coords(
double ox = lx, oy = ly;
wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy);
+ if (root->fullscreen_global) {
+ // Try fullscreen container
+ struct sway_container *con = tiling_container_at(
+ &root->fullscreen_global->node, lx, ly, surface, sx, sy);
+ if (con) {
+ return &con->node;
+ }
+ return NULL;
+ }
+
// find the focused workspace on the output for this seat
struct sway_workspace *ws = output_get_active_workspace(output);
@@ -659,7 +669,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
// Handle moving a tiling container
if (config->tiling_drag && (mod_pressed || on_titlebar) &&
state == WLR_BUTTON_PRESSED && !is_floating_or_child &&
- cont && !cont->is_fullscreen) {
+ cont && cont->fullscreen_mode == FULLSCREEN_NONE) {
struct sway_container *focus = seat_get_focused_container(seat);
bool focused = focus == cont || container_has_ancestor(focus, cont);
if (on_titlebar && !focused) {
diff --git a/sway/input/seat.c b/sway/input/seat.c
index fd5eda2d..f216810b 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -753,6 +753,18 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) {
return;
}
}
+ // Deny setting focus to a workspace node when using fullscreen global
+ if (root->fullscreen_global && !container && new_workspace) {
+ return;
+ }
+ // Deny setting focus to a view which is hidden by a fullscreen global
+ if (root->fullscreen_global && container != root->fullscreen_global &&
+ !container_has_ancestor(container, root->fullscreen_global)) {
+ // Unless it's a transient container
+ if (!container_is_transient_for(container, root->fullscreen_global)) {
+ return;
+ }
+ }
struct sway_output *new_output = new_workspace->output;
diff --git a/sway/ipc-json.c b/sway/ipc-json.c
index 778bf773..87d2c1ec 100644
--- a/sway/ipc-json.c
+++ b/sway/ipc-json.c
@@ -425,7 +425,9 @@ static void ipc_json_describe_container(struct sway_container *c, json_object *o
view_is_urgent(c->view) : container_has_urgent_child(c);
json_object_object_add(object, "urgent", json_object_new_boolean(urgent));
json_object_object_add(object, "sticky", json_object_new_boolean(c->is_sticky));
- json_object_object_add(object, "fullscreen_mode", json_object_new_int(c->is_fullscreen));
+
+ json_object_object_add(object, "fullscreen_mode",
+ json_object_new_int(c->fullscreen_mode));
struct sway_node *parent = node_get_parent(&c->node);
struct wlr_box parent_box = {0, 0, 0, 0};
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index 06bc0dbf..c2539804 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -134,9 +134,10 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1).
*focus* mode\_toggle
Moves focus between the floating and tiled layers.
-*fullscreen* [enable|disable|toggle]
+*fullscreen* [enable|disable|toggle] [global]
Makes focused view fullscreen, non-fullscreen, or the opposite of what it
- is now. If no argument is given, it does the same as _toggle_.
+ is now. If no argument is given, it does the same as _toggle_. If _global_
+ is specified, the view will be fullscreen across all outputs.
*gaps* inner|outer|horizontal|vertical|top|right|bottom|left all|current
set|plus|minus <amount>
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c
index f78d95a4..da372aa4 100644
--- a/sway/tree/arrange.c
+++ b/sway/tree/arrange.c
@@ -261,9 +261,19 @@ void arrange_root(void) {
root->y = layout_box->y;
root->width = layout_box->width;
root->height = layout_box->height;
- for (int i = 0; i < root->outputs->length; ++i) {
- struct sway_output *output = root->outputs->items[i];
- arrange_output(output);
+
+ if (root->fullscreen_global) {
+ struct sway_container *fs = root->fullscreen_global;
+ fs->x = root->x;
+ fs->y = root->y;
+ fs->width = root->width;
+ fs->height = root->height;
+ arrange_container(fs);
+ } else {
+ for (int i = 0; i < root->outputs->length; ++i) {
+ struct sway_output *output = root->outputs->items[i];
+ arrange_output(output);
+ }
}
}
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 0c0684c0..d8ad3bc0 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -92,7 +92,7 @@ void container_begin_destroy(struct sway_container *con) {
}
// The workspace must have the fullscreen pointer cleared so that the
// seat code can find an appropriate new focus.
- if (con->is_fullscreen && con->workspace) {
+ if (con->fullscreen_mode == FULLSCREEN_WORKSPACE && con->workspace) {
con->workspace->fullscreen = NULL;
}
wl_signal_emit(&con->node.events.destroy, &con->node);
@@ -106,6 +106,10 @@ void container_begin_destroy(struct sway_container *con) {
root_scratchpad_remove_container(con);
}
+ if (con->fullscreen_mode == FULLSCREEN_GLOBAL) {
+ container_fullscreen_disable(con);
+ }
+
if (con->parent || con->workspace) {
container_detach(con);
}
@@ -840,15 +844,15 @@ 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);
+ enum sway_fullscreen_mode fullscreen_mode = con->fullscreen_mode;
+ if (fullscreen_mode) {
+ container_fullscreen_disable(con);
}
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);
+ if (fullscreen_mode) {
+ container_set_fullscreen(con, fullscreen_mode);
}
}
@@ -877,59 +881,125 @@ static void set_fullscreen_iterator(struct sway_container *con, void *data) {
}
}
-void container_set_fullscreen(struct sway_container *container, bool enable) {
- if (container->is_fullscreen == enable) {
+static void container_fullscreen_workspace(struct sway_container *con) {
+ if (!sway_assert(con->fullscreen_mode == FULLSCREEN_NONE,
+ "Expected a non-fullscreen container")) {
return;
}
+ bool enable = true;
+ set_fullscreen_iterator(con, &enable);
+ container_for_each_child(con, set_fullscreen_iterator, &enable);
- struct sway_workspace *workspace = container->workspace;
- if (enable && workspace->fullscreen) {
- container_set_fullscreen(workspace->fullscreen, false);
+ con->workspace->fullscreen = con;
+ con->saved_x = con->x;
+ con->saved_y = con->y;
+ con->saved_width = con->width;
+ con->saved_height = con->height;
+
+ struct sway_seat *seat;
+ struct sway_workspace *focus_ws;
+ wl_list_for_each(seat, &server.input->seats, link) {
+ focus_ws = seat_get_focused_workspace(seat);
+ if (focus_ws == con->workspace) {
+ seat_set_focus_container(seat, con);
+ }
}
- set_fullscreen_iterator(container, &enable);
- container_for_each_child(container, set_fullscreen_iterator, &enable);
+ con->fullscreen_mode = FULLSCREEN_WORKSPACE;
+ container_end_mouse_operation(con);
+ ipc_event_window(con, "fullscreen_mode");
+}
+
+static void container_fullscreen_global(struct sway_container *con) {
+ if (!sway_assert(con->fullscreen_mode == FULLSCREEN_NONE,
+ "Expected a non-fullscreen container")) {
+ return;
+ }
+ bool enable = true;
+ set_fullscreen_iterator(con, &enable);
+ container_for_each_child(con, set_fullscreen_iterator, &enable);
- container->is_fullscreen = enable;
+ root->fullscreen_global = con;
+ con->saved_x = con->x;
+ con->saved_y = con->y;
+ con->saved_width = con->width;
+ con->saved_height = con->height;
- if (enable) {
- workspace->fullscreen = container;
- container->saved_x = container->x;
- container->saved_y = container->y;
- container->saved_width = container->width;
- container->saved_height = container->height;
-
- struct sway_seat *seat;
- struct sway_workspace *focus_ws;
- wl_list_for_each(seat, &server.input->seats, link) {
- focus_ws = seat_get_focused_workspace(seat);
- if (focus_ws) {
- if (focus_ws == workspace) {
- seat_set_focus_container(seat, container);
- }
- }
+ struct sway_seat *seat;
+ wl_list_for_each(seat, &server.input->seats, link) {
+ struct sway_container *focus = seat_get_focused_container(seat);
+ if (focus && focus != con) {
+ seat_set_focus_container(seat, con);
}
- } else {
- workspace->fullscreen = NULL;
- if (container_is_floating(container)) {
- container->x = container->saved_x;
- container->y = container->saved_y;
- container->width = container->saved_width;
- container->height = container->saved_height;
- struct sway_output *output =
- container_floating_find_output(container);
- if (workspace->output != output) {
- container_floating_move_to_center(container);
+ }
+
+ con->fullscreen_mode = FULLSCREEN_GLOBAL;
+ container_end_mouse_operation(con);
+ ipc_event_window(con, "fullscreen_mode");
+}
+
+void container_fullscreen_disable(struct sway_container *con) {
+ if (!sway_assert(con->fullscreen_mode != FULLSCREEN_NONE,
+ "Expected a fullscreen container")) {
+ return;
+ }
+ bool enable = false;
+ set_fullscreen_iterator(con, &enable);
+ container_for_each_child(con, set_fullscreen_iterator, &enable);
+
+ if (container_is_floating(con)) {
+ con->x = con->saved_x;
+ con->y = con->saved_y;
+ }
+ con->width = con->saved_width;
+ con->height = con->saved_height;
+
+ if (con->fullscreen_mode == FULLSCREEN_WORKSPACE) {
+ con->workspace->fullscreen = NULL;
+ if (container_is_floating(con)) {
+ struct sway_output *output = container_floating_find_output(con);
+ if (con->workspace->output != output) {
+ container_floating_move_to_center(con);
}
- } else {
- container->width = container->saved_width;
- container->height = container->saved_height;
}
+ } else {
+ root->fullscreen_global = NULL;
}
- container_end_mouse_operation(container);
+ con->fullscreen_mode = FULLSCREEN_NONE;
+ container_end_mouse_operation(con);
+ ipc_event_window(con, "fullscreen_mode");
+}
+
+void container_set_fullscreen(struct sway_container *con,
+ enum sway_fullscreen_mode mode) {
+ if (con->fullscreen_mode == mode) {
+ return;
+ }
- ipc_event_window(container, "fullscreen_mode");
+ switch (mode) {
+ case FULLSCREEN_NONE:
+ container_fullscreen_disable(con);
+ break;
+ case FULLSCREEN_WORKSPACE:
+ if (root->fullscreen_global) {
+ container_fullscreen_disable(root->fullscreen_global);
+ }
+ if (con->workspace->fullscreen) {
+ container_fullscreen_disable(con->workspace->fullscreen);
+ }
+ container_fullscreen_workspace(con);
+ break;
+ case FULLSCREEN_GLOBAL:
+ if (root->fullscreen_global) {
+ container_fullscreen_disable(root->fullscreen_global);
+ }
+ if (con->fullscreen_mode == FULLSCREEN_WORKSPACE) {
+ container_fullscreen_disable(con);
+ }
+ container_fullscreen_global(con);
+ break;
+ }
}
bool container_is_floating_or_child(struct sway_container *container) {
@@ -941,7 +1011,7 @@ bool container_is_floating_or_child(struct sway_container *container) {
bool container_is_fullscreen_or_child(struct sway_container *container) {
do {
- if (container->is_fullscreen) {
+ if (container->fullscreen_mode) {
return true;
}
container = container->parent;
@@ -1111,12 +1181,12 @@ list_t *container_get_current_siblings(struct sway_container *container) {
}
void container_handle_fullscreen_reparent(struct sway_container *con) {
- if (!con->is_fullscreen || !con->workspace ||
+ if (con->fullscreen_mode != FULLSCREEN_WORKSPACE || !con->workspace ||
con->workspace->fullscreen == con) {
return;
}
if (con->workspace->fullscreen) {
- container_set_fullscreen(con->workspace->fullscreen, false);
+ container_fullscreen_disable(con->workspace->fullscreen);
}
con->workspace->fullscreen = con;
@@ -1171,9 +1241,12 @@ void container_add_child(struct sway_container *parent,
}
void container_detach(struct sway_container *child) {
- if (child->is_fullscreen) {
+ if (child->fullscreen_mode == FULLSCREEN_WORKSPACE) {
child->workspace->fullscreen = NULL;
}
+ if (child->fullscreen_mode == FULLSCREEN_GLOBAL) {
+ root->fullscreen_global = NULL;
+ }
struct sway_container *old_parent = child->parent;
struct sway_workspace *old_workspace = child->workspace;
@@ -1387,4 +1460,3 @@ void container_raise_floating(struct sway_container *con) {
node_set_dirty(&floater->workspace->node);
}
}
-
diff --git a/sway/tree/root.c b/sway/tree/root.c
index 99cf91a7..476e47a3 100644
--- a/sway/tree/root.c
+++ b/sway/tree/root.c
@@ -101,7 +101,10 @@ void root_scratchpad_show(struct sway_container *con) {
// If the current con or any of its parents are in fullscreen mode, we
// first need to disable it before showing the scratchpad con.
if (new_ws->fullscreen) {
- container_set_fullscreen(new_ws->fullscreen, false);
+ container_fullscreen_disable(new_ws->fullscreen);
+ }
+ if (root->fullscreen_global) {
+ container_fullscreen_disable(root->fullscreen_global);
}
// Show the container
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 8795e04f..561c6ef1 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -203,12 +203,18 @@ void view_autoconfigure(struct sway_view *view) {
}
struct sway_output *output = con->workspace->output;
- if (con->is_fullscreen) {
+ if (con->fullscreen_mode == FULLSCREEN_WORKSPACE) {
con->content_x = output->lx;
con->content_y = output->ly;
con->content_width = output->width;
con->content_height = output->height;
return;
+ } else if (con->fullscreen_mode == FULLSCREEN_GLOBAL) {
+ con->content_x = root->x;
+ con->content_y = root->y;
+ con->content_width = root->width;
+ con->content_height = root->height;
+ return;
}
struct sway_workspace *ws = view->container->workspace;
@@ -648,7 +654,10 @@ void view_unmap(struct sway_view *view) {
workspace_consider_destroy(ws);
}
- if (ws && !ws->node.destroying) {
+ if (root->fullscreen_global) {
+ // Container may have been a child of the root fullscreen container
+ arrange_root();
+ } else if (ws && !ws->node.destroying) {
arrange_workspace(ws);
workspace_detect_urgent(ws);
}
@@ -1008,14 +1017,11 @@ bool view_is_visible(struct sway_view *view) {
con = con->parent;
}
// Check view isn't hidden by another fullscreen view
- if (workspace->fullscreen &&
- !container_is_fullscreen_or_child(view->container)) {
- // However, if we're transient for the fullscreen view and we allow
- // "popups" during fullscreen then it might be visible
- if (!container_is_transient_for(view->container,
- workspace->fullscreen)) {
- return false;
- }
+ struct sway_container *fs = root->fullscreen_global ?
+ root->fullscreen_global : workspace->fullscreen;
+ if (fs && !container_is_fullscreen_or_child(view->container) &&
+ !container_is_transient_for(view->container, fs)) {
+ return false;
}
return true;
}