diff options
| author | emersion <contact@emersion.fr> | 2018-05-01 15:31:02 +0100 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-05-01 15:31:02 +0100 | 
| commit | 0e51c7be449dd68025d5acd8c634f8dcacb10a16 (patch) | |
| tree | c2c7e713a150c7f9a947b100e0fa4c56efb5c3b2 /sway/desktop/output.c | |
| parent | bf0603cd2d905554cc57d121b56b6708bb1d382b (diff) | |
| parent | cb07434913b89580a4025824cb181733b2db1eb7 (diff) | |
| download | sway-0e51c7be449dd68025d5acd8c634f8dcacb10a16.tar.xz | |
Merge pull request #1874 from RyanDwyer/borders
Implement borders
Diffstat (limited to 'sway/desktop/output.c')
| -rw-r--r-- | sway/desktop/output.c | 235 | 
1 files changed, 220 insertions, 15 deletions
| diff --git a/sway/desktop/output.c b/sway/desktop/output.c index d9ae890f..e0a211d1 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -116,8 +116,8 @@ static void surface_for_each_surface(struct wlr_surface *surface,  static void output_view_for_each_surface(struct sway_view *view,  		struct root_geometry *geo, wlr_surface_iterator_func_t iterator,  		void *user_data) { -	geo->x = view->swayc->x; -	geo->y = view->swayc->y; +	geo->x = view->x; +	geo->y = view->y;  	geo->width = view->surface->current->width;  	geo->height = view->surface->current->height;  	geo->rotation = 0; // TODO @@ -217,23 +217,228 @@ static void render_unmanaged(struct sway_output *output,  		render_surface_iterator, &data);  } -static void render_container_iterator(struct sway_container *con, -		void *_data) { -	struct sway_output *output = _data; -	if (!sway_assert(con->type == C_VIEW, "expected a view")) { -		return; +static void render_view(struct sway_view *view, struct sway_output *output) { +	struct render_data data = { .output = output, .alpha = view->swayc->alpha }; +	output_view_for_each_surface( +			view, &data.root_geo, render_surface_iterator, &data); +} + +/** + * Render decorations for a view with "border normal". + */ +static void render_container_simple_border_normal(struct sway_output *output, +		struct sway_container *con, struct border_colors *colors) { +	struct wlr_renderer *renderer = +		wlr_backend_get_renderer(output->wlr_output->backend); +	struct wlr_box box; +	float color[4]; +	color[3] = con->alpha; + +	// Child border - left edge +	memcpy(&color, colors->child_border, sizeof(float) * 3); +	box.x = con->x; +	box.y = con->y + 1; +	box.width = con->sway_view->border_thickness; +	box.height = con->height - 1; +	scale_box(&box, output->wlr_output->scale); +	wlr_render_rect(renderer, &box, color, +			output->wlr_output->transform_matrix); + +	// Child border - right edge +	if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) { +		memcpy(&color, colors->indicator, sizeof(float) * 3); +	} else { +		memcpy(&color, colors->child_border, sizeof(float) * 3);  	} -	struct render_data data = { .output = output, .alpha = con->alpha }; -	output_view_for_each_surface(con->sway_view, &data.root_geo, -		render_surface_iterator, &data); +	box.x = con->x + con->width - con->sway_view->border_thickness; +	box.y = con->y + 1; +	box.width = con->sway_view->border_thickness; +	box.height = con->height - 1; +	scale_box(&box, output->wlr_output->scale); +	wlr_render_rect(renderer, &box, color, +			output->wlr_output->transform_matrix); + +	// Child border - bottom edge +	if (con->parent->children->length == 1 && con->parent->layout == L_VERT) { +		memcpy(&color, colors->indicator, sizeof(float) * 3); +	} else { +		memcpy(&color, colors->child_border, sizeof(float) * 3); +	} +	box.x = con->x; +	box.y = con->y + con->height - con->sway_view->border_thickness; +	box.width = con->width; +	box.height = con->sway_view->border_thickness; +	scale_box(&box, output->wlr_output->scale); +	wlr_render_rect(renderer, &box, color, +			output->wlr_output->transform_matrix); + +	// Single pixel bar above title +	memcpy(&color, colors->border, sizeof(float) * 3); +	box.x = con->x; +	box.y = con->y; +	box.width = con->width; +	box.height = 1; +	scale_box(&box, output->wlr_output->scale); +	wlr_render_rect(renderer, &box, color, +			output->wlr_output->transform_matrix); + +	// Single pixel bar below title +	box.x = con->x + con->sway_view->border_thickness; +	box.y = con->sway_view->y - 1; +	box.width = con->width - con->sway_view->border_thickness * 2; +	box.height = 1; +	scale_box(&box, output->wlr_output->scale); +	wlr_render_rect(renderer, &box, color, +			output->wlr_output->transform_matrix); + +	// Title background +	memcpy(&color, colors->background, sizeof(float) * 3); +	box.x = con->x + con->sway_view->border_thickness; +	box.y = con->y + 1; +	box.width = con->width - con->sway_view->border_thickness * 2; +	box.height = con->sway_view->y - con->y - 2; +	scale_box(&box, output->wlr_output->scale); +	wlr_render_rect(renderer, &box, color, +			output->wlr_output->transform_matrix); + +	// Title text +	// TODO +} + +/** + * Render decorations for a view with "border pixel". + */ +static void render_container_simple_border_pixel(struct sway_output *output, +		struct sway_container *con, struct border_colors *colors) { +	struct wlr_renderer *renderer = +		wlr_backend_get_renderer(output->wlr_output->backend); +	struct wlr_box box; +	float color[4]; +	color[3] = con->alpha; + +	// Child border - left edge +	memcpy(&color, colors->child_border, sizeof(float) * 3); +	box.x = con->x; +	box.y = con->y; +	box.width = con->sway_view->border_thickness; +	box.height = con->height; +	scale_box(&box, output->wlr_output->scale); +	wlr_render_rect(renderer, &box, color, +			output->wlr_output->transform_matrix); + +	// Child border - right edge +	if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) { +		memcpy(&color, colors->indicator, sizeof(float) * 3); +	} else { +		memcpy(&color, colors->child_border, sizeof(float) * 3); +	} +	box.x = con->x + con->width - con->sway_view->border_thickness; +	box.y = con->y; +	box.width = con->sway_view->border_thickness; +	box.height = con->height; +	scale_box(&box, output->wlr_output->scale); +	wlr_render_rect(renderer, &box, color, +			output->wlr_output->transform_matrix); + +	// Child border - top edge +	box.x = con->x; +	box.y = con->y; +	box.width = con->width; +	box.height = con->sway_view->border_thickness; +	scale_box(&box, output->wlr_output->scale); +	wlr_render_rect(renderer, &box, color, +			output->wlr_output->transform_matrix); + +	// Child border - bottom edge +	if (con->parent->children->length == 1 && con->parent->layout == L_VERT) { +		memcpy(&color, colors->indicator, sizeof(float) * 3); +	} else { +		memcpy(&color, colors->child_border, sizeof(float) * 3); +	} +	box.x = con->x; +	box.y = con->y + con->height - con->sway_view->border_thickness; +	box.width = con->width; +	box.height = con->sway_view->border_thickness; +	scale_box(&box, output->wlr_output->scale); +	wlr_render_rect(renderer, &box, color, +			output->wlr_output->transform_matrix);  }  static void render_container(struct sway_output *output, +		struct sway_container *con); + +/** + * Render a container's children using a L_HORIZ or L_VERT layout. + * + * Wrap child views in borders and leave child containers borderless because + * they'll apply their own borders to their children. + */ +static void render_container_simple(struct sway_output *output,  		struct sway_container *con) { -	if (con->type == C_VIEW) { // Happens if a view is fullscreened -		render_container_iterator(con, output); -	} else { -		container_descendants(con, C_VIEW, render_container_iterator, output); +	struct sway_seat *seat = input_manager_current_seat(input_manager); +	struct sway_container *focus = seat_get_focus(seat); + +	for (int i = 0; i < con->children->length; ++i) { +		struct sway_container *child = con->children->items[i]; + +		if (child->type == C_VIEW) { +			if (child->sway_view->border != B_NONE) { +				struct border_colors *colors; +				if (focus == child) { +					colors = &config->border_colors.focused; +				} else if (seat_get_focus_inactive(seat, con) == child) { +					colors = &config->border_colors.focused_inactive; +				} else { +					colors = &config->border_colors.unfocused; +				} + +				if (child->sway_view->border == B_NORMAL) { +					render_container_simple_border_normal(output, child, +							colors); +				} else { +					render_container_simple_border_pixel(output, child, colors); +				} +			} +			render_view(child->sway_view, output); +		} else { +			render_container(output, child); +		} +	} +} + +/** + * Render a container's children using the L_TABBED layout. + */ +static void render_container_tabbed(struct sway_output *output, +		struct sway_container *con) { +	// TODO +} + +/** + * Render a container's children using the L_STACKED layout. + */ +static void render_container_stacked(struct sway_output *output, +		struct sway_container *con) { +	// TODO +} + +static void render_container(struct sway_output *output, +		struct sway_container *con) { +	switch (con->layout) { +	case L_NONE: +	case L_HORIZ: +	case L_VERT: +		render_container_simple(output, con); +		break; +	case L_STACKED: +		render_container_stacked(output, con); +		break; +	case L_TABBED: +		render_container_tabbed(output, con); +		break; +	case L_FLOATING: +		// TODO +		break;  	}  } @@ -282,7 +487,7 @@ static void render_output(struct sway_output *output, struct timespec *when,  		float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f};  		wlr_renderer_clear(renderer, clear_color);  		// TODO: handle views smaller than the output -		render_container(output, workspace->sway_workspace->fullscreen->swayc); +		render_view(workspace->sway_workspace->fullscreen, output);  		if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) {  			render_unmanaged(output, | 
