aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVäinö Mäkelä <vaino.makela@iki.fi>2023-11-01 08:51:18 +0200
committerSimon Ser <contact@emersion.fr>2023-11-06 17:46:55 +0000
commit5de9e1a99d6642c2d09d589aa37ff0a8945dcee1 (patch)
treef81e296c41de0c75bd0880d5bd22c93223a0f11e
parent26eac25d7f7d25a5bfbeb308aa09de618a1384ef (diff)
wlr-output-management: Send custom modes to clients
Since commit 5567aefb, fixed modes haven't been automatically generated for custom modes, so the output management implementation needs to be able to handle them directly. To avoid polluting the mode list, only a single custom mode can be listed at a time and will be removed when a fixed mode is set. Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3744
-rw-r--r--types/wlr_output_management_v1.c46
1 files changed, 37 insertions, 9 deletions
diff --git a/types/wlr_output_management_v1.c b/types/wlr_output_management_v1.c
index b6dfb93d..b90d227e 100644
--- a/types/wlr_output_management_v1.c
+++ b/types/wlr_output_management_v1.c
@@ -32,7 +32,7 @@ static struct wlr_output_head_v1 *head_from_resource(
static const struct zwlr_output_mode_v1_interface output_mode_impl;
-// Can return NULL if the mode is inert
+// Can return NULL if the mode is custom or inert
static struct wlr_output_mode *mode_from_resource(
struct wl_resource *resource) {
assert(wl_resource_instance_of(resource,
@@ -86,6 +86,28 @@ static struct wlr_output_head_v1 *head_create(
return head;
}
+static void head_destroy_custom_mode_resources(struct wlr_output_head_v1 *head) {
+ struct wl_resource *resource, *tmp;
+ wl_resource_for_each_safe(resource, tmp, &head->mode_resources) {
+ if (wl_resource_get_user_data(resource) != NULL) {
+ continue;
+ }
+ zwlr_output_mode_v1_send_finished(resource);
+ wl_list_remove(wl_resource_get_link(resource));
+ wl_list_init(wl_resource_get_link(resource));
+ }
+}
+
+static bool head_has_custom_mode_resources(const struct wlr_output_head_v1 *head) {
+ struct wl_resource *resource;
+ wl_resource_for_each(resource, &head->mode_resources) {
+ if (wl_resource_get_user_data(resource) == NULL) {
+ return true;
+ }
+ }
+ return false;
+}
+
static void config_head_destroy(
struct wlr_output_configuration_head_v1 *config_head) {
@@ -161,12 +183,12 @@ static void config_head_handle_set_mode(struct wl_client *client,
return;
}
- // Mode can be NULL if the output doesn't support modes (in which case we
- // expose only one "virtual" mode, the current mode)
+ // Mode can be NULL if the output uses a custom mode (in which case we
+ // expose a virtual mode with user data set to NULL).
struct wlr_output_mode *mode = mode_from_resource(mode_resource);
struct wlr_output *output = config_head->state.output;
- bool found = (mode == NULL && wl_list_empty(&output->modes));
+ bool found = mode == NULL;
struct wlr_output_mode *m;
wl_list_for_each(m, &output->modes, link) {
if (mode == m) {
@@ -737,9 +759,6 @@ static void head_send_state(struct wlr_output_head_v1 *head,
}
if (state & HEAD_STATE_MODE) {
- assert(head->state.mode != NULL ||
- wl_list_empty(&head->state.output->modes));
-
bool found = false;
struct wl_resource *mode_resource;
wl_resource_for_each(mode_resource, &head->mode_resources) {
@@ -847,8 +866,8 @@ static void manager_send_head(struct wlr_output_manager_v1 *manager,
head_send_mode(head, head_resource, mode);
}
- if (wl_list_empty(&output->modes)) {
- // Output doesn't support modes. Send a virtual one.
+ if (output->current_mode == NULL) {
+ // Output doesn't have a fixed mode set. Send a virtual one.
head_send_mode(head, head_resource, NULL);
}
@@ -907,6 +926,15 @@ static bool manager_update_head(struct wlr_output_manager_v1 *manager,
}
}
+ if (next->mode == NULL && !head_has_custom_mode_resources(head)) {
+ struct wl_resource *resource;
+ wl_resource_for_each(resource, &head->resources) {
+ head_send_mode(head, resource, NULL);
+ }
+ } else if (next->mode != NULL) {
+ head_destroy_custom_mode_resources(head);
+ }
+
if (state != 0) {
*current = *next;