|  |  |  | @ -599,12 +599,195 @@ static void render_container_simple(struct sway_output *output, | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void render_tab(struct sway_output *output, pixman_region32_t *damage, | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_container *parent, int child_index, | 
			
		
	
		
			
				
					|  |  |  |  | 		struct border_colors *colors, struct wlr_texture *title_texture) { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_container *con = parent->children->items[child_index]; | 
			
		
	
		
			
				
					|  |  |  |  | 	float output_scale = output->wlr_output->scale; | 
			
		
	
		
			
				
					|  |  |  |  | 	float color[4]; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct wlr_box box; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	int tab_width = parent->width / parent->children->length; | 
			
		
	
		
			
				
					|  |  |  |  | 	int x = parent->x + tab_width * child_index; | 
			
		
	
		
			
				
					|  |  |  |  | 	// Make last tab use the remaining width of the parent
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (child_index == parent->children->length - 1) { | 
			
		
	
		
			
				
					|  |  |  |  | 		tab_width = parent->width - tab_width * child_index; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// Single pixel bar above title
 | 
			
		
	
		
			
				
					|  |  |  |  | 	memcpy(&color, colors->border, sizeof(float) * 4); | 
			
		
	
		
			
				
					|  |  |  |  | 	premultiply_alpha(color, con->alpha); | 
			
		
	
		
			
				
					|  |  |  |  | 	box.x = x; | 
			
		
	
		
			
				
					|  |  |  |  | 	box.y = parent->y; | 
			
		
	
		
			
				
					|  |  |  |  | 	box.width = tab_width; | 
			
		
	
		
			
				
					|  |  |  |  | 	box.height = 1; | 
			
		
	
		
			
				
					|  |  |  |  | 	scale_box(&box, output_scale); | 
			
		
	
		
			
				
					|  |  |  |  | 	render_rect(output->wlr_output, damage, &box, color); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// Single pixel bar below title
 | 
			
		
	
		
			
				
					|  |  |  |  | 	box.y = (parent->y + config->border_thickness * 2 + config->font_height - 1) | 
			
		
	
		
			
				
					|  |  |  |  | 		* output_scale; | 
			
		
	
		
			
				
					|  |  |  |  | 	render_rect(output->wlr_output, damage, &box, color); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// Single pixel bar on left
 | 
			
		
	
		
			
				
					|  |  |  |  | 	box.x = x; | 
			
		
	
		
			
				
					|  |  |  |  | 	box.y = parent->y + 1; | 
			
		
	
		
			
				
					|  |  |  |  | 	box.width = 1; | 
			
		
	
		
			
				
					|  |  |  |  | 	box.height = config->border_thickness * 2 + config->font_height - 2; | 
			
		
	
		
			
				
					|  |  |  |  | 	scale_box(&box, output_scale); | 
			
		
	
		
			
				
					|  |  |  |  | 	render_rect(output->wlr_output, damage, &box, color); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// Single pixel bar on right
 | 
			
		
	
		
			
				
					|  |  |  |  | 	box.x = (x + tab_width - 1) * output_scale; | 
			
		
	
		
			
				
					|  |  |  |  | 	render_rect(output->wlr_output, damage, &box, color); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// Title text
 | 
			
		
	
		
			
				
					|  |  |  |  | 	size_t title_width = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 	if (title_texture) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct wlr_box texture_box; | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_texture_get_size(title_texture, | 
			
		
	
		
			
				
					|  |  |  |  | 			&texture_box.width, &texture_box.height); | 
			
		
	
		
			
				
					|  |  |  |  | 		texture_box.x = (x + 1 + config->border_thickness) * output_scale; | 
			
		
	
		
			
				
					|  |  |  |  | 		texture_box.y = (parent->y + config->border_thickness) * output_scale; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		float matrix[9]; | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_matrix_project_box(matrix, &texture_box, | 
			
		
	
		
			
				
					|  |  |  |  | 			WL_OUTPUT_TRANSFORM_NORMAL, | 
			
		
	
		
			
				
					|  |  |  |  | 			0.0, output->wlr_output->transform_matrix); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		int available = (tab_width - config->border_thickness * 2 - 2) | 
			
		
	
		
			
				
					|  |  |  |  | 			* output_scale; | 
			
		
	
		
			
				
					|  |  |  |  | 		if (texture_box.width > available) { | 
			
		
	
		
			
				
					|  |  |  |  | 			texture_box.width = available; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		render_texture(output->wlr_output, damage, title_texture, | 
			
		
	
		
			
				
					|  |  |  |  | 			&texture_box, matrix, 1.0); | 
			
		
	
		
			
				
					|  |  |  |  | 		title_width = texture_box.width; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// Title background - above the text
 | 
			
		
	
		
			
				
					|  |  |  |  | 	memcpy(&color, colors->background, sizeof(float) * 4); | 
			
		
	
		
			
				
					|  |  |  |  | 	premultiply_alpha(color, con->alpha); | 
			
		
	
		
			
				
					|  |  |  |  | 	box.x = x + 1; | 
			
		
	
		
			
				
					|  |  |  |  | 	box.y = parent->y + 1; | 
			
		
	
		
			
				
					|  |  |  |  | 	box.width = tab_width - 2; | 
			
		
	
		
			
				
					|  |  |  |  | 	box.height = config->border_thickness - 1; | 
			
		
	
		
			
				
					|  |  |  |  | 	scale_box(&box, output_scale); | 
			
		
	
		
			
				
					|  |  |  |  | 	render_rect(output->wlr_output, damage, &box, color); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// Title background - below the text
 | 
			
		
	
		
			
				
					|  |  |  |  | 	box.y = (parent->y + config->border_thickness + config->font_height) | 
			
		
	
		
			
				
					|  |  |  |  | 		* output_scale; | 
			
		
	
		
			
				
					|  |  |  |  | 	render_rect(output->wlr_output, damage, &box, color); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// Title background - left of text
 | 
			
		
	
		
			
				
					|  |  |  |  | 	box.x = x + 1; | 
			
		
	
		
			
				
					|  |  |  |  | 	box.y = parent->y + config->border_thickness; | 
			
		
	
		
			
				
					|  |  |  |  | 	box.width = config->border_thickness; | 
			
		
	
		
			
				
					|  |  |  |  | 	box.height = config->font_height; | 
			
		
	
		
			
				
					|  |  |  |  | 	scale_box(&box, output_scale); | 
			
		
	
		
			
				
					|  |  |  |  | 	render_rect(output->wlr_output, damage, &box, color); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// Title background - right of text
 | 
			
		
	
		
			
				
					|  |  |  |  | 	box.x = (x + 1 + config->border_thickness) * output_scale + title_width; | 
			
		
	
		
			
				
					|  |  |  |  | 	box.y = (parent->y + config->border_thickness) * output_scale; | 
			
		
	
		
			
				
					|  |  |  |  | 	box.width = (tab_width - config->border_thickness - 2) * output_scale | 
			
		
	
		
			
				
					|  |  |  |  | 		- title_width; | 
			
		
	
		
			
				
					|  |  |  |  | 	box.height = config->font_height * output_scale; | 
			
		
	
		
			
				
					|  |  |  |  | 	render_rect(output->wlr_output, damage, &box, color); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void render_tab_content(struct sway_output *output, | 
			
		
	
		
			
				
					|  |  |  |  | 		pixman_region32_t *damage, struct sway_container *con, | 
			
		
	
		
			
				
					|  |  |  |  | 		struct border_colors *colors) { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_view *view = con->sway_view; | 
			
		
	
		
			
				
					|  |  |  |  | 	render_view(view, output, damage); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	struct wlr_box box; | 
			
		
	
		
			
				
					|  |  |  |  | 	float output_scale = output->wlr_output->scale; | 
			
		
	
		
			
				
					|  |  |  |  | 	float color[4]; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (view->border != B_NONE) { | 
			
		
	
		
			
				
					|  |  |  |  | 		if (view->border_left) { | 
			
		
	
		
			
				
					|  |  |  |  | 			memcpy(&color, colors->child_border, sizeof(float) * 4); | 
			
		
	
		
			
				
					|  |  |  |  | 			premultiply_alpha(color, con->alpha); | 
			
		
	
		
			
				
					|  |  |  |  | 			box.x = con->x; | 
			
		
	
		
			
				
					|  |  |  |  | 			box.y = con->y + config->border_thickness * 2 + config->font_height; | 
			
		
	
		
			
				
					|  |  |  |  | 			box.width = view->border_thickness; | 
			
		
	
		
			
				
					|  |  |  |  | 			box.height = view->height; | 
			
		
	
		
			
				
					|  |  |  |  | 			scale_box(&box, output_scale); | 
			
		
	
		
			
				
					|  |  |  |  | 			render_rect(output->wlr_output, damage, &box, color); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (view->border_right) { | 
			
		
	
		
			
				
					|  |  |  |  | 			memcpy(&color, colors->child_border, sizeof(float) * 4); | 
			
		
	
		
			
				
					|  |  |  |  | 			premultiply_alpha(color, con->alpha); | 
			
		
	
		
			
				
					|  |  |  |  | 			box.x = view->x + view->width; | 
			
		
	
		
			
				
					|  |  |  |  | 			box.y = con->y + config->border_thickness * 2 + config->font_height; | 
			
		
	
		
			
				
					|  |  |  |  | 			box.width = view->border_thickness; | 
			
		
	
		
			
				
					|  |  |  |  | 			box.height = view->height; | 
			
		
	
		
			
				
					|  |  |  |  | 			scale_box(&box, output_scale); | 
			
		
	
		
			
				
					|  |  |  |  | 			render_rect(output->wlr_output, damage, &box, color); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (view->border_bottom) { | 
			
		
	
		
			
				
					|  |  |  |  | 			memcpy(&color, colors->child_border, sizeof(float) * 4); | 
			
		
	
		
			
				
					|  |  |  |  | 			premultiply_alpha(color, con->alpha); | 
			
		
	
		
			
				
					|  |  |  |  | 			box.x = con->x; | 
			
		
	
		
			
				
					|  |  |  |  | 			box.y = view->y + view->height; | 
			
		
	
		
			
				
					|  |  |  |  | 			box.width = con->width; | 
			
		
	
		
			
				
					|  |  |  |  | 			box.height = view->border_thickness; | 
			
		
	
		
			
				
					|  |  |  |  | 			scale_box(&box, output_scale); | 
			
		
	
		
			
				
					|  |  |  |  | 			render_rect(output->wlr_output, damage, &box, color); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /**
 | 
			
		
	
		
			
				
					|  |  |  |  |  * Render a container's children using the L_TABBED layout. | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | static void render_container_tabbed(struct sway_output *output, | 
			
		
	
		
			
				
					|  |  |  |  | 		pixman_region32_t *damage, struct sway_container *con) { | 
			
		
	
		
			
				
					|  |  |  |  | 	// TODO
 | 
			
		
	
		
			
				
					|  |  |  |  | 		pixman_region32_t *damage, struct sway_container *con, | 
			
		
	
		
			
				
					|  |  |  |  | 		bool parent_focused) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!con->children->length) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_seat *seat = input_manager_current_seat(input_manager); | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_container *focus = seat_get_focus(seat); | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_container *current = seat_get_active_child(seat, con); | 
			
		
	
		
			
				
					|  |  |  |  | 	struct border_colors *current_colors = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// Render tabs
 | 
			
		
	
		
			
				
					|  |  |  |  | 	for (int i = 0; i < con->children->length; ++i) { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_container *child = con->children->items[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 		struct border_colors *colors; | 
			
		
	
		
			
				
					|  |  |  |  | 		struct wlr_texture *title_texture; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (focus == child || parent_focused) { | 
			
		
	
		
			
				
					|  |  |  |  | 			colors = &config->border_colors.focused; | 
			
		
	
		
			
				
					|  |  |  |  | 			title_texture = child->title_focused; | 
			
		
	
		
			
				
					|  |  |  |  | 		} else if (child == current) { | 
			
		
	
		
			
				
					|  |  |  |  | 			colors = &config->border_colors.focused_inactive; | 
			
		
	
		
			
				
					|  |  |  |  | 			title_texture = child->title_focused_inactive; | 
			
		
	
		
			
				
					|  |  |  |  | 		} else { | 
			
		
	
		
			
				
					|  |  |  |  | 			colors = &config->border_colors.unfocused; | 
			
		
	
		
			
				
					|  |  |  |  | 			title_texture = child->title_unfocused; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		render_tab(output, damage, con, i, colors, title_texture); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (child == current) { | 
			
		
	
		
			
				
					|  |  |  |  | 			current_colors = colors; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// Render surface and left/right/bottom borders
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (current->type == C_VIEW) { | 
			
		
	
		
			
				
					|  |  |  |  | 		render_tab_content(output, damage, current, current_colors); | 
			
		
	
		
			
				
					|  |  |  |  | 	} else { | 
			
		
	
		
			
				
					|  |  |  |  | 		render_container(output, damage, current, | 
			
		
	
		
			
				
					|  |  |  |  | 				parent_focused || current == focus); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /**
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -628,7 +811,7 @@ static void render_container(struct sway_output *output, | 
			
		
	
		
			
				
					|  |  |  |  | 		render_container_stacked(output, damage, con); | 
			
		
	
		
			
				
					|  |  |  |  | 		break; | 
			
		
	
		
			
				
					|  |  |  |  | 	case L_TABBED: | 
			
		
	
		
			
				
					|  |  |  |  | 		render_container_tabbed(output, damage, con); | 
			
		
	
		
			
				
					|  |  |  |  | 		render_container_tabbed(output, damage, con, parent_focused); | 
			
		
	
		
			
				
					|  |  |  |  | 		break; | 
			
		
	
		
			
				
					|  |  |  |  | 	case L_FLOATING: | 
			
		
	
		
			
				
					|  |  |  |  | 		// TODO
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -896,9 +1079,7 @@ static void output_damage_view(struct sway_output *output, | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_container *workspace = container_parent(view->swayc, | 
			
		
	
		
			
				
					|  |  |  |  | 			C_WORKSPACE); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (workspace->sway_workspace->fullscreen && !view->is_fullscreen) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!view_is_visible(view)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | 
 |