mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	Add apply and test events to manager
This commit is contained in:
		
							parent
							
								
									0b64ecc162
								
							
						
					
					
						commit
						d695003498
					
				
					 2 changed files with 138 additions and 17 deletions
				
			
		| 
						 | 
				
			
			@ -9,6 +9,7 @@
 | 
			
		|||
#ifndef WLR_TYPES_WLR_OUTPUT_MANAGEMENT_V1_H
 | 
			
		||||
#define WLR_TYPES_WLR_OUTPUT_MANAGEMENT_V1_H
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <wayland-server.h>
 | 
			
		||||
#include <wlr/types/wlr_output.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,6 +22,8 @@ struct wlr_output_manager_v1 {
 | 
			
		|||
	uint32_t serial;
 | 
			
		||||
 | 
			
		||||
	struct {
 | 
			
		||||
		struct wl_signal apply; // wlr_output_configuration_v1
 | 
			
		||||
		struct wl_signal test; // wlr_output_configuration_v1
 | 
			
		||||
		struct wl_signal destroy;
 | 
			
		||||
	} events;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +50,12 @@ struct wlr_output_head_v1 {
 | 
			
		|||
 | 
			
		||||
struct wlr_output_configuration_v1 {
 | 
			
		||||
	struct wl_list heads; // wlr_output_configuration_head_v1::link
 | 
			
		||||
 | 
			
		||||
	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 wlr_output_configuration_head_v1 {
 | 
			
		||||
| 
						 | 
				
			
			@ -69,6 +77,10 @@ void wlr_output_manager_v1_set_configuration(
 | 
			
		|||
struct wlr_output_configuration_v1 *wlr_output_configuration_v1_create(void);
 | 
			
		||||
void wlr_output_configuration_v1_destroy(
 | 
			
		||||
	struct wlr_output_configuration_v1 *config);
 | 
			
		||||
void wlr_output_configuration_v1_send_succeeded(
 | 
			
		||||
	struct wlr_output_configuration_v1 *config);
 | 
			
		||||
void wlr_output_configuration_v1_send_failed(
 | 
			
		||||
	struct wlr_output_configuration_v1 *config);
 | 
			
		||||
 | 
			
		||||
struct wlr_output_configuration_head_v1 *
 | 
			
		||||
	wlr_output_configuration_head_v1_create(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -122,6 +122,7 @@ static void config_head_handle_resource_destroy(struct wl_resource *resource) {
 | 
			
		|||
 | 
			
		||||
static const struct zwlr_output_configuration_v1_interface config_impl;
 | 
			
		||||
 | 
			
		||||
// Can return NULL if the config has been used
 | 
			
		||||
static struct wlr_output_configuration_v1 *config_from_resource(
 | 
			
		||||
		struct wl_resource *resource) {
 | 
			
		||||
	assert(wl_resource_instance_of(resource,
 | 
			
		||||
| 
						 | 
				
			
			@ -145,7 +146,12 @@ static void config_handle_enable_head(struct wl_client *client,
 | 
			
		|||
		struct wl_resource *head_resource) {
 | 
			
		||||
	struct wlr_output_configuration_v1 *config =
 | 
			
		||||
		config_from_resource(config_resource);
 | 
			
		||||
	// Can be NULL if the head no longer exists
 | 
			
		||||
	if (config == NULL || config->finalized) {
 | 
			
		||||
		wl_resource_post_error(config_resource,
 | 
			
		||||
			ZWLR_OUTPUT_CONFIGURATION_V1_ERROR_ALREADY_USED,
 | 
			
		||||
			"configuration object has already been used");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	struct wlr_output_head_v1 *head = head_from_resource(head_resource);
 | 
			
		||||
 | 
			
		||||
	// Create an inert resource if the head no longer exists
 | 
			
		||||
| 
						 | 
				
			
			@ -179,6 +185,12 @@ static void config_handle_disable_head(struct wl_client *client,
 | 
			
		|||
		struct wl_resource *head_resource) {
 | 
			
		||||
	struct wlr_output_configuration_v1 *config =
 | 
			
		||||
		config_from_resource(config_resource);
 | 
			
		||||
	if (config == NULL || config->finalized) {
 | 
			
		||||
		wl_resource_post_error(config_resource,
 | 
			
		||||
			ZWLR_OUTPUT_CONFIGURATION_V1_ERROR_ALREADY_USED,
 | 
			
		||||
			"configuration object has already been used");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	struct wlr_output_head_v1 *head = head_from_resource(head_resource);
 | 
			
		||||
	if (head == NULL) {
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -194,70 +206,165 @@ static void config_handle_disable_head(struct wl_client *client,
 | 
			
		|||
	config_head->state.enabled = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void config_finalize(struct wlr_output_configuration_v1 *config) {
 | 
			
		||||
	if (config->finalized) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Destroy config head resources now, the client is forbidden to use them at
 | 
			
		||||
	// this point anyway
 | 
			
		||||
	struct wlr_output_configuration_head_v1 *config_head, *tmp;
 | 
			
		||||
	wl_list_for_each_safe(config_head, tmp, &config->heads, link) {
 | 
			
		||||
		wl_resource_set_user_data(config_head->resource, NULL);
 | 
			
		||||
		wl_resource_destroy(config_head->resource);
 | 
			
		||||
		config_head->resource = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config->finalized = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Destroys the config if serial is invalid
 | 
			
		||||
static bool config_validate_serial(struct wlr_output_configuration_v1 *config) {
 | 
			
		||||
	if (config->serial != config->manager->serial) {
 | 
			
		||||
		wlr_log(WLR_DEBUG, "Ignored configuration request: invalid serial");
 | 
			
		||||
		zwlr_output_configuration_v1_send_cancelled(config->resource);
 | 
			
		||||
		wlr_output_configuration_v1_destroy(config);
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void config_handle_apply(struct wl_client *client,
 | 
			
		||||
		struct wl_resource *config_resource) {
 | 
			
		||||
	//struct wlr_output_configuration_v1 *config =
 | 
			
		||||
	//	config_from_resource(config_resource);
 | 
			
		||||
	// TODO: post already_used if needed
 | 
			
		||||
	struct wlr_output_configuration_v1 *config =
 | 
			
		||||
		config_from_resource(config_resource);
 | 
			
		||||
	if (config == NULL || config->finalized) {
 | 
			
		||||
		wl_resource_post_error(config_resource,
 | 
			
		||||
			ZWLR_OUTPUT_CONFIGURATION_V1_ERROR_ALREADY_USED,
 | 
			
		||||
			"configuration object has already been used");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO
 | 
			
		||||
	config_finalize(config);
 | 
			
		||||
	if (!config_validate_serial(config)) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wlr_signal_emit_safe(&config->manager->events.apply, config);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void config_handle_test(struct wl_client *client,
 | 
			
		||||
		struct wl_resource *config_resource) {
 | 
			
		||||
	struct wlr_output_configuration_v1 *config =
 | 
			
		||||
		config_from_resource(config_resource);
 | 
			
		||||
	if (config == NULL || config->finalized) {
 | 
			
		||||
		wl_resource_post_error(config_resource,
 | 
			
		||||
			ZWLR_OUTPUT_CONFIGURATION_V1_ERROR_ALREADY_USED,
 | 
			
		||||
			"configuration object has already been used");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config_finalize(config);
 | 
			
		||||
	if (!config_validate_serial(config)) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wlr_signal_emit_safe(&config->manager->events.test, config);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void config_handle_destroy(struct wl_client *client,
 | 
			
		||||
		struct wl_resource *config_resource) {
 | 
			
		||||
	wl_resource_destroy(config_resource);
 | 
			
		||||
	// TODO: destroy head configurations
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct zwlr_output_configuration_v1_interface config_impl = {
 | 
			
		||||
	.enable_head = config_handle_enable_head,
 | 
			
		||||
	.disable_head = config_handle_disable_head,
 | 
			
		||||
	.apply = config_handle_apply,
 | 
			
		||||
	// TODO: test
 | 
			
		||||
	.test = config_handle_test,
 | 
			
		||||
	.destroy = config_handle_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct wlr_output_configuration_v1 *wlr_output_configuration_v1_create(void) {
 | 
			
		||||
static struct wlr_output_configuration_v1 *config_create(bool finalized) {
 | 
			
		||||
	struct wlr_output_configuration_v1 *config = calloc(1, sizeof(*config));
 | 
			
		||||
	if (config == NULL) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	wl_list_init(&config->heads);
 | 
			
		||||
	config->finalized = finalized;
 | 
			
		||||
	return config;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct wlr_output_configuration_v1 *wlr_output_configuration_v1_create(void) {
 | 
			
		||||
	return config_create(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void wlr_output_configuration_v1_destroy(
 | 
			
		||||
		struct wlr_output_configuration_v1 *config) {
 | 
			
		||||
	if (config == NULL) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	struct wlr_output_configuration_head_v1 *head, *tmp;
 | 
			
		||||
	wl_list_for_each_safe(head, tmp, &config->heads, link) {
 | 
			
		||||
		config_head_destroy(head);
 | 
			
		||||
	config_finalize(config);
 | 
			
		||||
	if (config->resource != NULL) {
 | 
			
		||||
		wl_resource_set_user_data(config->resource, NULL); // make inert
 | 
			
		||||
	}
 | 
			
		||||
	struct wlr_output_configuration_head_v1 *config_head, *tmp;
 | 
			
		||||
	wl_list_for_each_safe(config_head, tmp, &config->heads, link) {
 | 
			
		||||
		config_head_destroy(config_head);
 | 
			
		||||
	}
 | 
			
		||||
	free(config);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void config_handle_resource_destroy(struct wl_resource *resource) {
 | 
			
		||||
	struct wlr_output_configuration_v1 *config = config_from_resource(resource);
 | 
			
		||||
	wlr_output_configuration_v1_destroy(config);
 | 
			
		||||
	if (config == NULL) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (config->finalized) {
 | 
			
		||||
		config->resource = NULL; // we no longer own the config
 | 
			
		||||
	} else {
 | 
			
		||||
		wlr_output_configuration_v1_destroy(config);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void wlr_output_configuration_v1_send_succeeded(
 | 
			
		||||
		struct wlr_output_configuration_v1 *config) {
 | 
			
		||||
	assert(!config->finished);
 | 
			
		||||
	if (config->resource == NULL) {
 | 
			
		||||
		return; // client destroyed the resource early
 | 
			
		||||
	}
 | 
			
		||||
	zwlr_output_configuration_v1_send_succeeded(config->resource);
 | 
			
		||||
	config->finished = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void wlr_output_configuration_v1_send_failed(
 | 
			
		||||
		struct wlr_output_configuration_v1 *config) {
 | 
			
		||||
	assert(!config->finished);
 | 
			
		||||
	if (config->resource == NULL) {
 | 
			
		||||
		return; // client destroyed the resource early
 | 
			
		||||
	}
 | 
			
		||||
	zwlr_output_configuration_v1_send_failed(config->resource);
 | 
			
		||||
	config->finished = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void manager_handle_create_configuration(struct wl_client *client,
 | 
			
		||||
		struct wl_resource *manager_resource, uint32_t id, uint32_t serial) {
 | 
			
		||||
	struct wlr_output_configuration_v1 *config =
 | 
			
		||||
		wlr_output_configuration_v1_create();
 | 
			
		||||
	struct wlr_output_configuration_v1 *config = config_create(false);
 | 
			
		||||
	if (config == NULL) {
 | 
			
		||||
		wl_resource_post_no_memory(manager_resource);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	config->serial = serial;
 | 
			
		||||
 | 
			
		||||
	uint32_t version = wl_resource_get_version(manager_resource);
 | 
			
		||||
	struct wl_resource *resource = wl_resource_create(client,
 | 
			
		||||
	config->resource = wl_resource_create(client,
 | 
			
		||||
		&zwlr_output_configuration_v1_interface, version, id);
 | 
			
		||||
	if (resource == NULL) {
 | 
			
		||||
	if (config->resource == NULL) {
 | 
			
		||||
		wl_client_post_no_memory(client);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	wl_resource_set_implementation(resource, &config_impl,
 | 
			
		||||
	wl_resource_set_implementation(config->resource, &config_impl,
 | 
			
		||||
		config, config_handle_resource_destroy);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -315,6 +422,8 @@ struct wlr_output_manager_v1 *wlr_output_manager_v1_create(
 | 
			
		|||
	manager->display = display;
 | 
			
		||||
 | 
			
		||||
	wl_signal_init(&manager->events.destroy);
 | 
			
		||||
	wl_signal_init(&manager->events.apply);
 | 
			
		||||
	wl_signal_init(&manager->events.test);
 | 
			
		||||
 | 
			
		||||
	manager->global = wl_global_create(display,
 | 
			
		||||
		&zwlr_output_manager_v1_interface, OUTPUT_MANAGER_VERSION,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue