|  |  |  | @ -23,6 +23,7 @@ | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/layers.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/output.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/server.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/surface.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/tree/arrange.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/tree/container.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "sway/tree/root.h" | 
			
		
	
	
		
			
				
					|  |  |  | @ -80,6 +81,7 @@ struct surface_iterator_data { | 
			
		
	
		
			
				
					|  |  |  |  | 	void *user_data; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_output *output; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_view *view; | 
			
		
	
		
			
				
					|  |  |  |  | 	double ox, oy; | 
			
		
	
		
			
				
					|  |  |  |  | 	int width, height; | 
			
		
	
		
			
				
					|  |  |  |  | 	float rotation; | 
			
		
	
	
		
			
				
					|  |  |  | @ -134,7 +136,7 @@ static void output_for_each_surface_iterator(struct wlr_surface *surface, | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	data->user_iterator(data->output, surface, &box, data->rotation, | 
			
		
	
		
			
				
					|  |  |  |  | 	data->user_iterator(data->output, data->view, surface, &box, data->rotation, | 
			
		
	
		
			
				
					|  |  |  |  | 		data->user_data); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -145,6 +147,7 @@ void output_surface_for_each_surface(struct sway_output *output, | 
			
		
	
		
			
				
					|  |  |  |  | 		.user_iterator = iterator, | 
			
		
	
		
			
				
					|  |  |  |  | 		.user_data = user_data, | 
			
		
	
		
			
				
					|  |  |  |  | 		.output = output, | 
			
		
	
		
			
				
					|  |  |  |  | 		.view = NULL, | 
			
		
	
		
			
				
					|  |  |  |  | 		.ox = ox, | 
			
		
	
		
			
				
					|  |  |  |  | 		.oy = oy, | 
			
		
	
		
			
				
					|  |  |  |  | 		.width = surface->current.width, | 
			
		
	
	
		
			
				
					|  |  |  | @ -163,6 +166,7 @@ void output_view_for_each_surface(struct sway_output *output, | 
			
		
	
		
			
				
					|  |  |  |  | 		.user_iterator = iterator, | 
			
		
	
		
			
				
					|  |  |  |  | 		.user_data = user_data, | 
			
		
	
		
			
				
					|  |  |  |  | 		.output = output, | 
			
		
	
		
			
				
					|  |  |  |  | 		.view = view, | 
			
		
	
		
			
				
					|  |  |  |  | 		.ox = view->container->surface_x - output->lx | 
			
		
	
		
			
				
					|  |  |  |  | 			- view->geometry.x, | 
			
		
	
		
			
				
					|  |  |  |  | 		.oy = view->container->surface_y - output->ly | 
			
		
	
	
		
			
				
					|  |  |  | @ -182,6 +186,7 @@ void output_view_for_each_popup(struct sway_output *output, | 
			
		
	
		
			
				
					|  |  |  |  | 		.user_iterator = iterator, | 
			
		
	
		
			
				
					|  |  |  |  | 		.user_data = user_data, | 
			
		
	
		
			
				
					|  |  |  |  | 		.output = output, | 
			
		
	
		
			
				
					|  |  |  |  | 		.view = view, | 
			
		
	
		
			
				
					|  |  |  |  | 		.ox = view->container->surface_x - output->lx | 
			
		
	
		
			
				
					|  |  |  |  | 			- view->geometry.x, | 
			
		
	
		
			
				
					|  |  |  |  | 		.oy = view->container->surface_y - output->ly | 
			
		
	
	
		
			
				
					|  |  |  | @ -224,6 +229,7 @@ void output_layer_for_each_surface(struct sway_output *output, | 
			
		
	
		
			
				
					|  |  |  |  | 				.user_iterator = iterator, | 
			
		
	
		
			
				
					|  |  |  |  | 				.user_data = user_data, | 
			
		
	
		
			
				
					|  |  |  |  | 				.output = output, | 
			
		
	
		
			
				
					|  |  |  |  | 				.view = NULL, | 
			
		
	
		
			
				
					|  |  |  |  | 				.ox = popup_sx, | 
			
		
	
		
			
				
					|  |  |  |  | 				.oy = popup_sy, | 
			
		
	
		
			
				
					|  |  |  |  | 				.width = surface->current.width, | 
			
		
	
	
		
			
				
					|  |  |  | @ -291,6 +297,7 @@ static void output_for_each_surface(struct sway_output *output, | 
			
		
	
		
			
				
					|  |  |  |  | 		.user_iterator = iterator, | 
			
		
	
		
			
				
					|  |  |  |  | 		.user_data = user_data, | 
			
		
	
		
			
				
					|  |  |  |  | 		.output = output, | 
			
		
	
		
			
				
					|  |  |  |  | 		.view = NULL, | 
			
		
	
		
			
				
					|  |  |  |  | 	}; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_workspace *workspace = output_get_active_workspace(output); | 
			
		
	
	
		
			
				
					|  |  |  | @ -401,18 +408,37 @@ bool output_has_opaque_overlay_layer_surface(struct sway_output *output) { | 
			
		
	
		
			
				
					|  |  |  |  | 	return false; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void send_frame_done_iterator(struct sway_output *output, | 
			
		
	
		
			
				
					|  |  |  |  | struct send_frame_done_data { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct timespec when; | 
			
		
	
		
			
				
					|  |  |  |  | 	int msec_until_refresh; | 
			
		
	
		
			
				
					|  |  |  |  | }; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void send_frame_done_iterator(struct sway_output *output, struct sway_view *view, | 
			
		
	
		
			
				
					|  |  |  |  | 		struct wlr_surface *surface, struct wlr_box *box, float rotation, | 
			
		
	
		
			
				
					|  |  |  |  | 		void *data) { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct timespec *when = data; | 
			
		
	
		
			
				
					|  |  |  |  | 	wlr_surface_send_frame_done(surface, when); | 
			
		
	
		
			
				
					|  |  |  |  | 		void *user_data) { | 
			
		
	
		
			
				
					|  |  |  |  | 	int view_max_render_time = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 	if (view != NULL) { | 
			
		
	
		
			
				
					|  |  |  |  | 		view_max_render_time = view->max_render_time; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	struct send_frame_done_data *data = user_data; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	int delay = data->msec_until_refresh - output->max_render_time | 
			
		
	
		
			
				
					|  |  |  |  | 			- view_max_render_time; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (output->max_render_time == 0 || view_max_render_time == 0 || delay < 1) { | 
			
		
	
		
			
				
					|  |  |  |  | 		wlr_surface_send_frame_done(surface, &data->when); | 
			
		
	
		
			
				
					|  |  |  |  | 	} else { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct sway_surface *sway_surface = surface->data; | 
			
		
	
		
			
				
					|  |  |  |  | 		wl_event_source_timer_update(sway_surface->frame_done_timer, delay); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void send_frame_done(struct sway_output *output, struct timespec *when) { | 
			
		
	
		
			
				
					|  |  |  |  | 	output_for_each_surface(output, send_frame_done_iterator, when); | 
			
		
	
		
			
				
					|  |  |  |  | static void send_frame_done(struct sway_output *output, struct send_frame_done_data *data) { | 
			
		
	
		
			
				
					|  |  |  |  | 	output_for_each_surface(output, send_frame_done_iterator, data); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void count_surface_iterator(struct sway_output *output, | 
			
		
	
		
			
				
					|  |  |  |  | static void count_surface_iterator(struct sway_output *output, struct sway_view *view, | 
			
		
	
		
			
				
					|  |  |  |  | 		struct wlr_surface *surface, struct wlr_box *_box, float rotation, | 
			
		
	
		
			
				
					|  |  |  |  | 		void *data) { | 
			
		
	
		
			
				
					|  |  |  |  | 	size_t *n = data; | 
			
		
	
	
		
			
				
					|  |  |  | @ -533,7 +559,7 @@ int output_repaint_timer_handler(void *data) { | 
			
		
	
		
			
				
					|  |  |  |  | 	return 0; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void damage_handle_frame(struct wl_listener *listener, void *data) { | 
			
		
	
		
			
				
					|  |  |  |  | static void damage_handle_frame(struct wl_listener *listener, void *user_data) { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct sway_output *output = | 
			
		
	
		
			
				
					|  |  |  |  | 		wl_container_of(listener, output, damage_frame); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!output->enabled || !output->wlr_output->enabled) { | 
			
		
	
	
		
			
				
					|  |  |  | @ -592,9 +618,10 @@ static void damage_handle_frame(struct wl_listener *listener, void *data) { | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// Send frame done to all visible surfaces
 | 
			
		
	
		
			
				
					|  |  |  |  | 	struct timespec now; | 
			
		
	
		
			
				
					|  |  |  |  | 	clock_gettime(CLOCK_MONOTONIC, &now); | 
			
		
	
		
			
				
					|  |  |  |  | 	send_frame_done(output, &now); | 
			
		
	
		
			
				
					|  |  |  |  | 	struct send_frame_done_data data = {0}; | 
			
		
	
		
			
				
					|  |  |  |  | 	clock_gettime(CLOCK_MONOTONIC, &data.when); | 
			
		
	
		
			
				
					|  |  |  |  | 	data.msec_until_refresh = msec_until_refresh; | 
			
		
	
		
			
				
					|  |  |  |  | 	send_frame_done(output, &data); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void output_damage_whole(struct sway_output *output) { | 
			
		
	
	
		
			
				
					|  |  |  | @ -605,7 +632,7 @@ void output_damage_whole(struct sway_output *output) { | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void damage_surface_iterator(struct sway_output *output, | 
			
		
	
		
			
				
					|  |  |  |  | static void damage_surface_iterator(struct sway_output *output, struct sway_view *view, | 
			
		
	
		
			
				
					|  |  |  |  | 		struct wlr_surface *surface, struct wlr_box *_box, float rotation, | 
			
		
	
		
			
				
					|  |  |  |  | 		void *_data) { | 
			
		
	
		
			
				
					|  |  |  |  | 	bool *data = _data; | 
			
		
	
	
		
			
				
					|  |  |  | @ -811,7 +838,7 @@ static void handle_scale(struct wl_listener *listener, void *data) { | 
			
		
	
		
			
				
					|  |  |  |  | 	update_output_manager_config(output->server); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void send_presented_iterator(struct sway_output *output, | 
			
		
	
		
			
				
					|  |  |  |  | static void send_presented_iterator(struct sway_output *output, struct sway_view *view, | 
			
		
	
		
			
				
					|  |  |  |  | 		struct wlr_surface *surface, struct wlr_box *box, float rotation, | 
			
		
	
		
			
				
					|  |  |  |  | 		void *data) { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct wlr_presentation_event *event = data; | 
			
		
	
	
		
			
				
					|  |  |  | 
 |