mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-29 16:05:59 +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
|
#ifndef WLR_TYPES_WLR_OUTPUT_MANAGEMENT_V1_H
|
||||||
#define WLR_TYPES_WLR_OUTPUT_MANAGEMENT_V1_H
|
#define WLR_TYPES_WLR_OUTPUT_MANAGEMENT_V1_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include <wlr/types/wlr_output.h>
|
#include <wlr/types/wlr_output.h>
|
||||||
|
|
||||||
|
@ -21,6 +22,8 @@ struct wlr_output_manager_v1 {
|
||||||
uint32_t serial;
|
uint32_t serial;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
struct wl_signal apply; // wlr_output_configuration_v1
|
||||||
|
struct wl_signal test; // wlr_output_configuration_v1
|
||||||
struct wl_signal destroy;
|
struct wl_signal destroy;
|
||||||
} events;
|
} events;
|
||||||
|
|
||||||
|
@ -47,7 +50,12 @@ struct wlr_output_head_v1 {
|
||||||
|
|
||||||
struct wlr_output_configuration_v1 {
|
struct wlr_output_configuration_v1 {
|
||||||
struct wl_list heads; // wlr_output_configuration_head_v1::link
|
struct wl_list heads; // wlr_output_configuration_head_v1::link
|
||||||
|
|
||||||
|
struct wlr_output_manager_v1 *manager;
|
||||||
uint32_t serial;
|
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 {
|
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);
|
struct wlr_output_configuration_v1 *wlr_output_configuration_v1_create(void);
|
||||||
void wlr_output_configuration_v1_destroy(
|
void wlr_output_configuration_v1_destroy(
|
||||||
struct wlr_output_configuration_v1 *config);
|
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 *
|
struct wlr_output_configuration_head_v1 *
|
||||||
wlr_output_configuration_head_v1_create(
|
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;
|
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(
|
static struct wlr_output_configuration_v1 *config_from_resource(
|
||||||
struct wl_resource *resource) {
|
struct wl_resource *resource) {
|
||||||
assert(wl_resource_instance_of(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 wl_resource *head_resource) {
|
||||||
struct wlr_output_configuration_v1 *config =
|
struct wlr_output_configuration_v1 *config =
|
||||||
config_from_resource(config_resource);
|
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);
|
struct wlr_output_head_v1 *head = head_from_resource(head_resource);
|
||||||
|
|
||||||
// Create an inert resource if the head no longer exists
|
// 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 wl_resource *head_resource) {
|
||||||
struct wlr_output_configuration_v1 *config =
|
struct wlr_output_configuration_v1 *config =
|
||||||
config_from_resource(config_resource);
|
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);
|
struct wlr_output_head_v1 *head = head_from_resource(head_resource);
|
||||||
if (head == NULL) {
|
if (head == NULL) {
|
||||||
return;
|
return;
|
||||||
|
@ -194,70 +206,165 @@ static void config_handle_disable_head(struct wl_client *client,
|
||||||
config_head->state.enabled = false;
|
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,
|
static void config_handle_apply(struct wl_client *client,
|
||||||
struct wl_resource *config_resource) {
|
struct wl_resource *config_resource) {
|
||||||
//struct wlr_output_configuration_v1 *config =
|
struct wlr_output_configuration_v1 *config =
|
||||||
// config_from_resource(config_resource);
|
config_from_resource(config_resource);
|
||||||
// TODO: post already_used if needed
|
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,
|
static void config_handle_destroy(struct wl_client *client,
|
||||||
struct wl_resource *config_resource) {
|
struct wl_resource *config_resource) {
|
||||||
wl_resource_destroy(config_resource);
|
wl_resource_destroy(config_resource);
|
||||||
// TODO: destroy head configurations
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct zwlr_output_configuration_v1_interface config_impl = {
|
static const struct zwlr_output_configuration_v1_interface config_impl = {
|
||||||
.enable_head = config_handle_enable_head,
|
.enable_head = config_handle_enable_head,
|
||||||
.disable_head = config_handle_disable_head,
|
.disable_head = config_handle_disable_head,
|
||||||
.apply = config_handle_apply,
|
.apply = config_handle_apply,
|
||||||
// TODO: test
|
.test = config_handle_test,
|
||||||
.destroy = config_handle_destroy,
|
.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));
|
struct wlr_output_configuration_v1 *config = calloc(1, sizeof(*config));
|
||||||
if (config == NULL) {
|
if (config == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
wl_list_init(&config->heads);
|
wl_list_init(&config->heads);
|
||||||
|
config->finalized = finalized;
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct wlr_output_configuration_v1 *wlr_output_configuration_v1_create(void) {
|
||||||
|
return config_create(true);
|
||||||
|
}
|
||||||
|
|
||||||
void wlr_output_configuration_v1_destroy(
|
void wlr_output_configuration_v1_destroy(
|
||||||
struct wlr_output_configuration_v1 *config) {
|
struct wlr_output_configuration_v1 *config) {
|
||||||
if (config == NULL) {
|
if (config == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct wlr_output_configuration_head_v1 *head, *tmp;
|
config_finalize(config);
|
||||||
wl_list_for_each_safe(head, tmp, &config->heads, link) {
|
if (config->resource != NULL) {
|
||||||
config_head_destroy(head);
|
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);
|
free(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void config_handle_resource_destroy(struct wl_resource *resource) {
|
static void config_handle_resource_destroy(struct wl_resource *resource) {
|
||||||
struct wlr_output_configuration_v1 *config = config_from_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,
|
static void manager_handle_create_configuration(struct wl_client *client,
|
||||||
struct wl_resource *manager_resource, uint32_t id, uint32_t serial) {
|
struct wl_resource *manager_resource, uint32_t id, uint32_t serial) {
|
||||||
struct wlr_output_configuration_v1 *config =
|
struct wlr_output_configuration_v1 *config = config_create(false);
|
||||||
wlr_output_configuration_v1_create();
|
if (config == NULL) {
|
||||||
|
wl_resource_post_no_memory(manager_resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
config->serial = serial;
|
config->serial = serial;
|
||||||
|
|
||||||
uint32_t version = wl_resource_get_version(manager_resource);
|
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);
|
&zwlr_output_configuration_v1_interface, version, id);
|
||||||
if (resource == NULL) {
|
if (config->resource == NULL) {
|
||||||
wl_client_post_no_memory(client);
|
wl_client_post_no_memory(client);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wl_resource_set_implementation(resource, &config_impl,
|
wl_resource_set_implementation(config->resource, &config_impl,
|
||||||
config, config_handle_resource_destroy);
|
config, config_handle_resource_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,6 +422,8 @@ struct wlr_output_manager_v1 *wlr_output_manager_v1_create(
|
||||||
manager->display = display;
|
manager->display = display;
|
||||||
|
|
||||||
wl_signal_init(&manager->events.destroy);
|
wl_signal_init(&manager->events.destroy);
|
||||||
|
wl_signal_init(&manager->events.apply);
|
||||||
|
wl_signal_init(&manager->events.test);
|
||||||
|
|
||||||
manager->global = wl_global_create(display,
|
manager->global = wl_global_create(display,
|
||||||
&zwlr_output_manager_v1_interface, OUTPUT_MANAGER_VERSION,
|
&zwlr_output_manager_v1_interface, OUTPUT_MANAGER_VERSION,
|
||||||
|
|
Loading…
Reference in a new issue