mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Merge pull request #3423 from RyanDwyer/fullscreen-global
Implement fullscreen global
This commit is contained in:
		
						commit
						783fadab28
					
				
					 22 changed files with 331 additions and 131 deletions
				
			
		| 
						 | 
					@ -25,6 +25,12 @@ enum sway_container_border {
 | 
				
			||||||
	B_CSD,
 | 
						B_CSD,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum sway_fullscreen_mode {
 | 
				
			||||||
 | 
						FULLSCREEN_NONE,
 | 
				
			||||||
 | 
						FULLSCREEN_WORKSPACE,
 | 
				
			||||||
 | 
						FULLSCREEN_GLOBAL,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sway_root;
 | 
					struct sway_root;
 | 
				
			||||||
struct sway_output;
 | 
					struct sway_output;
 | 
				
			||||||
struct sway_workspace;
 | 
					struct sway_workspace;
 | 
				
			||||||
| 
						 | 
					@ -38,7 +44,7 @@ struct sway_container_state {
 | 
				
			||||||
	double x, y;
 | 
						double x, y;
 | 
				
			||||||
	double width, height;
 | 
						double width, height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool is_fullscreen;
 | 
						enum sway_fullscreen_mode fullscreen_mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct sway_workspace *workspace;
 | 
						struct sway_workspace *workspace;
 | 
				
			||||||
	struct sway_container *parent;
 | 
						struct sway_container *parent;
 | 
				
			||||||
| 
						 | 
					@ -85,7 +91,7 @@ struct sway_container {
 | 
				
			||||||
	double content_x, content_y;
 | 
						double content_x, content_y;
 | 
				
			||||||
	int content_width, content_height;
 | 
						int content_width, content_height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool is_fullscreen;
 | 
						enum sway_fullscreen_mode fullscreen_mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	enum sway_container_border border;
 | 
						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_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
 | 
					 * Return true if the container is floating, or a child of a floating split
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,6 +35,8 @@ struct sway_root {
 | 
				
			||||||
	// For when there's no connected outputs
 | 
						// For when there's no connected outputs
 | 
				
			||||||
	struct sway_output *noop_output;
 | 
						struct sway_output *noop_output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct sway_container *fullscreen_global;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct {
 | 
						struct {
 | 
				
			||||||
		struct wl_signal new_node;
 | 
							struct wl_signal new_node;
 | 
				
			||||||
	} events;
 | 
						} events;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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,
 | 
					static struct sway_node *node_get_in_direction(struct sway_container *container,
 | 
				
			||||||
		struct sway_seat *seat, enum wlr_direction dir) {
 | 
							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 *wrap_candidate = NULL;
 | 
				
			||||||
	struct sway_container *current = container;
 | 
						struct sway_container *current = container;
 | 
				
			||||||
	while (current) {
 | 
						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;
 | 
							bool can_move = false;
 | 
				
			||||||
		int desired;
 | 
							int desired;
 | 
				
			||||||
		int idx = container_sibling_index(current);
 | 
							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) {
 | 
					static struct cmd_results *focus_parent(void) {
 | 
				
			||||||
	struct sway_seat *seat = config->handler_context.seat;
 | 
						struct sway_seat *seat = config->handler_context.seat;
 | 
				
			||||||
	struct sway_container *con = config->handler_context.container;
 | 
						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);
 | 
							return cmd_results_new(CMD_SUCCESS, NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	struct sway_node *parent = node_get_parent(&con->node);
 | 
						struct sway_node *parent = node_get_parent(&con->node);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,4 @@
 | 
				
			||||||
 | 
					#include <strings.h>
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
#include "sway/commands.h"
 | 
					#include "sway/commands.h"
 | 
				
			||||||
#include "sway/config.h"
 | 
					#include "sway/config.h"
 | 
				
			||||||
| 
						 | 
					@ -7,9 +8,10 @@
 | 
				
			||||||
#include "sway/tree/workspace.h"
 | 
					#include "sway/tree/workspace.h"
 | 
				
			||||||
#include "util.h"
 | 
					#include "util.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// fullscreen [enable|disable|toggle] [global]
 | 
				
			||||||
struct cmd_results *cmd_fullscreen(int argc, char **argv) {
 | 
					struct cmd_results *cmd_fullscreen(int argc, char **argv) {
 | 
				
			||||||
	struct cmd_results *error = NULL;
 | 
						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;
 | 
							return error;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (!root->outputs->length) {
 | 
						if (!root->outputs->length) {
 | 
				
			||||||
| 
						 | 
					@ -23,20 +25,38 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) {
 | 
				
			||||||
		return cmd_results_new(CMD_FAILURE,
 | 
							return cmd_results_new(CMD_FAILURE,
 | 
				
			||||||
				"Can't fullscreen an empty workspace");
 | 
									"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
 | 
							// Wrap the workspace's children in a container so we can fullscreen it
 | 
				
			||||||
		container = workspace_wrap_children(workspace);
 | 
							container = workspace_wrap_children(workspace);
 | 
				
			||||||
		workspace->layout = L_HORIZ;
 | 
							workspace->layout = L_HORIZ;
 | 
				
			||||||
		seat_set_focus_container(config->handler_context.seat, container);
 | 
							seat_set_focus_container(config->handler_context.seat, container);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	bool enable = !container->is_fullscreen;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (argc) {
 | 
						enum sway_fullscreen_mode mode = FULLSCREEN_NONE;
 | 
				
			||||||
		enable = parse_boolean(argv[0], container->is_fullscreen);
 | 
						if (enable) {
 | 
				
			||||||
 | 
							mode = global ? FULLSCREEN_GLOBAL : FULLSCREEN_WORKSPACE;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	container_set_fullscreen(container, enable);
 | 
						container_set_fullscreen(container, mode);
 | 
				
			||||||
	arrange_workspace(workspace);
 | 
						arrange_root();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cmd_results_new(CMD_SUCCESS, NULL);
 | 
						return cmd_results_new(CMD_SUCCESS, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -191,7 +191,7 @@ static void container_move_to_workspace(struct sway_container *container,
 | 
				
			||||||
		workspace_add_floating(workspace, container);
 | 
							workspace_add_floating(workspace, container);
 | 
				
			||||||
		container_handle_fullscreen_reparent(container);
 | 
							container_handle_fullscreen_reparent(container);
 | 
				
			||||||
		// If changing output, center it within the workspace
 | 
							// 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);
 | 
								container_floating_move_to_center(container);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -276,7 +276,7 @@ static void workspace_rejigger(struct sway_workspace *ws,
 | 
				
			||||||
static bool container_move_in_direction(struct sway_container *container,
 | 
					static bool container_move_in_direction(struct sway_container *container,
 | 
				
			||||||
		enum wlr_direction move_dir) {
 | 
							enum wlr_direction move_dir) {
 | 
				
			||||||
	// If moving a fullscreen view, only consider outputs
 | 
						// If moving a fullscreen view, only consider outputs
 | 
				
			||||||
	if (container->is_fullscreen) {
 | 
						if (container->fullscreen_mode == FULLSCREEN_WORKSPACE) {
 | 
				
			||||||
		struct sway_output *new_output =
 | 
							struct sway_output *new_output =
 | 
				
			||||||
			output_get_in_direction(container->workspace->output, move_dir);
 | 
								output_get_in_direction(container->workspace->output, move_dir);
 | 
				
			||||||
		if (!new_output) {
 | 
							if (!new_output) {
 | 
				
			||||||
| 
						 | 
					@ -286,6 +286,9 @@ static bool container_move_in_direction(struct sway_container *container,
 | 
				
			||||||
		container_move_to_workspace(container, ws);
 | 
							container_move_to_workspace(container, ws);
 | 
				
			||||||
		return true;
 | 
							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 is in a split container by itself, move out of the split
 | 
				
			||||||
	if (container->parent) {
 | 
						if (container->parent) {
 | 
				
			||||||
| 
						 | 
					@ -309,13 +312,19 @@ static bool container_move_in_direction(struct sway_container *container,
 | 
				
			||||||
		int index = list_find(siblings, current);
 | 
							int index = list_find(siblings, current);
 | 
				
			||||||
		int desired = index + offs;
 | 
							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 (is_parallel(layout, move_dir)) {
 | 
				
			||||||
			if (desired == -1 || desired == siblings->length) {
 | 
								if (desired == -1 || desired == siblings->length) {
 | 
				
			||||||
				if (current->parent == container->parent) {
 | 
									if (current->parent == container->parent) {
 | 
				
			||||||
					current = current->parent;
 | 
										current = current->parent;
 | 
				
			||||||
					continue;
 | 
										continue;
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					// Special case
 | 
										// Reparenting
 | 
				
			||||||
					if (current->parent) {
 | 
										if (current->parent) {
 | 
				
			||||||
						container_insert_child(current->parent, container,
 | 
											container_insert_child(current->parent, container,
 | 
				
			||||||
								index + (offs < 0 ? 0 : 1));
 | 
													index + (offs < 0 ? 0 : 1));
 | 
				
			||||||
| 
						 | 
					@ -334,13 +343,6 @@ static bool container_move_in_direction(struct sway_container *container,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		current = current->parent;
 | 
							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
 | 
						// Maybe rejigger the workspace
 | 
				
			||||||
| 
						 | 
					@ -563,10 +565,14 @@ static struct cmd_results *cmd_move_container(int argc, char **argv) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// arrange windows
 | 
						// arrange windows
 | 
				
			||||||
	if (old_ws && !old_ws->node.destroying) {
 | 
						if (root->fullscreen_global) {
 | 
				
			||||||
		arrange_workspace(old_ws);
 | 
							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);
 | 
						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");
 | 
									"Cannot move a hidden scratchpad container");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (container_is_floating(container)) {
 | 
						if (container_is_floating(container)) {
 | 
				
			||||||
		if (container->is_fullscreen) {
 | 
							if (container->fullscreen_mode) {
 | 
				
			||||||
			return cmd_results_new(CMD_FAILURE,
 | 
								return cmd_results_new(CMD_FAILURE,
 | 
				
			||||||
					"Cannot move fullscreen floating container");
 | 
										"Cannot move fullscreen floating container");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -690,9 +696,13 @@ static struct cmd_results *cmd_move_in_direction(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct sway_workspace *new_ws = container->workspace;
 | 
						struct sway_workspace *new_ws = container->workspace;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	arrange_workspace(old_ws);
 | 
						if (root->fullscreen_global) {
 | 
				
			||||||
	if (new_ws != old_ws) {
 | 
							arrange_root();
 | 
				
			||||||
		arrange_workspace(new_ws);
 | 
						} else {
 | 
				
			||||||
 | 
							arrange_workspace(old_ws);
 | 
				
			||||||
 | 
							if (new_ws != old_ws) {
 | 
				
			||||||
 | 
								arrange_workspace(new_ws);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (container->view) {
 | 
						if (container->view) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,11 @@ static struct cmd_results *do_split(int layout) {
 | 
				
			||||||
		container_flatten(con->parent->parent);
 | 
							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);
 | 
						return cmd_results_new(CMD_SUCCESS, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,6 +77,11 @@ static void swap_focus(struct sway_container *con1,
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		seat_set_focus_container(seat, focus);
 | 
							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,
 | 
					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",
 | 
						sway_log(SWAY_DEBUG, "Swapping containers %zu and %zu",
 | 
				
			||||||
			con1->node.id, con2->node.id);
 | 
								con1->node.id, con2->node.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool fs1 = con1->is_fullscreen;
 | 
						enum sway_fullscreen_mode fs1 = con1->fullscreen_mode;
 | 
				
			||||||
	bool fs2 = con2->is_fullscreen;
 | 
						enum sway_fullscreen_mode fs2 = con2->fullscreen_mode;
 | 
				
			||||||
	if (fs1) {
 | 
						if (fs1) {
 | 
				
			||||||
		container_set_fullscreen(con1, false);
 | 
							container_fullscreen_disable(con1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (fs2) {
 | 
						if (fs2) {
 | 
				
			||||||
		container_set_fullscreen(con2, false);
 | 
							container_fullscreen_disable(con2);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct sway_seat *seat = config->handler_context.seat;
 | 
						struct sway_seat *seat = config->handler_context.seat;
 | 
				
			||||||
| 
						 | 
					@ -136,10 +141,10 @@ static void container_swap(struct sway_container *con1,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fs1) {
 | 
						if (fs1) {
 | 
				
			||||||
		container_set_fullscreen(con2, true);
 | 
							container_set_fullscreen(con2, fs1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (fs2) {
 | 
						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);
 | 
						container_swap(current, other);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	arrange_node(node_get_parent(¤t->node));
 | 
						if (root->fullscreen_global) {
 | 
				
			||||||
	if (node_get_parent(&other->node) != node_get_parent(¤t->node)) {
 | 
							arrange_root();
 | 
				
			||||||
		arrange_node(node_get_parent(&other->node));
 | 
						} else {
 | 
				
			||||||
 | 
							arrange_node(node_get_parent(¤t->node));
 | 
				
			||||||
 | 
							if (node_get_parent(&other->node) != node_get_parent(¤t->node)) {
 | 
				
			||||||
 | 
								arrange_node(node_get_parent(&other->node));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cmd_results_new(CMD_SUCCESS, NULL);
 | 
						return cmd_results_new(CMD_SUCCESS, NULL);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -168,6 +168,11 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
 | 
				
			||||||
					"Can't run this command while there's no outputs connected.");
 | 
										"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;
 | 
							bool no_auto_back_and_forth = false;
 | 
				
			||||||
		while (strcasecmp(argv[0], "--no-auto-back-and-forth") == 0) {
 | 
							while (strcasecmp(argv[0], "--no-auto-back-and-forth") == 0) {
 | 
				
			||||||
			no_auto_back_and_forth = true;
 | 
								no_auto_back_and_forth = true;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -251,17 +251,27 @@ static void output_for_each_surface(struct sway_output *output,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct sway_workspace *workspace = output_get_active_workspace(output);
 | 
						struct sway_workspace *workspace = output_get_active_workspace(output);
 | 
				
			||||||
	if (workspace->current.fullscreen) {
 | 
						struct sway_container *fullscreen_con = root->fullscreen_global;
 | 
				
			||||||
		for_each_surface_container_iterator(
 | 
						if (fullscreen_con && fullscreen_con->scratchpad &&
 | 
				
			||||||
			workspace->current.fullscreen, &data);
 | 
								!fullscreen_con->workspace) {
 | 
				
			||||||
		container_for_each_child(workspace->current.fullscreen,
 | 
							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_each_surface_container_iterator, &data);
 | 
				
			||||||
		for (int i = 0; i < workspace->current.floating->length; ++i) {
 | 
					
 | 
				
			||||||
			struct sway_container *floater =
 | 
							// TODO: Show transient containers for fullscreen global
 | 
				
			||||||
				workspace->current.floating->items[i];
 | 
							if (fullscreen_con == workspace->current.fullscreen) {
 | 
				
			||||||
			if (container_is_transient_for(floater,
 | 
								for (int i = 0; i < workspace->current.floating->length; ++i) {
 | 
				
			||||||
					workspace->current.fullscreen)) {
 | 
									struct sway_container *floater =
 | 
				
			||||||
				for_each_surface_container_iterator(floater, &data);
 | 
										workspace->current.floating->items[i];
 | 
				
			||||||
 | 
									if (container_is_transient_for(floater, fullscreen_con)) {
 | 
				
			||||||
 | 
										for_each_surface_container_iterator(floater, &data);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
#if HAVE_XWAYLAND
 | 
					#if HAVE_XWAYLAND
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -985,7 +985,15 @@ void output_render(struct sway_output *output, struct timespec *when,
 | 
				
			||||||
		goto render_overlay;
 | 
							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) {
 | 
						if (fullscreen_con) {
 | 
				
			||||||
		float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
 | 
							float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,7 +132,7 @@ static void copy_container_state(struct sway_container *container,
 | 
				
			||||||
	state->y = container->y;
 | 
						state->y = container->y;
 | 
				
			||||||
	state->width = container->width;
 | 
						state->width = container->width;
 | 
				
			||||||
	state->height = container->height;
 | 
						state->height = container->height;
 | 
				
			||||||
	state->is_fullscreen = container->is_fullscreen;
 | 
						state->fullscreen_mode = container->fullscreen_mode;
 | 
				
			||||||
	state->parent = container->parent;
 | 
						state->parent = container->parent;
 | 
				
			||||||
	state->workspace = container->workspace;
 | 
						state->workspace = container->workspace;
 | 
				
			||||||
	state->border = container->border;
 | 
						state->border = container->border;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -349,7 +349,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	container_set_fullscreen(view->container, e->fullscreen);
 | 
						container_set_fullscreen(view->container, e->fullscreen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	arrange_workspace(view->container->workspace);
 | 
						arrange_root();
 | 
				
			||||||
	transaction_commit_dirty();
 | 
						transaction_commit_dirty();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -342,7 +342,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	container_set_fullscreen(view->container, e->fullscreen);
 | 
						container_set_fullscreen(view->container, e->fullscreen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	arrange_workspace(view->container->workspace);
 | 
						arrange_root();
 | 
				
			||||||
	transaction_commit_dirty();
 | 
						transaction_commit_dirty();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -453,7 +453,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	container_set_fullscreen(view->container, xsurface->fullscreen);
 | 
						container_set_fullscreen(view->container, xsurface->fullscreen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	arrange_workspace(view->container->workspace);
 | 
						arrange_root();
 | 
				
			||||||
	transaction_commit_dirty();
 | 
						transaction_commit_dirty();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -90,6 +90,16 @@ struct sway_node *node_at_coords(
 | 
				
			||||||
	double ox = lx, oy = ly;
 | 
						double ox = lx, oy = ly;
 | 
				
			||||||
	wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy);
 | 
						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
 | 
						// find the focused workspace on the output for this seat
 | 
				
			||||||
	struct sway_workspace *ws = output_get_active_workspace(output);
 | 
						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
 | 
						// Handle moving a tiling container
 | 
				
			||||||
	if (config->tiling_drag && (mod_pressed || on_titlebar) &&
 | 
						if (config->tiling_drag && (mod_pressed || on_titlebar) &&
 | 
				
			||||||
			state == WLR_BUTTON_PRESSED && !is_floating_or_child &&
 | 
								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);
 | 
							struct sway_container *focus = seat_get_focused_container(seat);
 | 
				
			||||||
		bool focused = focus == cont || container_has_ancestor(focus, cont);
 | 
							bool focused = focus == cont || container_has_ancestor(focus, cont);
 | 
				
			||||||
		if (on_titlebar && !focused) {
 | 
							if (on_titlebar && !focused) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -752,6 +752,18 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) {
 | 
				
			||||||
			return;
 | 
								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;
 | 
						struct sway_output *new_output = new_workspace->output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
							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, "urgent", json_object_new_boolean(urgent));
 | 
				
			||||||
	json_object_object_add(object, "sticky", json_object_new_boolean(c->is_sticky));
 | 
						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 sway_node *parent = node_get_parent(&c->node);
 | 
				
			||||||
	struct wlr_box parent_box = {0, 0, 0, 0};
 | 
						struct wlr_box parent_box = {0, 0, 0, 0};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -134,9 +134,10 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1).
 | 
				
			||||||
*focus* mode_toggle
 | 
					*focus* mode_toggle
 | 
				
			||||||
	Moves focus between the floating and tiled layers.
 | 
						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
 | 
						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
 | 
					*gaps* inner|outer|horizontal|vertical|top|right|bottom|left all|current
 | 
				
			||||||
set|plus|minus <amount>
 | 
					set|plus|minus <amount>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -261,9 +261,19 @@ void arrange_root(void) {
 | 
				
			||||||
	root->y = layout_box->y;
 | 
						root->y = layout_box->y;
 | 
				
			||||||
	root->width = layout_box->width;
 | 
						root->width = layout_box->width;
 | 
				
			||||||
	root->height = layout_box->height;
 | 
						root->height = layout_box->height;
 | 
				
			||||||
	for (int i = 0; i < root->outputs->length; ++i) {
 | 
					
 | 
				
			||||||
		struct sway_output *output = root->outputs->items[i];
 | 
						if (root->fullscreen_global) {
 | 
				
			||||||
		arrange_output(output);
 | 
							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);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,7 +92,7 @@ void container_begin_destroy(struct sway_container *con) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// The workspace must have the fullscreen pointer cleared so that the
 | 
						// The workspace must have the fullscreen pointer cleared so that the
 | 
				
			||||||
	// seat code can find an appropriate new focus.
 | 
						// 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;
 | 
							con->workspace->fullscreen = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	wl_signal_emit(&con->node.events.destroy, &con->node);
 | 
						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);
 | 
							root_scratchpad_remove_container(con);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (con->fullscreen_mode == FULLSCREEN_GLOBAL) {
 | 
				
			||||||
 | 
							container_fullscreen_disable(con);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (con->parent || con->workspace) {
 | 
						if (con->parent || con->workspace) {
 | 
				
			||||||
		container_detach(con);
 | 
							container_detach(con);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -840,15 +844,15 @@ void container_floating_move_to_center(struct sway_container *con) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	struct sway_workspace *ws = con->workspace;
 | 
						struct sway_workspace *ws = con->workspace;
 | 
				
			||||||
	bool full = con->is_fullscreen;
 | 
						enum sway_fullscreen_mode fullscreen_mode = con->fullscreen_mode;
 | 
				
			||||||
	if (full) {
 | 
						if (fullscreen_mode) {
 | 
				
			||||||
		container_set_fullscreen(con, false);
 | 
							container_fullscreen_disable(con);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	double new_lx = ws->x + (ws->width - con->width) / 2;
 | 
						double new_lx = ws->x + (ws->width - con->width) / 2;
 | 
				
			||||||
	double new_ly = ws->y + (ws->height - con->height) / 2;
 | 
						double new_ly = ws->y + (ws->height - con->height) / 2;
 | 
				
			||||||
	container_floating_translate(con, new_lx - con->x, new_ly - con->y);
 | 
						container_floating_translate(con, new_lx - con->x, new_ly - con->y);
 | 
				
			||||||
	if (full) {
 | 
						if (fullscreen_mode) {
 | 
				
			||||||
		container_set_fullscreen(con, true);
 | 
							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) {
 | 
					static void container_fullscreen_workspace(struct sway_container *con) {
 | 
				
			||||||
	if (container->is_fullscreen == enable) {
 | 
						if (!sway_assert(con->fullscreen_mode == FULLSCREEN_NONE,
 | 
				
			||||||
 | 
									"Expected a non-fullscreen container")) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						bool enable = true;
 | 
				
			||||||
 | 
						set_fullscreen_iterator(con, &enable);
 | 
				
			||||||
 | 
						container_for_each_child(con, set_fullscreen_iterator, &enable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct sway_workspace *workspace = container->workspace;
 | 
						con->workspace->fullscreen = con;
 | 
				
			||||||
	if (enable && workspace->fullscreen) {
 | 
						con->saved_x = con->x;
 | 
				
			||||||
		container_set_fullscreen(workspace->fullscreen, false);
 | 
						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);
 | 
						con->fullscreen_mode = FULLSCREEN_WORKSPACE;
 | 
				
			||||||
	container_for_each_child(container, set_fullscreen_iterator, &enable);
 | 
						container_end_mouse_operation(con);
 | 
				
			||||||
 | 
						ipc_event_window(con, "fullscreen_mode");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	container->is_fullscreen = enable;
 | 
					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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (enable) {
 | 
						root->fullscreen_global = con;
 | 
				
			||||||
		workspace->fullscreen = container;
 | 
						con->saved_x = con->x;
 | 
				
			||||||
		container->saved_x = container->x;
 | 
						con->saved_y = con->y;
 | 
				
			||||||
		container->saved_y = container->y;
 | 
						con->saved_width = con->width;
 | 
				
			||||||
		container->saved_width = container->width;
 | 
						con->saved_height = con->height;
 | 
				
			||||||
		container->saved_height = container->height;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		struct sway_seat *seat;
 | 
						struct sway_seat *seat;
 | 
				
			||||||
		struct sway_workspace *focus_ws;
 | 
						wl_list_for_each(seat, &server.input->seats, link) {
 | 
				
			||||||
		wl_list_for_each(seat, &server.input->seats, link) {
 | 
							struct sway_container *focus = seat_get_focused_container(seat);
 | 
				
			||||||
			focus_ws = seat_get_focused_workspace(seat);
 | 
							if (focus && focus != con) {
 | 
				
			||||||
			if (focus_ws) {
 | 
								seat_set_focus_container(seat, con);
 | 
				
			||||||
				if (focus_ws == workspace) {
 | 
							}
 | 
				
			||||||
					seat_set_focus_container(seat, 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 {
 | 
						} else {
 | 
				
			||||||
		workspace->fullscreen = NULL;
 | 
							root->fullscreen_global = 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);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			container->width = container->saved_width;
 | 
					 | 
				
			||||||
			container->height = container->saved_height;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	container_end_mouse_operation(container);
 | 
						con->fullscreen_mode = FULLSCREEN_NONE;
 | 
				
			||||||
 | 
						container_end_mouse_operation(con);
 | 
				
			||||||
 | 
						ipc_event_window(con, "fullscreen_mode");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ipc_event_window(container, "fullscreen_mode");
 | 
					void container_set_fullscreen(struct sway_container *con,
 | 
				
			||||||
 | 
							enum sway_fullscreen_mode mode) {
 | 
				
			||||||
 | 
						if (con->fullscreen_mode == mode) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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) {
 | 
					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) {
 | 
					bool container_is_fullscreen_or_child(struct sway_container *container) {
 | 
				
			||||||
	do {
 | 
						do {
 | 
				
			||||||
		if (container->is_fullscreen) {
 | 
							if (container->fullscreen_mode) {
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		container = container->parent;
 | 
							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) {
 | 
					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) {
 | 
								con->workspace->fullscreen == con) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (con->workspace->fullscreen) {
 | 
						if (con->workspace->fullscreen) {
 | 
				
			||||||
		container_set_fullscreen(con->workspace->fullscreen, false);
 | 
							container_fullscreen_disable(con->workspace->fullscreen);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	con->workspace->fullscreen = con;
 | 
						con->workspace->fullscreen = con;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1171,9 +1241,12 @@ void container_add_child(struct sway_container *parent,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void container_detach(struct sway_container *child) {
 | 
					void container_detach(struct sway_container *child) {
 | 
				
			||||||
	if (child->is_fullscreen) {
 | 
						if (child->fullscreen_mode == FULLSCREEN_WORKSPACE) {
 | 
				
			||||||
		child->workspace->fullscreen = NULL;
 | 
							child->workspace->fullscreen = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (child->fullscreen_mode == FULLSCREEN_GLOBAL) {
 | 
				
			||||||
 | 
							root->fullscreen_global = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct sway_container *old_parent = child->parent;
 | 
						struct sway_container *old_parent = child->parent;
 | 
				
			||||||
	struct sway_workspace *old_workspace = child->workspace;
 | 
						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);
 | 
							node_set_dirty(&floater->workspace->node);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
						// If the current con or any of its parents are in fullscreen mode, we
 | 
				
			||||||
	// first need to disable it before showing the scratchpad con.
 | 
						// first need to disable it before showing the scratchpad con.
 | 
				
			||||||
	if (new_ws->fullscreen) {
 | 
						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
 | 
						// Show the container
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -203,12 +203,18 @@ void view_autoconfigure(struct sway_view *view) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	struct sway_output *output = con->workspace->output;
 | 
						struct sway_output *output = con->workspace->output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (con->is_fullscreen) {
 | 
						if (con->fullscreen_mode == FULLSCREEN_WORKSPACE) {
 | 
				
			||||||
		con->content_x = output->lx;
 | 
							con->content_x = output->lx;
 | 
				
			||||||
		con->content_y = output->ly;
 | 
							con->content_y = output->ly;
 | 
				
			||||||
		con->content_width = output->width;
 | 
							con->content_width = output->width;
 | 
				
			||||||
		con->content_height = output->height;
 | 
							con->content_height = output->height;
 | 
				
			||||||
		return;
 | 
							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;
 | 
						struct sway_workspace *ws = view->container->workspace;
 | 
				
			||||||
| 
						 | 
					@ -648,7 +654,10 @@ void view_unmap(struct sway_view *view) {
 | 
				
			||||||
		workspace_consider_destroy(ws);
 | 
							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);
 | 
							arrange_workspace(ws);
 | 
				
			||||||
		workspace_detect_urgent(ws);
 | 
							workspace_detect_urgent(ws);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1008,14 +1017,11 @@ bool view_is_visible(struct sway_view *view) {
 | 
				
			||||||
		con = con->parent;
 | 
							con = con->parent;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Check view isn't hidden by another fullscreen view
 | 
						// Check view isn't hidden by another fullscreen view
 | 
				
			||||||
	if (workspace->fullscreen &&
 | 
						struct sway_container *fs = root->fullscreen_global ?
 | 
				
			||||||
			!container_is_fullscreen_or_child(view->container)) {
 | 
							root->fullscreen_global : workspace->fullscreen;
 | 
				
			||||||
		// However, if we're transient for the fullscreen view and we allow
 | 
						if (fs && !container_is_fullscreen_or_child(view->container) &&
 | 
				
			||||||
		// "popups" during fullscreen then it might be visible
 | 
								!container_is_transient_for(view->container, fs)) {
 | 
				
			||||||
		if (!container_is_transient_for(view->container,
 | 
							return false;
 | 
				
			||||||
					workspace->fullscreen)) {
 | 
					 | 
				
			||||||
			return false;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue