|  |  |  | @ -8,15 +8,13 @@ | 
			
		
	
		
			
				
					|  |  |  |  | #include <wlr/types/wlr_output_layout.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include <wlr/types/wlr_subcompositor.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include "linux-dmabuf-unstable-v1-protocol.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "cairo_util.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "pango.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/config.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/desktop.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/desktop/transaction.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/input/input-manager.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/input/seat.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/ipc-server.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/scene_descriptor.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/sway_text_node.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/output.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/server.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/surface.h" | 
			
		
	
	
		
			
				
					|  |  |  | @ -120,9 +118,328 @@ struct sway_container *container_create(struct sway_view *view) { | 
			
		
	
		
			
				
					|  |  |  |  | 	wl_signal_init(&c->events.destroy); | 
			
		
	
		
			
				
					|  |  |  |  | 	wl_signal_emit_mutable(&root->events.new_node, &c->node); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	container_update(c); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	return c; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static bool container_is_focused(struct sway_container *con, void *data) { | 
			
		
	
		
			
				
					|  |  |  |  | 	return con->current.focused; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static bool container_has_focused_child(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	return container_find_child(con, container_is_focused, NULL); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static bool container_is_current_parent_focused(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->current.parent) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_container *parent = con->current.parent; | 
			
		
	
		
			
				
					|  |  |  |  | 		return parent->current.focused || container_is_current_parent_focused(parent); | 
			
		
	
		
			
				
					|  |  |  |  | 	} else if (con->current.workspace) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_workspace *ws = con->current.workspace; | 
			
		
	
		
			
				
					|  |  |  |  | 		return ws->current.focused; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	return false; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static struct border_colors *container_get_current_colors( | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct border_colors *colors; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	bool urgent = con->view ? | 
			
		
	
		
			
				
					|  |  |  |  | 		view_is_urgent(con->view) : container_has_urgent_child(con); | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_container *active_child; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->current.parent) { | 
			
		
	
		
			
				
					|  |  |  |  | 		active_child = con->current.parent->current.focused_inactive_child; | 
			
		
	
		
			
				
					|  |  |  |  | 	} else if (con->current.workspace) { | 
			
		
	
		
			
				
					|  |  |  |  | 		active_child = con->current.workspace->current.focused_inactive_child; | 
			
		
	
		
			
				
					|  |  |  |  | 	} else { | 
			
		
	
		
			
				
					|  |  |  |  | 		active_child = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (urgent) { | 
			
		
	
		
			
				
					|  |  |  |  | 		colors = &config->border_colors.urgent; | 
			
		
	
		
			
				
					|  |  |  |  | 	} else if (con->current.focused || container_is_current_parent_focused(con)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		colors = &config->border_colors.focused; | 
			
		
	
		
			
				
					|  |  |  |  | 	} else if (config->has_focused_tab_title && container_has_focused_child(con)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		colors = &config->border_colors.focused_tab_title; | 
			
		
	
		
			
				
					|  |  |  |  | 	} else if (con == active_child) { | 
			
		
	
		
			
				
					|  |  |  |  | 		colors = &config->border_colors.focused_inactive; | 
			
		
	
		
			
				
					|  |  |  |  | 	} else { | 
			
		
	
		
			
				
					|  |  |  |  | 		colors = &config->border_colors.unfocused; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	return colors; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static bool container_is_current_floating(struct sway_container *container) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!container->current.parent && container->current.workspace && | 
			
		
	
		
			
				
					|  |  |  |  | 			list_find(container->current.workspace->floating, container) != -1) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return true; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	if (container->scratchpad) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return true; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	return false; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // scene rect wants premultiplied colors
 | 
			
		
	
		
			
				
					|  |  |  |  | static void scene_rect_set_color(struct wlr_scene_rect *rect, | 
			
		
	
		
			
				
					|  |  |  |  | 		const float color[4], float opacity) { | 
			
		
	
		
			
				
					|  |  |  |  | 	const float premultiplied[] = { | 
			
		
	
		
			
				
					|  |  |  |  | 		color[0] * color[3] * opacity, | 
			
		
	
		
			
				
					|  |  |  |  | 		color[1] * color[3] * opacity, | 
			
		
	
		
			
				
					|  |  |  |  | 		color[2] * color[3] * opacity, | 
			
		
	
		
			
				
					|  |  |  |  | 		color[3] * opacity, | 
			
		
	
		
			
				
					|  |  |  |  | 	}; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_scene_rect_set_color(rect, premultiplied); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void container_update(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct border_colors *colors = container_get_current_colors(con); | 
			
		
	
		
			
				
					|  |  |  |  | 	list_t *siblings = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	enum sway_container_layout layout = L_NONE; | 
			
		
	
		
			
				
					|  |  |  |  | 	float alpha = con->alpha; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->current.parent) { | 
			
		
	
		
			
				
					|  |  |  |  | 		siblings = con->current.parent->current.children; | 
			
		
	
		
			
				
					|  |  |  |  | 		layout = con->current.parent->current.layout; | 
			
		
	
		
			
				
					|  |  |  |  | 	} else if (con->current.workspace) { | 
			
		
	
		
			
				
					|  |  |  |  | 		siblings = con->current.workspace->current.tiling; | 
			
		
	
		
			
				
					|  |  |  |  | 		layout = con->current.workspace->current.layout; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	float bottom[4], right[4]; | 
			
		
	
		
			
				
					|  |  |  |  | 	memcpy(bottom, colors->child_border, sizeof(bottom)); | 
			
		
	
		
			
				
					|  |  |  |  | 	memcpy(right, colors->child_border, sizeof(right)); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!container_is_current_floating(con) && siblings && siblings->length == 1) { | 
			
		
	
		
			
				
					|  |  |  |  | 		if (layout == L_HORIZ) { | 
			
		
	
		
			
				
					|  |  |  |  | 			memcpy(right, colors->indicator, sizeof(right)); | 
			
		
	
		
			
				
					|  |  |  |  | 		} else if (layout == L_VERT) { | 
			
		
	
		
			
				
					|  |  |  |  | 			memcpy(bottom, colors->indicator, sizeof(bottom)); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	struct wlr_scene_node *node; | 
			
		
	
		
			
				
					|  |  |  |  | 	wl_list_for_each(node, &con->title_bar.border->children, link) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct wlr_scene_rect *rect = wlr_scene_rect_from_node(node); | 
			
		
	
		
			
				
					|  |  |  |  | 		scene_rect_set_color(rect, colors->border, alpha); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	wl_list_for_each(node, &con->title_bar.background->children, link) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct wlr_scene_rect *rect = wlr_scene_rect_from_node(node); | 
			
		
	
		
			
				
					|  |  |  |  | 		scene_rect_set_color(rect, colors->background, alpha); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->view) { | 
			
		
	
		
			
				
					|  |  |  |  | 		scene_rect_set_color(con->border.top, colors->child_border, alpha); | 
			
		
	
		
			
				
					|  |  |  |  | 		scene_rect_set_color(con->border.bottom, bottom, alpha); | 
			
		
	
		
			
				
					|  |  |  |  | 		scene_rect_set_color(con->border.left, colors->child_border, alpha); | 
			
		
	
		
			
				
					|  |  |  |  | 		scene_rect_set_color(con->border.right, right, alpha); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->title_bar.title_text) { | 
			
		
	
		
			
				
					|  |  |  |  | 		sway_text_node_set_color(con->title_bar.title_text, colors->text); | 
			
		
	
		
			
				
					|  |  |  |  | 		sway_text_node_set_background(con->title_bar.title_text, colors->background); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->title_bar.marks_text) { | 
			
		
	
		
			
				
					|  |  |  |  | 		sway_text_node_set_color(con->title_bar.marks_text, colors->text); | 
			
		
	
		
			
				
					|  |  |  |  | 		sway_text_node_set_background(con->title_bar.marks_text, colors->background); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void container_update_itself_and_parents(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	container_update(con); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->current.parent) { | 
			
		
	
		
			
				
					|  |  |  |  | 		container_update_itself_and_parents(con->current.parent); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void update_rect_list(struct wlr_scene_tree *tree, pixman_region32_t *region) { | 
			
		
	
		
			
				
					|  |  |  |  | 	int len; | 
			
		
	
		
			
				
					|  |  |  |  | 	const pixman_box32_t *rects = pixman_region32_rectangles(region, &len); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_scene_node_set_enabled(&tree->node, len > 0); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (len == 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	int i = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct wlr_scene_node *node; | 
			
		
	
		
			
				
					|  |  |  |  | 	wl_list_for_each(node, &tree->children, link) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct wlr_scene_rect *rect = wlr_scene_rect_from_node(node); | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_set_enabled(&rect->node, i < len); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (i < len) { | 
			
		
	
		
			
				
					|  |  |  |  | 			const pixman_box32_t *box = &rects[i++]; | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_set_position(&rect->node, box->x1, box->y1); | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_rect_set_size(rect, box->x2 - box->x1, box->y2 - box->y1); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void container_arrange_title_bar(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	enum alignment title_align = config->title_align; | 
			
		
	
		
			
				
					|  |  |  |  | 	int marks_buffer_width = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 	int width = con->title_width; | 
			
		
	
		
			
				
					|  |  |  |  | 	int height = container_titlebar_height(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	pixman_region32_t text_area; | 
			
		
	
		
			
				
					|  |  |  |  | 	pixman_region32_init(&text_area); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->title_bar.marks_text) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_text_node *node = con->title_bar.marks_text; | 
			
		
	
		
			
				
					|  |  |  |  | 		marks_buffer_width = node->width; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		int h_padding; | 
			
		
	
		
			
				
					|  |  |  |  | 		if (title_align == ALIGN_RIGHT) { | 
			
		
	
		
			
				
					|  |  |  |  | 			h_padding = config->titlebar_h_padding; | 
			
		
	
		
			
				
					|  |  |  |  | 		} else { | 
			
		
	
		
			
				
					|  |  |  |  | 			h_padding = width - config->titlebar_h_padding - marks_buffer_width; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		h_padding = MAX(h_padding, 0); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		int alloc_width = MIN((int)node->width, | 
			
		
	
		
			
				
					|  |  |  |  | 			width - h_padding - config->titlebar_h_padding); | 
			
		
	
		
			
				
					|  |  |  |  | 		sway_text_node_set_max_width(node, alloc_width); | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_set_position(node->node, | 
			
		
	
		
			
				
					|  |  |  |  | 			h_padding, (height - node->height) >> 1); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		pixman_region32_union_rect(&text_area, &text_area, | 
			
		
	
		
			
				
					|  |  |  |  | 			node->node->x, node->node->y, alloc_width, node->height); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->title_bar.title_text) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_text_node *node = con->title_bar.title_text; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		int h_padding; | 
			
		
	
		
			
				
					|  |  |  |  | 		if (title_align == ALIGN_RIGHT) { | 
			
		
	
		
			
				
					|  |  |  |  | 			h_padding = width - config->titlebar_h_padding - node->width; | 
			
		
	
		
			
				
					|  |  |  |  | 		} else if (title_align == ALIGN_CENTER) { | 
			
		
	
		
			
				
					|  |  |  |  | 			h_padding = ((int)width - marks_buffer_width - node->width) >> 1; | 
			
		
	
		
			
				
					|  |  |  |  | 		} else { | 
			
		
	
		
			
				
					|  |  |  |  | 			h_padding = config->titlebar_h_padding; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		h_padding = MAX(h_padding, 0); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		int alloc_width = MIN((int) node->width, | 
			
		
	
		
			
				
					|  |  |  |  | 			width - h_padding - config->titlebar_h_padding); | 
			
		
	
		
			
				
					|  |  |  |  | 		sway_text_node_set_max_width(node, alloc_width); | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_set_position(node->node, | 
			
		
	
		
			
				
					|  |  |  |  | 			h_padding, (height - node->height) >> 1); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		pixman_region32_union_rect(&text_area, &text_area, | 
			
		
	
		
			
				
					|  |  |  |  | 			node->node->x, node->node->y, alloc_width, node->height); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// silence pixman errors
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (width <= 0 || height <= 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 		pixman_region32_fini(&text_area); | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	pixman_region32_t background, border; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	int thickness = config->titlebar_border_thickness; | 
			
		
	
		
			
				
					|  |  |  |  | 	pixman_region32_init_rect(&background, | 
			
		
	
		
			
				
					|  |  |  |  | 		thickness, thickness, | 
			
		
	
		
			
				
					|  |  |  |  | 		width - thickness * 2, height - thickness * 2); | 
			
		
	
		
			
				
					|  |  |  |  | 	pixman_region32_init_rect(&border, 0, 0, width, height); | 
			
		
	
		
			
				
					|  |  |  |  | 	pixman_region32_subtract(&border, &border, &background); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	pixman_region32_subtract(&background, &background, &text_area); | 
			
		
	
		
			
				
					|  |  |  |  | 	pixman_region32_fini(&text_area); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	update_rect_list(con->title_bar.background, &background); | 
			
		
	
		
			
				
					|  |  |  |  | 	pixman_region32_fini(&background); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	update_rect_list(con->title_bar.border, &border); | 
			
		
	
		
			
				
					|  |  |  |  | 	pixman_region32_fini(&border); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	container_update(con); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void container_update_marks(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	char *buffer = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (config->show_marks && con->marks->length) { | 
			
		
	
		
			
				
					|  |  |  |  | 		size_t len = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 		for (int i = 0; i < con->marks->length; ++i) { | 
			
		
	
		
			
				
					|  |  |  |  | 			char *mark = con->marks->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 			if (mark[0] != '_') { | 
			
		
	
		
			
				
					|  |  |  |  | 				len += strlen(mark) + 2; | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		buffer = calloc(len + 1, 1); | 
			
		
	
		
			
				
					|  |  |  |  | 		char *part = malloc(len + 1); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (!sway_assert(buffer && part, "Unable to allocate memory")) { | 
			
		
	
		
			
				
					|  |  |  |  | 			free(buffer); | 
			
		
	
		
			
				
					|  |  |  |  | 			return; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		for (int i = 0; i < con->marks->length; ++i) { | 
			
		
	
		
			
				
					|  |  |  |  | 			char *mark = con->marks->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 			if (mark[0] != '_') { | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(part, len + 1, "[%s]", mark); | 
			
		
	
		
			
				
					|  |  |  |  | 				strcat(buffer, part); | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		free(part); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!buffer) { | 
			
		
	
		
			
				
					|  |  |  |  | 		if (con->title_bar.marks_text) { | 
			
		
	
		
			
				
					|  |  |  |  | 			wlr_scene_node_destroy(con->title_bar.marks_text->node); | 
			
		
	
		
			
				
					|  |  |  |  | 			con->title_bar.marks_text = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} else if (!con->title_bar.marks_text) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct border_colors *colors = container_get_current_colors(con); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		con->title_bar.marks_text = sway_text_node_create(con->title_bar.tree, | 
			
		
	
		
			
				
					|  |  |  |  | 			buffer, colors->text, false); | 
			
		
	
		
			
				
					|  |  |  |  | 	} else { | 
			
		
	
		
			
				
					|  |  |  |  | 		sway_text_node_set_text(con->title_bar.marks_text, buffer); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	container_arrange_title_bar(con); | 
			
		
	
		
			
				
					|  |  |  |  | 	free(buffer); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void container_update_title_bar(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!con->formatted_title) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	struct border_colors *colors = container_get_current_colors(con); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->title_bar.title_text) { | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_destroy(con->title_bar.title_text->node); | 
			
		
	
		
			
				
					|  |  |  |  | 		con->title_bar.title_text = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	con->title_bar.title_text = sway_text_node_create(con->title_bar.tree, | 
			
		
	
		
			
				
					|  |  |  |  | 		con->formatted_title, colors->text, config->pango_markup); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// we always have to remake these text buffers completely for text font
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// changes etc...
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->title_bar.marks_text) { | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_destroy(con->title_bar.marks_text->node); | 
			
		
	
		
			
				
					|  |  |  |  | 		con->title_bar.marks_text = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	container_update_marks(con); | 
			
		
	
		
			
				
					|  |  |  |  | 	container_arrange_title_bar(con); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void container_destroy(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!sway_assert(con->node.destroying, | 
			
		
	
		
			
				
					|  |  |  |  | 				"Tried to free container which wasn't marked as destroying")) { | 
			
		
	
	
		
			
				
					|  |  |  | @ -134,21 +451,11 @@ void container_destroy(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	free(con->title); | 
			
		
	
		
			
				
					|  |  |  |  | 	free(con->formatted_title); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_texture_destroy(con->title_focused); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_texture_destroy(con->title_focused_inactive); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_texture_destroy(con->title_unfocused); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_texture_destroy(con->title_urgent); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_texture_destroy(con->title_focused_tab_title); | 
			
		
	
		
			
				
					|  |  |  |  | 	list_free(con->pending.children); | 
			
		
	
		
			
				
					|  |  |  |  | 	list_free(con->current.children); | 
			
		
	
		
			
				
					|  |  |  |  | 	list_free(con->outputs); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	list_free_items_and_destroy(con->marks); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_texture_destroy(con->marks_focused); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_texture_destroy(con->marks_focused_inactive); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_texture_destroy(con->marks_unfocused); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_texture_destroy(con->marks_urgent); | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_texture_destroy(con->marks_focused_tab_title); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->view && con->view->container == con) { | 
			
		
	
		
			
				
					|  |  |  |  | 		con->view->container = NULL; | 
			
		
	
	
		
			
				
					|  |  |  | @ -308,108 +615,6 @@ struct sway_output *container_get_effective_output(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	return con->outputs->items[con->outputs->length - 1]; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void render_titlebar_text_texture(struct sway_output *output, | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_container *con, struct wlr_texture **texture, | 
			
		
	
		
			
				
					|  |  |  |  | 		struct border_colors *class, bool pango_markup, char *text) { | 
			
		
	
		
			
				
					|  |  |  |  | 	double scale = output->wlr_output->scale; | 
			
		
	
		
			
				
					|  |  |  |  | 	int width = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 	int height = config->font_height * scale; | 
			
		
	
		
			
				
					|  |  |  |  | 	int baseline; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// We must use a non-nil cairo_t for cairo_set_font_options to work.
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// Therefore, we cannot use cairo_create(NULL).
 | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_surface_t *dummy_surface = cairo_image_surface_create( | 
			
		
	
		
			
				
					|  |  |  |  | 			CAIRO_FORMAT_ARGB32, 0, 0); | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_t *c = cairo_create(dummy_surface); | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_set_antialias(c, CAIRO_ANTIALIAS_BEST); | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_font_options_t *fo = cairo_font_options_create(); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (output->wlr_output->subpixel == WL_OUTPUT_SUBPIXEL_NONE) { | 
			
		
	
		
			
				
					|  |  |  |  | 		cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_GRAY); | 
			
		
	
		
			
				
					|  |  |  |  | 	} else { | 
			
		
	
		
			
				
					|  |  |  |  | 		cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL); | 
			
		
	
		
			
				
					|  |  |  |  | 		cairo_font_options_set_subpixel_order(fo, | 
			
		
	
		
			
				
					|  |  |  |  | 			to_cairo_subpixel_order(output->wlr_output->subpixel)); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_set_font_options(c, fo); | 
			
		
	
		
			
				
					|  |  |  |  | 	get_text_size(c, config->font_description, &width, NULL, &baseline, scale, | 
			
		
	
		
			
				
					|  |  |  |  | 			config->pango_markup, "%s", text); | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_surface_destroy(dummy_surface); | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_destroy(c); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (width == 0 || height == 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (height > config->font_height * scale) { | 
			
		
	
		
			
				
					|  |  |  |  | 		height = config->font_height * scale; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_surface_t *surface = cairo_image_surface_create( | 
			
		
	
		
			
				
					|  |  |  |  | 			CAIRO_FORMAT_ARGB32, width, height); | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_status_t status = cairo_surface_status(surface); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (status != CAIRO_STATUS_SUCCESS) { | 
			
		
	
		
			
				
					|  |  |  |  | 		sway_log(SWAY_ERROR, "cairo_image_surface_create failed: %s", | 
			
		
	
		
			
				
					|  |  |  |  | 			cairo_status_to_string(status)); | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_t *cairo = cairo_create(surface); | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_set_font_options(cairo, fo); | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_font_options_destroy(fo); | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_set_source_rgba(cairo, class->background[0], class->background[1], | 
			
		
	
		
			
				
					|  |  |  |  | 			class->background[2], class->background[3]); | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_paint(cairo); | 
			
		
	
		
			
				
					|  |  |  |  | 	PangoContext *pango = pango_cairo_create_context(cairo); | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_set_source_rgba(cairo, class->text[0], class->text[1], | 
			
		
	
		
			
				
					|  |  |  |  | 			class->text[2], class->text[3]); | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_move_to(cairo, 0, config->font_baseline * scale - baseline); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	render_text(cairo, config->font_description, scale, pango_markup, "%s", text); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_surface_flush(surface); | 
			
		
	
		
			
				
					|  |  |  |  | 	unsigned char *data = cairo_image_surface_get_data(surface); | 
			
		
	
		
			
				
					|  |  |  |  | 	int stride = cairo_image_surface_get_stride(surface); | 
			
		
	
		
			
				
					|  |  |  |  | 	struct wlr_renderer *renderer = output->wlr_output->renderer; | 
			
		
	
		
			
				
					|  |  |  |  | 	*texture = wlr_texture_from_pixels( | 
			
		
	
		
			
				
					|  |  |  |  | 			renderer, DRM_FORMAT_ARGB8888, stride, width, height, data); | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_surface_destroy(surface); | 
			
		
	
		
			
				
					|  |  |  |  | 	g_object_unref(pango); | 
			
		
	
		
			
				
					|  |  |  |  | 	cairo_destroy(cairo); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void update_title_texture(struct sway_container *con, | 
			
		
	
		
			
				
					|  |  |  |  | 		struct wlr_texture **texture, struct border_colors *class) { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_output *output = container_get_effective_output(con); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!output) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	if (*texture) { | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_texture_destroy(*texture); | 
			
		
	
		
			
				
					|  |  |  |  | 		*texture = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!con->formatted_title) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	render_titlebar_text_texture(output, con, texture, class, | 
			
		
	
		
			
				
					|  |  |  |  | 		config->pango_markup, con->formatted_title); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void container_update_title_textures(struct sway_container *container) { | 
			
		
	
		
			
				
					|  |  |  |  | 	update_title_texture(container, &container->title_focused, | 
			
		
	
		
			
				
					|  |  |  |  | 			&config->border_colors.focused); | 
			
		
	
		
			
				
					|  |  |  |  | 	update_title_texture(container, &container->title_focused_inactive, | 
			
		
	
		
			
				
					|  |  |  |  | 			&config->border_colors.focused_inactive); | 
			
		
	
		
			
				
					|  |  |  |  | 	update_title_texture(container, &container->title_unfocused, | 
			
		
	
		
			
				
					|  |  |  |  | 			&config->border_colors.unfocused); | 
			
		
	
		
			
				
					|  |  |  |  | 	update_title_texture(container, &container->title_urgent, | 
			
		
	
		
			
				
					|  |  |  |  | 			&config->border_colors.urgent); | 
			
		
	
		
			
				
					|  |  |  |  | 	update_title_texture(container, &container->title_focused_tab_title, | 
			
		
	
		
			
				
					|  |  |  |  | 			&config->border_colors.focused_tab_title); | 
			
		
	
		
			
				
					|  |  |  |  | 	container_damage_whole(container); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /**
 | 
			
		
	
		
			
				
					|  |  |  |  |  * Calculate and return the length of the tree representation. | 
			
		
	
		
			
				
					|  |  |  |  |  * An example tree representation is: V[Terminal, Firefox] | 
			
		
	
	
		
			
				
					|  |  |  | @ -475,7 +680,13 @@ void container_update_representation(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		container_build_representation(con->pending.layout, con->pending.children, | 
			
		
	
		
			
				
					|  |  |  |  | 				con->formatted_title); | 
			
		
	
		
			
				
					|  |  |  |  | 		container_update_title_textures(con); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (con->title_bar.title_text) { | 
			
		
	
		
			
				
					|  |  |  |  | 			sway_text_node_set_text(con->title_bar.title_text, con->formatted_title); | 
			
		
	
		
			
				
					|  |  |  |  | 			container_arrange_title_bar(con); | 
			
		
	
		
			
				
					|  |  |  |  | 		} else { | 
			
		
	
		
			
				
					|  |  |  |  | 			container_update_title_bar(con); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->pending.parent) { | 
			
		
	
		
			
				
					|  |  |  |  | 		container_update_representation(con->pending.parent); | 
			
		
	
	
		
			
				
					|  |  |  | @ -761,17 +972,6 @@ bool container_is_floating(struct sway_container *container) { | 
			
		
	
		
			
				
					|  |  |  |  | 	return false; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | bool container_is_current_floating(struct sway_container *container) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!container->current.parent && container->current.workspace && | 
			
		
	
		
			
				
					|  |  |  |  | 			list_find(container->current.workspace->floating, container) != -1) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return true; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	if (container->scratchpad) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return true; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	return false; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void container_get_box(struct sway_container *container, struct wlr_box *box) { | 
			
		
	
		
			
				
					|  |  |  |  | 	box->x = container->pending.x; | 
			
		
	
		
			
				
					|  |  |  |  | 	box->y = container->pending.y; | 
			
		
	
	
		
			
				
					|  |  |  | @ -1092,7 +1292,6 @@ void container_discover_outputs(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 		.width = con->current.width, | 
			
		
	
		
			
				
					|  |  |  |  | 		.height = con->current.height, | 
			
		
	
		
			
				
					|  |  |  |  | 	}; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_output *old_output = container_get_effective_output(con); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	for (int i = 0; i < root->outputs->length; ++i) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_output *output = root->outputs->items[i]; | 
			
		
	
	
		
			
				
					|  |  |  | @ -1129,14 +1328,6 @@ void container_discover_outputs(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 			list_del(con->outputs, index); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_output *new_output = container_get_effective_output(con); | 
			
		
	
		
			
				
					|  |  |  |  | 	double old_scale = old_output && old_output->enabled ? | 
			
		
	
		
			
				
					|  |  |  |  | 		old_output->wlr_output->scale : -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	double new_scale = new_output ? new_output->wlr_output->scale : -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	if (old_scale != new_scale) { | 
			
		
	
		
			
				
					|  |  |  |  | 		container_update_title_textures(con); | 
			
		
	
		
			
				
					|  |  |  |  | 		container_update_marks_textures(con); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | enum sway_container_layout container_parent_layout(struct sway_container *con) { | 
			
		
	
	
		
			
				
					|  |  |  | @ -1149,14 +1340,6 @@ enum sway_container_layout container_parent_layout(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	return L_NONE; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | enum sway_container_layout container_current_parent_layout( | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->current.parent) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return con->current.parent->current.layout; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	return con->current.workspace->current.layout; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | list_t *container_get_siblings(struct sway_container *container) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (container->pending.parent) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return container->pending.parent->pending.children; | 
			
		
	
	
		
			
				
					|  |  |  | @ -1174,13 +1357,6 @@ int container_sibling_index(struct sway_container *child) { | 
			
		
	
		
			
				
					|  |  |  |  | 	return list_find(container_get_siblings(child), child); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | list_t *container_get_current_siblings(struct sway_container *container) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (container->current.parent) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return container->current.parent->current.children; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	return container->current.workspace->current.tiling; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void container_handle_fullscreen_reparent(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (con->pending.fullscreen_mode != FULLSCREEN_WORKSPACE || !con->pending.workspace || | 
			
		
	
		
			
				
					|  |  |  |  | 			con->pending.workspace->fullscreen == con) { | 
			
		
	
	
		
			
				
					|  |  |  | @ -1395,7 +1571,7 @@ bool container_find_and_unmark(char *mark) { | 
			
		
	
		
			
				
					|  |  |  |  | 		if (strcmp(con_mark, mark) == 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 			free(con_mark); | 
			
		
	
		
			
				
					|  |  |  |  | 			list_del(con->marks, i); | 
			
		
	
		
			
				
					|  |  |  |  | 			container_update_marks_textures(con); | 
			
		
	
		
			
				
					|  |  |  |  | 			container_update_marks(con); | 
			
		
	
		
			
				
					|  |  |  |  | 			ipc_event_window(con, "mark"); | 
			
		
	
		
			
				
					|  |  |  |  | 			return true; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
	
		
			
				
					|  |  |  | @ -1426,70 +1602,15 @@ void container_add_mark(struct sway_container *con, char *mark) { | 
			
		
	
		
			
				
					|  |  |  |  | 	ipc_event_window(con, "mark"); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void update_marks_texture(struct sway_container *con, | 
			
		
	
		
			
				
					|  |  |  |  | 		struct wlr_texture **texture, struct border_colors *class) { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_output *output = container_get_effective_output(con); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!output) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	if (*texture) { | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_texture_destroy(*texture); | 
			
		
	
		
			
				
					|  |  |  |  | 		*texture = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!con->marks->length) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	size_t len = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 	for (int i = 0; i < con->marks->length; ++i) { | 
			
		
	
		
			
				
					|  |  |  |  | 		char *mark = con->marks->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 		if (mark[0] != '_') { | 
			
		
	
		
			
				
					|  |  |  |  | 			len += strlen(mark) + 2; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	char *buffer = calloc(len + 1, 1); | 
			
		
	
		
			
				
					|  |  |  |  | 	char *part = malloc(len + 1); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!sway_assert(buffer && part, "Unable to allocate memory")) { | 
			
		
	
		
			
				
					|  |  |  |  | 		free(buffer); | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	for (int i = 0; i < con->marks->length; ++i) { | 
			
		
	
		
			
				
					|  |  |  |  | 		char *mark = con->marks->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 		if (mark[0] != '_') { | 
			
		
	
		
			
				
					|  |  |  |  | 			snprintf(part, len + 1, "[%s]", mark); | 
			
		
	
		
			
				
					|  |  |  |  | 			strcat(buffer, part); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	free(part); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	render_titlebar_text_texture(output, con, texture, class, false, buffer); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	free(buffer); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void container_update_marks_textures(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!config->show_marks) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	update_marks_texture(con, &con->marks_focused, | 
			
		
	
		
			
				
					|  |  |  |  | 			&config->border_colors.focused); | 
			
		
	
		
			
				
					|  |  |  |  | 	update_marks_texture(con, &con->marks_focused_inactive, | 
			
		
	
		
			
				
					|  |  |  |  | 			&config->border_colors.focused_inactive); | 
			
		
	
		
			
				
					|  |  |  |  | 	update_marks_texture(con, &con->marks_unfocused, | 
			
		
	
		
			
				
					|  |  |  |  | 			&config->border_colors.unfocused); | 
			
		
	
		
			
				
					|  |  |  |  | 	update_marks_texture(con, &con->marks_urgent, | 
			
		
	
		
			
				
					|  |  |  |  | 			&config->border_colors.urgent); | 
			
		
	
		
			
				
					|  |  |  |  | 	update_marks_texture(con, &con->marks_focused_tab_title, | 
			
		
	
		
			
				
					|  |  |  |  | 			&config->border_colors.focused_tab_title); | 
			
		
	
		
			
				
					|  |  |  |  | 	container_damage_whole(con); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void container_raise_floating(struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	// Bring container to front by putting it at the end of the floating list.
 | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_container *floater = container_toplevel_ancestor(con); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (container_is_floating(floater) && floater->pending.workspace) { | 
			
		
	
		
			
				
					|  |  |  |  | 		// it's okay to just raise the scene directly instead of waiting
 | 
			
		
	
		
			
				
					|  |  |  |  | 		// for the transaction to go through. We won't be reconfiguring
 | 
			
		
	
		
			
				
					|  |  |  |  | 		// surfaces
 | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_scene_node_raise_to_top(&floater->scene_tree->node); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		list_move_to_end(floater->pending.workspace->floating, floater); | 
			
		
	
		
			
				
					|  |  |  |  | 		node_set_dirty(&floater->pending.workspace->node); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
	
		
			
				
					|  |  |  | 
 |