aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;