diff options
Diffstat (limited to 'rootston/output.c')
| -rw-r--r-- | rootston/output.c | 101 | 
1 files changed, 91 insertions, 10 deletions
diff --git a/rootston/output.c b/rootston/output.c index 52ece54d..bf2bbdc2 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -13,6 +13,7 @@  #include <wlr/util/log.h>  #include <wlr/util/region.h>  #include "rootston/config.h" +#include "rootston/layers.h"  #include "rootston/output.h"  #include "rootston/server.h" @@ -417,6 +418,33 @@ static void surface_send_frame_done(struct wlr_surface *surface, double lx,  	wlr_surface_send_frame_done(surface, when);  } +static void render_layer( +		struct roots_output *output, +		const struct wlr_box *output_layout_box, +		struct render_data *data, +		struct wl_list *layer) { +	struct roots_layer_surface *roots_surface; +	wl_list_for_each(roots_surface, layer, link) { +		struct wlr_layer_surface *layer = roots_surface->layer_surface; +		render_surface(layer->surface, +				roots_surface->geo.x + output_layout_box->x, +				roots_surface->geo.y + output_layout_box->y, +				0, data); +	} +} + +static void layers_send_done( +		struct roots_output *output, struct timespec *when) { +	size_t len = sizeof(output->layers) / sizeof(output->layers[0]); +	for (size_t i = 0; i < len; ++i) { +		struct roots_layer_surface *roots_surface; +		wl_list_for_each(roots_surface, &output->layers[i], link) { +			struct wlr_layer_surface *layer = roots_surface->layer_surface; +			wlr_surface_send_frame_done(layer->surface, when); +		} +	} +} +  static void render_output(struct roots_output *output) {  	struct wlr_output *wlr_output = output->wlr_output;  	struct roots_desktop *desktop = output->desktop; @@ -433,14 +461,15 @@ static void render_output(struct roots_output *output) {  	float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; +	const struct wlr_box *output_box = +		wlr_output_layout_get_box(desktop->layout, wlr_output); +  	// Check if we can delegate the fullscreen surface to the output  	if (output->fullscreen_view != NULL &&  			output->fullscreen_view->wlr_surface != NULL) {  		struct roots_view *view = output->fullscreen_view;  		// Make sure the view is centered on screen -		const struct wlr_box *output_box = -			wlr_output_layout_get_box(desktop->layout, wlr_output);  		struct wlr_box view_box;  		view_get_box(view, &view_box);  		double view_x = (double)(output_box->width - view_box.width) / 2 + @@ -498,6 +527,11 @@ static void render_output(struct roots_output *output) {  		wlr_renderer_clear(renderer, clear_color);  	} +	render_layer(output, output_box, &data, +			&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); +	render_layer(output, output_box, &data, +			&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); +  	// If a view is fullscreen on this output, render it  	if (output->fullscreen_view != NULL) {  		struct roots_view *view = output->fullscreen_view; @@ -520,20 +554,24 @@ static void render_output(struct roots_output *output) {  				render_surface, &data);  		}  #endif - -		goto renderer_end; -	} - -	// Render all views -	struct roots_view *view; -	wl_list_for_each_reverse(view, &desktop->views, link) { -		render_view(view, &data); +	} else { +		// Render all views +		struct roots_view *view; +		wl_list_for_each_reverse(view, &desktop->views, link) { +			render_view(view, &data); +		} +		// Render top layer above shell views +		render_layer(output, output_box, &data, +				&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);  	}  	// Render drag icons  	data.alpha = 1.0;  	drag_icons_for_each_surface(server->input, render_surface, &data); +	render_layer(output, output_box, &data, +			&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); +  renderer_end:  	wlr_renderer_scissor(renderer, NULL);  	wlr_renderer_end(renderer); @@ -570,6 +608,7 @@ damage_finish:  		drag_icons_for_each_surface(server->input, surface_send_frame_done,  			&data);  	} +	layers_send_done(output, data.when);  }  void output_damage_whole(struct roots_output *output) { @@ -626,6 +665,15 @@ static void damage_whole_surface(struct wlr_surface *surface,  	wlr_output_damage_add_box(output->damage, &box);  } +void output_damage_whole_local_surface(struct roots_output *output, +		struct wlr_surface *surface, double ox, double oy, float rotation) { +	struct wlr_output_layout_output *layout = wlr_output_layout_get( +		output->desktop->layout, output->wlr_output); +	damage_whole_surface(surface, ox + layout->x, oy + layout->y, +			rotation, output); +	// TODO: subsurfaces +} +  static void damage_whole_decoration(struct roots_view *view,  		struct roots_output *output) {  	if (!view->decorated || view->wlr_surface == NULL) { @@ -691,6 +739,15 @@ static void damage_from_surface(struct wlr_surface *surface,  	pixman_region32_fini(&damage);  } +void output_damage_from_local_surface(struct roots_output *output, +		struct wlr_surface *surface, double ox, double oy, float rotation) { +	struct wlr_output_layout_output *layout = wlr_output_layout_get( +		output->desktop->layout, output->wlr_output); +	damage_from_surface(surface, ox + layout->x, oy + layout->y, +			rotation, output); +	// TODO: Subsurfaces +} +  void output_damage_from_view(struct roots_output *output,  		struct roots_view *view) {  	if (!view_accept_damage(output, view)) { @@ -759,6 +816,18 @@ static void output_damage_handle_destroy(struct wl_listener *listener,  	output_destroy(output);  } +static void output_handle_mode(struct wl_listener *listener, void *data) { +	struct roots_output *output = +		wl_container_of(listener, output, mode); +	arrange_layers(output); +} + +static void output_handle_transform(struct wl_listener *listener, void *data) { +	struct roots_output *output = +		wl_container_of(listener, output, transform); +	arrange_layers(output); +} +  void handle_new_output(struct wl_listener *listener, void *data) {  	struct roots_desktop *desktop = wl_container_of(listener, desktop,  		new_output); @@ -781,17 +850,28 @@ void handle_new_output(struct wl_listener *listener, void *data) {  	clock_gettime(CLOCK_MONOTONIC, &output->last_frame);  	output->desktop = desktop;  	output->wlr_output = wlr_output; +	wlr_output->data = output;  	wl_list_insert(&desktop->outputs, &output->link);  	output->damage = wlr_output_damage_create(wlr_output);  	output->destroy.notify = output_handle_destroy;  	wl_signal_add(&wlr_output->events.destroy, &output->destroy); +	output->mode.notify = output_handle_mode; +	wl_signal_add(&wlr_output->events.mode, &output->mode); +	output->transform.notify = output_handle_transform; +	wl_signal_add(&wlr_output->events.transform, &output->transform); +  	output->damage_frame.notify = output_damage_handle_frame;  	wl_signal_add(&output->damage->events.frame, &output->damage_frame);  	output->damage_destroy.notify = output_damage_handle_destroy;  	wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); +	size_t len = sizeof(output->layers) / sizeof(output->layers[0]); +	for (size_t i = 0; i < len; ++i) { +		wl_list_init(&output->layers[i]); +	} +  	struct roots_output_config *output_config =  		roots_config_get_output(config, wlr_output);  	if (output_config) { @@ -816,5 +896,6 @@ void handle_new_output(struct wl_listener *listener, void *data) {  		roots_seat_configure_xcursor(seat);  	} +	arrange_layers(output);  	output_damage_whole(output);  }  | 
