diff options
Diffstat (limited to 'sway/desktop')
| -rw-r--r-- | sway/desktop/output.c | 223 | 
1 files changed, 144 insertions, 79 deletions
| diff --git a/sway/desktop/output.c b/sway/desktop/output.c index dea51bdf..1b3143d0 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -66,6 +66,10 @@ struct root_geometry {  static bool get_surface_box(struct root_geometry *geo,  		struct sway_output *output, struct wlr_surface *surface, int sx, int sy,  		struct wlr_box *surface_box) { +	if (!wlr_surface_has_buffer(surface)) { +		return false; +	} +  	int sw = surface->current->width;  	int sh = surface->current->height; @@ -95,7 +99,7 @@ static bool get_surface_box(struct root_geometry *geo,  	return wlr_box_intersection(&output_box, &rotated_box, &intersection);  } -static void output_surface_for_each_surface(struct wlr_surface *surface, +static void surface_for_each_surface(struct wlr_surface *surface,  		double ox, double oy, struct root_geometry *geo,  		wlr_surface_iterator_func_t iterator, void *user_data) {  	geo->x = ox; @@ -119,6 +123,34 @@ static void output_view_for_each_surface(struct sway_view *view,  	view_for_each_surface(view, iterator, user_data);  } +static void layer_for_each_surface(struct wl_list *layer_surfaces, +		struct root_geometry *geo, wlr_surface_iterator_func_t iterator, +		void *user_data) { +	struct sway_layer_surface *layer_surface; +	wl_list_for_each(layer_surface, layer_surfaces, link) { +		struct wlr_layer_surface *wlr_layer_surface = +			layer_surface->layer_surface; +		surface_for_each_surface(wlr_layer_surface->surface, +			layer_surface->geo.x, layer_surface->geo.y, geo, iterator, +			user_data); +	} +} + +static void unmanaged_for_each_surface(struct wl_list *unmanaged, +		struct sway_output *output, struct root_geometry *geo, +		wlr_surface_iterator_func_t iterator, void *user_data) { +	struct sway_xwayland_unmanaged *unmanaged_surface; +	wl_list_for_each(unmanaged_surface, unmanaged, link) { +		struct wlr_xwayland_surface *xsurface = +			unmanaged_surface->wlr_xwayland_surface; +		double ox = unmanaged_surface->lx - output->swayc->x; +		double oy = unmanaged_surface->ly - output->swayc->y; + +		surface_for_each_surface(xsurface->surface, ox, oy, geo, +			iterator, user_data); +	} +} +  static void scale_box(struct wlr_box *box, float scale) {  	box->x *= scale;  	box->y *= scale; @@ -129,7 +161,6 @@ static void scale_box(struct wlr_box *box, float scale) {  struct render_data {  	struct root_geometry root_geo;  	struct sway_output *output; -	struct timespec *when;  	float alpha;  }; @@ -137,7 +168,6 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy,  		void *_data) {  	struct render_data *data = _data;  	struct wlr_output *wlr_output = data->output->wlr_output; -	struct timespec *when = data->when;  	float rotation = data->root_geo.rotation;  	float alpha = data->alpha; @@ -169,59 +199,52 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy,  	wlr_render_texture_with_matrix(renderer, surface->texture,  		matrix, alpha); - -	// TODO: don't send the frame done event now -	wlr_surface_send_frame_done(surface, when);  } -static void render_surface(struct sway_output *output, struct timespec *when, -		struct wlr_surface *surface, double ox, double oy) { -	struct render_data data = { -		.output = output, -		.when = when, -		.alpha = 1.0f, -	}; - -	output_surface_for_each_surface(surface, ox, oy, &data.root_geo, +static void render_layer(struct sway_output *output, +		struct wl_list *layer_surfaces) { +	struct render_data data = { .output = output, .alpha = 1.0f }; +	layer_for_each_surface(layer_surfaces, &data.root_geo,  		render_surface_iterator, &data);  } -static void render_view(struct sway_output *output, struct timespec *when, -		struct sway_view *view) { -	struct render_data data = { -		.output = output, -		.when = when, -		.alpha = view->swayc->alpha, -	}; - -	output_view_for_each_surface(view, &data.root_geo, +static void render_unmanaged(struct sway_output *output, +		struct wl_list *unmanaged) { +	struct render_data data = { .output = output, .alpha = 1.0f }; +	unmanaged_for_each_surface(unmanaged, output, &data.root_geo,  		render_surface_iterator, &data);  } -static void render_layer(struct sway_output *output, struct timespec *when, -		struct wl_list *layer_surfaces) { -	struct sway_layer_surface *layer_surface; -	wl_list_for_each(layer_surface, layer_surfaces, link) { -		struct wlr_layer_surface *wlr_layer_surface = -			layer_surface->layer_surface; -		render_surface(output, when, wlr_layer_surface->surface, -			layer_surface->geo.x, layer_surface->geo.y); +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;  	} +	struct render_data data = { .output = output, .alpha = con->alpha }; +	output_view_for_each_surface(con->sway_view, &data.root_geo, +		render_surface_iterator, &data);  } -struct render_view_data { -	struct sway_output *output; -	struct timespec *when; -}; - -static void render_view_iterator(struct sway_container *con, void *_data) { -	struct render_view_data *data = _data; +static void render_container(struct sway_output *output, +		struct sway_container *con) { +	container_descendants(con, C_VIEW, render_container_iterator, output); +} -	if (!sway_assert(con->type == C_VIEW, "expected a view")) { -		return; +static struct sway_container *output_get_active_workspace( +		struct sway_output *output) { +	struct sway_seat *seat = input_manager_current_seat(input_manager); +	struct sway_container *focus = +		seat_get_focus_inactive(seat, output->swayc); +	if (!focus) { +		// We've never been to this output before +		focus = output->swayc->children->items[0];  	} - -	render_view(data->output, data->when, con->sway_view); +	struct sway_container *workspace = focus; +	if (workspace->type != C_WORKSPACE) { +		workspace = container_parent(workspace, C_WORKSPACE); +	} +	return workspace;  }  static void render_output(struct sway_output *output, struct timespec *when, @@ -250,40 +273,17 @@ static void render_output(struct sway_output *output, struct timespec *when,  	float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};  	wlr_renderer_clear(renderer, clear_color); -	render_layer(output, when, -		&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); -	render_layer(output, when, -		&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); +	render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); +	render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); -	// Render all views in the current workspace -	struct sway_seat *seat = input_manager_current_seat(input_manager); -	struct sway_container *focus = -		seat_get_focus_inactive(seat, output->swayc); -	if (!focus) { -		// We've never been to this output before -		focus = output->swayc->children->items[0]; -	} -	struct sway_container *workspace = focus->type == C_WORKSPACE ? -		focus : container_parent(focus, C_WORKSPACE); -	struct render_view_data data = { .output = output, .when = when }; -	container_descendants(workspace, C_VIEW, render_view_iterator, &data); +	struct sway_container *workspace = output_get_active_workspace(output); +	render_container(output, workspace); -	// Render unmanaged views on top -	struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; -	struct sway_xwayland_unmanaged *unmanaged_surface; -	wl_list_for_each(unmanaged_surface, unmanaged, link) { -		struct wlr_xwayland_surface *xsurface = -			unmanaged_surface->wlr_xwayland_surface; -		double ox = unmanaged_surface->lx - output->swayc->x; -		double oy = unmanaged_surface->ly - output->swayc->y; -		render_surface(output, when, xsurface->surface, ox, oy); -	} +	render_unmanaged(output, &root_container.sway_root->xwayland_unmanaged);  	// TODO: consider revising this when fullscreen windows are supported -	render_layer(output, when, -		&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); -	render_layer(output, when, -		&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); +	render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); +	render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);  renderer_end:  	if (root_container.sway_root->debug_tree) { @@ -298,6 +298,74 @@ renderer_end:  	output->last_frame = *when;  } +struct send_frame_done_data { +	struct root_geometry root_geo; +	struct sway_output *output; +	struct timespec *when; +}; + +static void send_frame_done_iterator(struct wlr_surface *surface, +		int sx, int sy, void *_data) { +	struct send_frame_done_data *data = _data; + +	bool intersects = get_surface_box(&data->root_geo, data->output, surface, +		sx, sy, NULL); +	if (intersects) { +		wlr_surface_send_frame_done(surface, data->when); +	} +} + +static void send_frame_done_layer(struct send_frame_done_data *data, +		struct wl_list *layer_surfaces) { +	layer_for_each_surface(layer_surfaces, &data->root_geo, +		send_frame_done_iterator, data); +} + +static void send_frame_done_unmanaged(struct send_frame_done_data *data, +		struct wl_list *unmanaged) { +	unmanaged_for_each_surface(unmanaged, data->output, &data->root_geo, +		send_frame_done_iterator, data); +} + +static void send_frame_done_container_iterator(struct sway_container *con, +		void *_data) { +	struct send_frame_done_data *data = _data; +	if (!sway_assert(con->type == C_VIEW, "expected a view")) { +		return; +	} +	output_view_for_each_surface(con->sway_view, &data->root_geo, +		send_frame_done_iterator, data); +} + +static void send_frame_done_container(struct send_frame_done_data *data, +		struct sway_container *con) { +	container_descendants(con, C_VIEW, +		send_frame_done_container_iterator, data); +} + +static void send_frame_done(struct sway_output *output, struct timespec *when) { +	struct send_frame_done_data data = { +		.output = output, +		.when = when, +	}; + +	send_frame_done_layer(&data, +		&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); +	send_frame_done_layer(&data, +		&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); + +	struct sway_container *workspace = output_get_active_workspace(output); +	send_frame_done_container(&data, workspace); + +	send_frame_done_unmanaged(&data, +		&root_container.sway_root->xwayland_unmanaged); + +	send_frame_done_layer(&data, +		&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); +	send_frame_done_layer(&data, +		&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); +} +  static void damage_handle_frame(struct wl_listener *listener, void *data) {  	struct sway_output *output =  		wl_container_of(listener, output, damage_frame); @@ -322,7 +390,8 @@ static void damage_handle_frame(struct wl_listener *listener, void *data) {  	pixman_region32_fini(&damage); -	// TODO: send frame done events here instead of inside render_surface +	// Send frame done to all visible surfaces +	send_frame_done(output, &now);  }  void output_damage_whole(struct sway_output *output) { @@ -342,10 +411,6 @@ static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy,  	float rotation = data->root_geo.rotation;  	bool whole = data->whole; -	if (!wlr_surface_has_buffer(surface)) { -		return; -	} -  	struct wlr_box box;  	bool intersects = get_surface_box(&data->root_geo, data->output, surface,  		sx, sy, &box); @@ -387,7 +452,7 @@ void output_damage_surface(struct sway_output *output, double ox, double oy,  		.whole = whole,  	}; -	output_surface_for_each_surface(surface, ox, oy, &data.root_geo, +	surface_for_each_surface(surface, ox, oy, &data.root_geo,  		damage_surface_iterator, &data);  } | 
