mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	output-management-v1: support applying configuration
This commit is contained in:
		
							parent
							
								
									d71ebde545
								
							
						
					
					
						commit
						8136605cfb
					
				
					 5 changed files with 152 additions and 30 deletions
				
			
		| 
						 | 
				
			
			@ -61,6 +61,8 @@ void output_for_each_surface(struct roots_output *output,
 | 
			
		|||
	roots_surface_iterator_func_t iterator, void *user_data);
 | 
			
		||||
 | 
			
		||||
void handle_new_output(struct wl_listener *listener, void *data);
 | 
			
		||||
void handle_output_manager_apply(struct wl_listener *listener, void *data);
 | 
			
		||||
void handle_output_manager_test(struct wl_listener *listener, void *data);
 | 
			
		||||
 | 
			
		||||
struct roots_view;
 | 
			
		||||
struct roots_drag_icon;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,11 +56,12 @@ struct wlr_output_head_v1 {
 | 
			
		|||
struct wlr_output_configuration_v1 {
 | 
			
		||||
	struct wl_list heads; // wlr_output_configuration_head_v1::link
 | 
			
		||||
 | 
			
		||||
	// client state
 | 
			
		||||
	struct wlr_output_manager_v1 *manager;
 | 
			
		||||
	uint32_t serial;
 | 
			
		||||
	bool finalized; // client has requested to apply the config
 | 
			
		||||
	bool finished; // feedback has been sent by the compositor
 | 
			
		||||
	struct wl_resource *resource; // can be NULL
 | 
			
