mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-25 22:25:58 +01: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…
Reference in a new issue