]> git.mdlowis.com Git - proto/labwc.git/commitdiff
src/output.c: properly test new output configurations
authorConsolatis <35009135+Consolatis@users.noreply.github.com>
Mon, 22 Jan 2024 14:21:18 +0000 (15:21 +0100)
committerJohan Malm <johanmalm@users.noreply.github.com>
Tue, 23 Jan 2024 20:14:24 +0000 (20:14 +0000)
Fixes #1458

src/output.c

index ed039545a322f66ce8caf9f30d260ca22011744e..650a338edf7bcfa8f0ace35e50c81c2bd1228f26 100644 (file)
@@ -7,9 +7,11 @@
  */
 
 #define _POSIX_C_SOURCE 200809L
+#include <assert.h>
 #include <strings.h>
 #include <wlr/backend/drm.h>
 #include <wlr/backend/headless.h>
+#include <wlr/backend/wayland.h>
 #include <wlr/types/wlr_buffer.h>
 #include <wlr/types/wlr_drm_lease_v1.h>
 #include <wlr/types/wlr_output.h>
@@ -483,8 +485,68 @@ output_config_apply(struct server *server,
 static bool
 verify_output_config_v1(const struct wlr_output_configuration_v1 *config)
 {
-       /* TODO implement */
+       const char *err_msg = NULL;
+       struct wlr_output_configuration_head_v1 *head;
+       wl_list_for_each(head, &config->heads, link) {
+               if (!head->state.enabled) {
+                       continue;
+               }
+
+               /* Handle custom modes */
+               if (!head->state.mode) {
+                       int32_t refresh = head->state.custom_mode.refresh;
+
+                       if (wlr_output_is_drm(head->state.output) && refresh == 0) {
+                               /*
+                                * wlroots has a bug which causes a divide by zero
+                                * when setting the refresh rate to 0 on a DRM output.
+                                * It is already fixed but not part of an official 0.17.x
+                                * release. Even it would be we still need to carry the
+                                * fix here to prevent older 0.17.x releases from crashing.
+                                *
+                                * https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3791
+                                */
+                               err_msg = "DRM backend does not support a refresh rate of 0";
+                               goto custom_mode_failed;
+                       }
+
+                       if (wlr_output_is_wl(head->state.output) && refresh != 0) {
+                               /* Wayland backend does not support refresh rates */
+                               err_msg = "Wayland backend refresh rate unsupported";
+                               goto custom_mode_failed;
+                       }
+               }
+
+               /*
+                * Ensure the new output state can be applied on
+                * its own and inform the client when it can not.
+                *
+                * Applying the changes may still fail later when
+                * getting mixed with wlr_output->pending which
+                * may contain further unrelated changes.
+                */
+               struct wlr_output_state output_state;
+               wlr_output_state_init(&output_state);
+               wlr_output_head_v1_state_apply(&head->state, &output_state);
+
+               if (!wlr_output_test_state(head->state.output, &output_state)) {
+                       wlr_output_state_finish(&output_state);
+                       return false;
+               }
+               wlr_output_state_finish(&output_state);
+       }
+
        return true;
+
+custom_mode_failed:
+       assert(err_msg);
+       wlr_log(WLR_INFO, "%s (%s: %dx%d@%d)",
+               err_msg,
+               head->state.output->name,
+               head->state.custom_mode.width,
+               head->state.custom_mode.height,
+               head->state.custom_mode.refresh);
+       return false;
 }
 
 static void