|  |  |  | @ -5,6 +5,7 @@ | 
			
		
	
		
			
				
					|  |  |  |  | #include <time.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include <wlr/types/wlr_buffer.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/config.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/scene_descriptor.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/desktop/idle_inhibit_v1.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/desktop/transaction.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/input/cursor.h" | 
			
		
	
	
		
			
				
					|  |  |  | @ -252,6 +253,431 @@ static void apply_container_state(struct sway_container *container, | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void arrange_title_bar(struct sway_container *con, | 
			
		
	
		
			
				
					|  |  |  |  | 		int x, int y, int width, int height) { | 
			
		
	
		
			
				
					|  |  |  |  | 	container_update(con); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	bool has_title_bar = height > 0; | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_scene_node_set_enabled(&con->title_bar.tree->node, has_title_bar); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!has_title_bar) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_scene_node_set_position(&con->title_bar.tree->node, x, y); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	con->title_width = width; | 
			
		
	
		
			
				
					|  |  |  |  | 	container_arrange_title_bar(con); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void disable_container(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->view) { | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_reparent(&con->view->scene_tree->node, con->content_tree); | 
			
		
	
		
			
				
					|  |  |  |  | 	} else { | 
			
		
	
		
			
				
					|  |  |  |  | 		for (int i = 0; i < con->current.children->length; i++) { | 
			
		
	
		
			
				
					|  |  |  |  | 			struct sway_container *child = con->current.children->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_reparent(&child->scene_tree->node, con->content_tree); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			disable_container(child); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void arrange_container(struct sway_container *con, | 
			
		
	
		
			
				
					|  |  |  |  | 		int width, int height, bool title_bar, int gaps); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void arrange_children(enum sway_container_layout layout, list_t *children, | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_container *active, struct wlr_scene_tree *content, | 
			
		
	
		
			
				
					|  |  |  |  | 		int width, int height, int gaps) { | 
			
		
	
		
			
				
					|  |  |  |  | 	int title_bar_height = container_titlebar_height(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (layout == L_TABBED) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_container *first = children->length == 1 ? | 
			
		
	
		
			
				
					|  |  |  |  | 			((struct sway_container *)children->items[0]) : NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 		if (config->hide_lone_tab && first && first->view && | 
			
		
	
		
			
				
					|  |  |  |  | 				first->current.border != B_NORMAL) { | 
			
		
	
		
			
				
					|  |  |  |  | 			title_bar_height = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		double w = (double) width / children->length; | 
			
		
	
		
			
				
					|  |  |  |  | 		int title_offset = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 		for (int i = 0; i < children->length; i++) { | 
			
		
	
		
			
				
					|  |  |  |  | 			struct sway_container *child = children->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 			bool activated = child == active; | 
			
		
	
		
			
				
					|  |  |  |  | 			int next_title_offset = round(w * i + w); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			arrange_title_bar(child, title_offset, -title_bar_height, | 
			
		
	
		
			
				
					|  |  |  |  | 				next_title_offset - title_offset, title_bar_height); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&child->border.tree->node, activated); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_position(&child->scene_tree->node, 0, title_bar_height); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_reparent(&child->scene_tree->node, content); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			if (activated) { | 
			
		
	
		
			
				
					|  |  |  |  | 				arrange_container(child, width, height - title_bar_height, | 
			
		
	
		
			
				
					|  |  |  |  | 					false, 0); | 
			
		
	
		
			
				
					|  |  |  |  | 			} else { | 
			
		
	
		
			
				
					|  |  |  |  | 				disable_container(child); | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			title_offset = next_title_offset; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} else if (layout == L_STACKED) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_container *first = children->length == 1 ? | 
			
		
	
		
			
				
					|  |  |  |  | 			((struct sway_container *)children->items[0]) : NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 		if (config->hide_lone_tab && first && first->view && | 
			
		
	
		
			
				
					|  |  |  |  | 				first->current.border != B_NORMAL) { | 
			
		
	
		
			
				
					|  |  |  |  | 			title_bar_height = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		int title_height = title_bar_height * children->length; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		int y = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 		for (int i = 0; i < children->length; i++) { | 
			
		
	
		
			
				
					|  |  |  |  | 			struct sway_container *child = children->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 			bool activated = child == active; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			arrange_title_bar(child, 0, y - title_height, width, title_bar_height); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&child->border.tree->node, activated); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_position(&child->scene_tree->node, 0, title_height); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_reparent(&child->scene_tree->node, content); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			if (activated) { | 
			
		
	
		
			
				
					|  |  |  |  | 				arrange_container(child, width, height - title_height, | 
			
		
	
		
			
				
					|  |  |  |  | 					false, 0); | 
			
		
	
		
			
				
					|  |  |  |  | 			} else { | 
			
		
	
		
			
				
					|  |  |  |  | 				disable_container(child); | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			y += title_bar_height; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} else if (layout == L_VERT) { | 
			
		
	
		
			
				
					|  |  |  |  | 		int off = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 		for (int i = 0; i < children->length; i++) { | 
			
		
	
		
			
				
					|  |  |  |  | 			struct sway_container *child = children->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 			int cheight = child->current.height; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&child->border.tree->node, true); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_position(&child->scene_tree->node, 0, off); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_reparent(&child->scene_tree->node, content); | 
			
		
	
		
			
				
					|  |  |  |  | 			arrange_container(child, width, cheight, true, gaps); | 
			
		
	
		
			
				
					|  |  |  |  | 			off += cheight + gaps; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} else if (layout == L_HORIZ) { | 
			
		
	
		
			
				
					|  |  |  |  | 		int off = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 		for (int i = 0; i < children->length; i++) { | 
			
		
	
		
			
				
					|  |  |  |  | 			struct sway_container *child = children->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 			int cwidth = child->current.width; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&child->border.tree->node, true); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_position(&child->scene_tree->node, off, 0); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_reparent(&child->scene_tree->node, content); | 
			
		
	
		
			
				
					|  |  |  |  | 			arrange_container(child, cwidth, height, true, gaps); | 
			
		
	
		
			
				
					|  |  |  |  | 			off += cwidth + gaps; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} else { | 
			
		
	
		
			
				
					|  |  |  |  | 		sway_assert(false, "unreachable"); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void arrange_container(struct sway_container *con, | 
			
		
	
		
			
				
					|  |  |  |  | 		int width, int height, bool title_bar, int gaps) { | 
			
		
	
		
			
				
					|  |  |  |  | 	// this container might have previously been in the scratchpad,
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// make sure it's enabled for viewing
 | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_scene_node_set_enabled(&con->scene_tree->node, true); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->view) { | 
			
		
	
		
			
				
					|  |  |  |  | 		int border_top = container_titlebar_height(); | 
			
		
	
		
			
				
					|  |  |  |  | 		int border_width = con->current.border_thickness; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (title_bar && con->current.border != B_NORMAL) { | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&con->title_bar.tree->node, false); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&con->border.top->node, true); | 
			
		
	
		
			
				
					|  |  |  |  | 		} else { | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&con->border.top->node, false); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (con->current.border == B_NORMAL) { | 
			
		
	
		
			
				
					|  |  |  |  | 			if (title_bar) { | 
			
		
	
		
			
				
					|  |  |  |  | 				arrange_title_bar(con, 0, 0, width, border_top); | 
			
		
	
		
			
				
					|  |  |  |  | 			} else { | 
			
		
	
		
			
				
					|  |  |  |  | 				border_top = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 				// should be handled by the parent container
 | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} else if (con->current.border == B_PIXEL) { | 
			
		
	
		
			
				
					|  |  |  |  | 			container_update(con); | 
			
		
	
		
			
				
					|  |  |  |  | 			border_top = title_bar && con->current.border_top ? border_width : 0; | 
			
		
	
		
			
				
					|  |  |  |  | 		} else if (con->current.border == B_NONE) { | 
			
		
	
		
			
				
					|  |  |  |  | 			container_update(con); | 
			
		
	
		
			
				
					|  |  |  |  | 			border_top = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 			border_width = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 		} else if (con->current.border == B_CSD) { | 
			
		
	
		
			
				
					|  |  |  |  | 			border_top = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 			border_width = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 		} else { | 
			
		
	
		
			
				
					|  |  |  |  | 			sway_assert(false, "unreachable"); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		int border_bottom = con->current.border_bottom ? border_width : 0; | 
			
		
	
		
			
				
					|  |  |  |  | 		int border_left = con->current.border_left ? border_width : 0; | 
			
		
	
		
			
				
					|  |  |  |  | 		int border_right = con->current.border_right ? border_width : 0; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_rect_set_size(con->border.top, width, border_top); | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_rect_set_size(con->border.bottom, width, border_bottom); | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_rect_set_size(con->border.left, | 
			
		
	
		
			
				
					|  |  |  |  | 			border_left, height - border_top - border_bottom); | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_rect_set_size(con->border.right, | 
			
		
	
		
			
				
					|  |  |  |  | 			border_right, height - border_top - border_bottom); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_set_position(&con->border.top->node, 0, 0); | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_set_position(&con->border.bottom->node, | 
			
		
	
		
			
				
					|  |  |  |  | 			0, height - border_bottom); | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_set_position(&con->border.left->node, | 
			
		
	
		
			
				
					|  |  |  |  | 			0, border_top); | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_set_position(&con->border.right->node, | 
			
		
	
		
			
				
					|  |  |  |  | 			width - border_right, border_top); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		// make sure to reparent, it's possible that the client just came out of
 | 
			
		
	
		
			
				
					|  |  |  |  | 		// fullscreen mode where the parent of the surface is not the container
 | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_reparent(&con->view->scene_tree->node, con->content_tree); | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_set_position(&con->view->scene_tree->node, | 
			
		
	
		
			
				
					|  |  |  |  | 			border_left, border_top); | 
			
		
	
		
			
				
					|  |  |  |  | 	} else { | 
			
		
	
		
			
				
					|  |  |  |  | 		// make sure to disable the title bar if the parent is not managing it
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (title_bar) { | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&con->title_bar.tree->node, false); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		arrange_children(con->current.layout, con->current.children, | 
			
		
	
		
			
				
					|  |  |  |  | 			con->current.focused_inactive_child, con->content_tree, | 
			
		
	
		
			
				
					|  |  |  |  | 			width, height, gaps); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static int container_get_gaps(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_workspace *ws = con->current.workspace; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_container *temp = con; | 
			
		
	
		
			
				
					|  |  |  |  | 	while (temp) { | 
			
		
	
		
			
				
					|  |  |  |  | 		enum sway_container_layout layout; | 
			
		
	
		
			
				
					|  |  |  |  | 		if (temp->current.parent) { | 
			
		
	
		
			
				
					|  |  |  |  | 			layout = temp->current.parent->current.layout; | 
			
		
	
		
			
				
					|  |  |  |  | 		} else { | 
			
		
	
		
			
				
					|  |  |  |  | 			layout = ws->current.layout; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		if (layout == L_TABBED || layout == L_STACKED) { | 
			
		
	
		
			
				
					|  |  |  |  | 			return 0; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		temp = temp->pending.parent; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	return ws->gaps_inner; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void arrange_fullscreen(struct wlr_scene_tree *tree, | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_container *fs, struct sway_workspace *ws, | 
			
		
	
		
			
				
					|  |  |  |  | 		int width, int height) { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct wlr_scene_node *fs_node; | 
			
		
	
		
			
				
					|  |  |  |  | 	if (fs->view) { | 
			
		
	
		
			
				
					|  |  |  |  | 		fs_node = &fs->view->scene_tree->node; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		// if we only care about the view, disable any decorations
 | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_set_enabled(&fs->scene_tree->node, false); | 
			
		
	
		
			
				
					|  |  |  |  | 	} else { | 
			
		
	
		
			
				
					|  |  |  |  | 		fs_node = &fs->scene_tree->node; | 
			
		
	
		
			
				
					|  |  |  |  | 		arrange_container(fs, width, height, true, container_get_gaps(fs)); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_scene_node_reparent(fs_node, tree); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_scene_node_lower_to_bottom(fs_node); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_scene_node_set_position(fs_node, 0, 0); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void arrange_workspace_floating(struct sway_workspace *ws) { | 
			
		
	
		
			
				
					|  |  |  |  | 	for (int i = 0; i < ws->current.floating->length; i++) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_container *floater = ws->current.floating->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 		struct wlr_scene_tree *layer = root->layers.floating; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (floater->current.fullscreen_mode != FULLSCREEN_NONE) { | 
			
		
	
		
			
				
					|  |  |  |  | 			continue; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (root->fullscreen_global) { | 
			
		
	
		
			
				
					|  |  |  |  | 			if (container_is_transient_for(floater, root->fullscreen_global)) { | 
			
		
	
		
			
				
					|  |  |  |  | 				layer = root->layers.fullscreen_global; | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} else { | 
			
		
	
		
			
				
					|  |  |  |  | 			for (int i = 0; i < root->outputs->length; i++) { | 
			
		
	
		
			
				
					|  |  |  |  | 				struct sway_output *output = root->outputs->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 				struct sway_workspace *active = output->current.active_workspace; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				if (active && active->fullscreen && | 
			
		
	
		
			
				
					|  |  |  |  | 						container_is_transient_for(floater, active->fullscreen)) { | 
			
		
	
		
			
				
					|  |  |  |  | 					layer = root->layers.fullscreen; | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_reparent(&floater->scene_tree->node, layer); | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_set_position(&floater->scene_tree->node, | 
			
		
	
		
			
				
					|  |  |  |  | 			floater->current.x, floater->current.y); | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_set_enabled(&floater->scene_tree->node, true); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		arrange_container(floater, floater->current.width, floater->current.height, | 
			
		
	
		
			
				
					|  |  |  |  | 			true, ws->gaps_inner); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void arrange_workspace_tiling(struct sway_workspace *ws, | 
			
		
	
		
			
				
					|  |  |  |  | 		int width, int height) { | 
			
		
	
		
			
				
					|  |  |  |  | 	arrange_children(ws->current.layout, ws->current.tiling, | 
			
		
	
		
			
				
					|  |  |  |  | 		ws->current.focused_inactive_child, ws->layers.tiling, | 
			
		
	
		
			
				
					|  |  |  |  | 		width, height, ws->gaps_inner); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void disable_workspace(struct sway_workspace *ws) { | 
			
		
	
		
			
				
					|  |  |  |  | 	// if any containers were just moved to a disabled workspace it will
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// have the parent of the old workspace. Move the workspace so that it won't
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// be shown.
 | 
			
		
	
		
			
				
					|  |  |  |  | 	for (int i = 0; i < ws->current.tiling->length; i++) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_container *child = ws->current.tiling->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_reparent(&child->scene_tree->node, ws->layers.tiling); | 
			
		
	
		
			
				
					|  |  |  |  | 		disable_container(child); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	for (int i = 0; i < ws->current.floating->length; i++) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_container *floater = ws->current.floating->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_reparent(&floater->scene_tree->node, root->layers.floating); | 
			
		
	
		
			
				
					|  |  |  |  | 		disable_container(floater); | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_set_enabled(&floater->scene_tree->node, false); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void arrange_output(struct sway_output *output, int width, int height) { | 
			
		
	
		
			
				
					|  |  |  |  | 	for (int i = 0; i < output->current.workspaces->length; i++) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_workspace *child = output->current.workspaces->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		bool activated = output->current.active_workspace == child; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_reparent(&child->layers.tiling->node, output->layers.tiling); | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_reparent(&child->layers.fullscreen->node, output->layers.fullscreen); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		for (int i = 0; i < child->current.floating->length; i++) { | 
			
		
	
		
			
				
					|  |  |  |  | 			struct sway_container *floater = child->current.floating->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_reparent(&floater->scene_tree->node, root->layers.floating); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&floater->scene_tree->node, activated); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (activated) { | 
			
		
	
		
			
				
					|  |  |  |  | 			struct sway_container *fs = child->current.fullscreen; | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&child->layers.tiling->node, !fs); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&child->layers.fullscreen->node, fs); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			arrange_workspace_floating(child); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&output->layers.shell_background->node, !fs); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&output->layers.shell_bottom->node, !fs); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&output->layers.fullscreen->node, fs); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			if (fs) { | 
			
		
	
		
			
				
					|  |  |  |  | 				wlr_scene_rect_set_size(output->fullscreen_background, width, height); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				arrange_fullscreen(child->layers.fullscreen, fs, child, | 
			
		
	
		
			
				
					|  |  |  |  | 					width, height); | 
			
		
	
		
			
				
					|  |  |  |  | 			} else { | 
			
		
	
		
			
				
					|  |  |  |  | 				struct wlr_box *area = &output->usable_area; | 
			
		
	
		
			
				
					|  |  |  |  | 				struct side_gaps *gaps = &child->current_gaps; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				wlr_scene_node_set_position(&child->layers.tiling->node, | 
			
		
	
		
			
				
					|  |  |  |  | 					gaps->left + area->x, gaps->top + area->y); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				arrange_workspace_tiling(child, | 
			
		
	
		
			
				
					|  |  |  |  | 					area->width - gaps->left - gaps->right, | 
			
		
	
		
			
				
					|  |  |  |  | 					area->height - gaps->top - gaps->bottom); | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} else { | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&child->layers.tiling->node, false); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_enabled(&child->layers.fullscreen->node, false); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			disable_workspace(child); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void arrange_popup(struct wlr_scene_tree *popup) { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct wlr_scene_node *node; | 
			
		
	
		
			
				
					|  |  |  |  | 	wl_list_for_each(node, &popup->children, link) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_xdg_popup *popup = scene_descriptor_try_get(node, | 
			
		
	
		
			
				
					|  |  |  |  | 			SWAY_SCENE_DESC_POPUP); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		// the popup layer may have popups from layer_shell surfaces, in this
 | 
			
		
	
		
			
				
					|  |  |  |  | 		// case those don't have a scene descriptor, so lets skip those here.
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (popup) { | 
			
		
	
		
			
				
					|  |  |  |  | 			struct wlr_scene_tree *tree = popup->view->content_tree; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			int lx, ly; | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_coords(&tree->node, &lx, &ly); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_position(&popup->scene_tree->node, lx, ly); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void arrange_root(struct sway_root *root) { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_container *fs = root->fullscreen_global; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_scene_node_set_enabled(&root->layers.shell_background->node, !fs); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_scene_node_set_enabled(&root->layers.shell_bottom->node, !fs); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_scene_node_set_enabled(&root->layers.tiling->node, !fs); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_scene_node_set_enabled(&root->layers.floating->node, !fs); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_scene_node_set_enabled(&root->layers.shell_top->node, !fs); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_scene_node_set_enabled(&root->layers.fullscreen->node, !fs); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// hide all contents in the scratchpad
 | 
			
		
	
		
			
				
					|  |  |  |  | 	for (int i = 0; i < root->scratchpad->length; i++) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_container *con = root->scratchpad->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_set_enabled(&con->scene_tree->node, false); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (fs) { | 
			
		
	
		
			
				
					|  |  |  |  | 		for (int i = 0; i < root->outputs->length; i++) { | 
			
		
	
		
			
				
					|  |  |  |  | 			struct sway_output *output = root->outputs->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 			struct sway_workspace *ws = output->current.active_workspace; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			if (ws) { | 
			
		
	
		
			
				
					|  |  |  |  | 				arrange_workspace_floating(ws); | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		arrange_fullscreen(root->layers.fullscreen_global, fs, NULL, | 
			
		
	
		
			
				
					|  |  |  |  | 			root->width, root->height); | 
			
		
	
		
			
				
					|  |  |  |  | 	} else { | 
			
		
	
		
			
				
					|  |  |  |  | 		for (int i = 0; i < root->outputs->length; i++) { | 
			
		
	
		
			
				
					|  |  |  |  | 			struct sway_output *output = root->outputs->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_output_set_position(output->scene_output, output->lx, output->ly); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_reparent(&output->layers.shell_background->node, root->layers.shell_background); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_reparent(&output->layers.shell_bottom->node, root->layers.shell_bottom); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_reparent(&output->layers.tiling->node, root->layers.tiling); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_reparent(&output->layers.shell_top->node, root->layers.shell_top); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_reparent(&output->layers.shell_overlay->node, root->layers.shell_overlay); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_reparent(&output->layers.fullscreen->node, root->layers.fullscreen); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_reparent(&output->layers.session_lock->node, root->layers.session_lock); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_position(&output->layers.shell_background->node, output->lx, output->ly); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_position(&output->layers.shell_bottom->node, output->lx, output->ly); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_position(&output->layers.tiling->node, output->lx, output->ly); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_position(&output->layers.fullscreen->node, output->lx, output->ly); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_position(&output->layers.shell_top->node, output->lx, output->ly); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_position(&output->layers.shell_overlay->node, output->lx, output->ly); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_position(&output->layers.session_lock->node, output->lx, output->ly); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			arrange_output(output, output->width, output->height); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	arrange_popup(root->layers.popup); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /**
 | 
			
		
	
		
			
				
					|  |  |  |  |  * Apply a transaction to the "current" state of the tree. | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
	
		
			
				
					|  |  |  | @ -291,8 +717,6 @@ static void transaction_apply(struct sway_transaction *transaction) { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		node->instruction = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	cursor_rebase_all(); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void transaction_commit_pending(void); | 
			
		
	
	
		
			
				
					|  |  |  | @ -305,6 +729,8 @@ static void transaction_progress(void) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	transaction_apply(server.queued_transaction); | 
			
		
	
		
			
				
					|  |  |  |  | 	arrange_root(root); | 
			
		
	
		
			
				
					|  |  |  |  | 	cursor_rebase_all(); | 
			
		
	
		
			
				
					|  |  |  |  | 	transaction_destroy(server.queued_transaction); | 
			
		
	
		
			
				
					|  |  |  |  | 	server.queued_transaction = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | 
 |