		||||
	struct wl_resource *resource; // can be NULL if destroyed early
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct wlr_output_configuration_head_v1 {
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +69,8 @@ struct wlr_output_configuration_head_v1 {
 | 
			
		|||
	struct wlr_output_configuration_v1 *config;
 | 
			
		||||
	struct wl_list link; // wlr_output_configuration_v1::heads
 | 
			
		||||
 | 
			
		||||
	struct wl_resource *resource; // can be NULL
 | 
			
		||||
	// client state
 | 
			
		||||
	struct wl_resource *resource; // can be NULL if finalized or disabled
 | 
			
		||||
 | 
			
		||||
	struct wl_listener output_destroy;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -294,26 +294,6 @@ static void handle_pointer_constraint(struct wl_listener *listener,
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void handle_output_manager_apply(struct wl_listener *listener,
 | 
			
		||||
		void *data) {
 | 
			
		||||
	struct roots_desktop *desktop =
 | 
			
		||||
		wl_container_of(listener, desktop, output_manager_apply);
 | 
			
		||||
	struct wlr_output_configuration_v1 *config = data;
 | 
			
		||||
	(void)config;
 | 
			
		||||
	wlr_log(WLR_DEBUG, "APPLY"); // TODO
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void handle_output_manager_test(struct wl_listener *listener,
 | 
			
		||||
		void *data) {
 | 
			
		||||
	struct roots_desktop *desktop =
 | 
			
		||||
		wl_container_of(listener, desktop, output_manager_test);
 | 
			
		||||
	struct wlr_output_configuration_v1 *config = data;
 | 
			
		||||
 | 
			
		||||
	// TODO: implement test-only mode
 | 
			
		||||
	wlr_output_configuration_v1_send_succeeded(config);
 | 
			
		||||
	wlr_output_configuration_v1_destroy(config);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct roots_desktop *desktop_create(struct roots_server *server,
 | 
			
		||||
		struct roots_config *config) {
 | 
			
		||||
	wlr_log(WLR_DEBUG, "Initializing roots desktop");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -430,14 +430,54 @@ static void update_output_manager_config(struct roots_desktop *desktop) {
 | 
			
		|||
 | 
			
		||||
	struct roots_output *output;
 | 
			
		||||
	wl_list_for_each(output, &desktop->outputs, link) {
 | 
			
		||||
		struct wlr_output_configuration_head_v1 *head =
 | 
			
		||||
		wlr_output_configuration_head_v1_create(config, output->wlr_output);
 | 
			
		||||
		(void)head;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wlr_output_manager_v1_set_configuration(desktop->output_manager_v1, config);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void handle_output_manager_apply(struct wl_listener *listener, void *data) {
 | 
			
		||||
	struct roots_desktop *desktop =
 | 
			
		||||
		wl_container_of(listener, desktop, output_manager_apply);
 | 
			
		||||
	struct wlr_output_configuration_v1 *config = data;
 | 
			
		||||
 | 
			
		||||
	bool ok = true;
 | 
			
		||||
	struct wlr_output_configuration_head_v1 *config_head;
 | 
			
		||||
	wl_list_for_each(config_head, &config->heads, link) {
 | 
			
		||||
		struct wlr_output *wlr_output = config_head->state.output;
 | 
			
		||||
		ok &= wlr_output_enable(wlr_output, config_head->state.enabled);
 | 
			
		||||
		if (!config_head->state.enabled) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (config_head->state.mode != NULL) {
 | 
			
		||||
			ok &= wlr_output_set_mode(wlr_output, config_head->state.mode);
 | 
			
		||||
		}
 | 
			
		||||
		wlr_output_layout_add(desktop->layout, wlr_output,
 | 
			
		||||
			config_head->state.x, config_head->state.y);
 | 
			
		||||
		wlr_output_set_transform(wlr_output, config_head->state.transform);
 | 
			
		||||
		wlr_output_set_scale(wlr_output, config_head->state.scale);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ok) {
 | 
			
		||||
		wlr_output_configuration_v1_send_succeeded(config);
 | 
			
		||||
	} else {
 | 
			
		||||
		wlr_output_configuration_v1_send_failed(config);
 | 
			
		||||
	}
 | 
			
		||||
	wlr_output_configuration_v1_destroy(config);
 | 
			
		||||
 | 
			
		||||
	update_output_manager_config(desktop);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void handle_output_manager_test(struct wl_listener *listener, void *data) {
 | 
			
		||||
	struct roots_desktop *desktop =
 | 
			
		||||
		wl_container_of(listener, desktop, output_manager_test);
 | 
			
		||||
	struct wlr_output_configuration_v1 *config = data;
 | 
			
		||||
 | 
			
		||||
	// TODO: implement test-only mode
 | 
			
		||||
	wlr_output_configuration_v1_send_succeeded(config);
 | 
			
		||||
	wlr_output_configuration_v1_destroy(config);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void output_destroy(struct roots_output *output) {
 | 
			
		||||
	// TODO: cursor
 | 
			
		||||
	//example_config_configure_cursor(sample->config, sample->cursor,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -132,12 +132,94 @@ static const struct zwlr_output_configuration_head_v1_interface config_head_impl
 | 
			
		|||
static struct wlr_output_configuration_head_v1 *config_head_from_resource(
 | 
			
		||||
		struct wl_resource *resource) {
 | 
			
		||||
	assert(wl_resource_instance_of(resource,
 | 
			
		||||
		&zwlr_output_head_v1_interface, &config_head_impl));
 | 
			
		||||
		&zwlr_output_configuration_head_v1_interface, &config_head_impl));
 | 
			
		||||
	return wl_resource_get_user_data(resource);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void config_head_handle_set_mode(struct wl_client *client,
 | 
			
		||||
		struct wl_resource *config_head_resource,
 | 
			
		||||
		struct wl_resource *mode_resource) {
 | 
			
		||||
	struct wlr_output_configuration_head_v1 *config_head =
 | 
			
		||||
		config_head_from_resource(config_head_resource);
 | 
			
		||||
	if (config_head == NULL) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	struct wlr_output_mode *mode = mode_from_resource(mode_resource);
 | 
			
		||||
 | 
			
		||||
	bool found = false;
 | 
			
		||||
	struct wlr_output_mode *m;
 | 
			
		||||
	wl_list_for_each(m, &config_head->state.output->modes, link) {
 | 
			
		||||
		if (mode == m) {
 | 
			
		||||
			found = true;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!found) {
 | 
			
		||||
		wl_resource_post_error(config_head_resource,
 | 
			
		||||
			ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_INVALID_MODE,
 | 
			
		||||
			"mode doesn't belong to head");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config_head->state.mode = mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void config_head_handle_set_position(struct wl_client *client,
 | 
			
		||||
		struct wl_resource *config_head_resource, int32_t x, int32_t y) {
 | 
			
		||||
	struct wlr_output_configuration_head_v1 *config_head =
 | 
			
		||||
		config_head_from_resource(config_head_resource);
 | 
			
		||||
	if (config_head == NULL) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config_head->state.x = x;
 | 
			
		||||
	config_head->state.y = y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void config_head_handle_set_transform(struct wl_client *client,
 | 
			
		||||
		struct wl_resource *config_head_resource, int32_t transform) {
 | 
			
		||||
	struct wlr_output_configuration_head_v1 *config_head =
 | 
			
		||||
		config_head_from_resource(config_head_resource);
 | 
			
		||||
	if (config_head == NULL) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (transform < WL_OUTPUT_TRANSFORM_NORMAL ||
 | 
			
		||||
			transform > WL_OUTPUT_TRANSFORM_FLIPPED_270) {
 | 
			
		||||
		wl_resource_post_error(config_head_resource,
 | 
			
		||||
			ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_INVALID_TRANSFORM,
 | 
			
		||||
			"invalid transform");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config_head->state.transform = transform;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void config_head_handle_set_scale(struct wl_client *client,
 | 
			
		||||
		struct wl_resource *config_head_resource, int32_t scale) {
 | 
			
		||||
	struct wlr_output_configuration_head_v1 *config_head =
 | 
			
		||||
		config_head_from_resource(config_head_resource);
 | 
			
		||||
	if (config_head == NULL) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (scale <= 0) {
 | 
			
		||||
		wl_resource_post_error(config_head_resource,
 | 
			
		||||
			ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_INVALID_SCALE,
 | 
			
		||||
			"invalid scale");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config_head->state.scale = scale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct zwlr_output_configuration_head_v1_interface config_head_impl = {
 | 
			
		||||
	0 // TODO
 | 
			
		||||
	.set_mode = config_head_handle_set_mode,
 | 
			
		||||
	.set_position = config_head_handle_set_position,
 | 
			
		||||
	.set_transform = config_head_handle_set_transform,
 | 
			
		||||
	.set_scale = config_head_handle_set_scale,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void config_head_handle_resource_destroy(struct wl_resource *resource) {
 | 
			
		||||
| 
						 | 
				
			
			@ -252,10 +334,13 @@ static void config_finalize(struct wlr_output_configuration_v1 *config) {
 | 
			
		|||
	// this point anyway
 | 
			
		||||
	struct wlr_output_configuration_head_v1 *config_head, *tmp;
 | 
			
		||||
	wl_list_for_each_safe(config_head, tmp, &config->heads, link) {
 | 
			
		||||
		// Resource is NULL if head has been disabled
 | 
			
		||||
		if (config_head->resource != NULL) {
 | 
			
		||||
			wl_resource_set_user_data(config_head->resource, NULL);
 | 
			
		||||
			wl_resource_destroy(config_head->resource);
 | 
			
		||||
			config_head->resource = NULL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config->finalized = true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -385,13 +470,26 @@ void wlr_output_configuration_v1_send_failed(
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static const struct zwlr_output_manager_v1_interface manager_impl;
 | 
			
		||||
 | 
			
		||||
static struct wlr_output_manager_v1 *manager_from_resource(
 | 
			
		||||
		struct wl_resource *resource) {
 | 
			
		||||
	assert(wl_resource_instance_of(resource,
 | 
			
		||||
		&zwlr_output_manager_v1_interface, &manager_impl));
 | 
			
		||||
	return wl_resource_get_user_data(resource);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void manager_handle_create_configuration(struct wl_client *client,
 | 
			
		||||
		struct wl_resource *manager_resource, uint32_t id, uint32_t serial) {
 | 
			
		||||
	struct wlr_output_manager_v1 *manager =
 | 
			
		||||
		manager_from_resource(manager_resource);
 | 
			
		||||
 | 
			
		||||
	struct wlr_output_configuration_v1 *config = config_create(false);
 | 
			
		||||
	if (config == NULL) {
 | 
			
		||||
		wl_resource_post_no_memory(manager_resource);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	config->manager = manager;
 | 
			
		||||
	config->serial = serial;
 | 
			
		||||
 | 
			
		||||
	uint32_t version = wl_resource_get_version(manager_resource);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue