SDL: wayland: Remove kde_output_order_v1 support

From 4c2d0c422b11ac5515ad123cfe3d659d0e45722c Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Sat, 19 Oct 2024 11:13:24 -0400
Subject: [PATCH] wayland: Remove kde_output_order_v1 support

This protocol is unstable and not intended for clients, and SDL now sorts the display list into a stable order and selects a primary display suitable for games on its own, so it isn't necessary.

Reverts e71e16950a5591913bd15bc8f4d04c01bf654b72
---
 src/video/wayland/SDL_waylandvideo.c      | 120 +++-------------------
 src/video/wayland/SDL_waylandvideo.h      |   3 -
 wayland-protocols/kde-output-order-v1.xml |  33 ------
 3 files changed, 13 insertions(+), 143 deletions(-)
 delete mode 100644 wayland-protocols/kde-output-order-v1.xml

diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index 13744a2cb2134..d93eb60b4794e 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -49,7 +49,6 @@
 #include "frog-color-management-v1-client-protocol.h"
 #include "idle-inhibit-unstable-v1-client-protocol.h"
 #include "input-timestamps-unstable-v1-client-protocol.h"
-#include "kde-output-order-v1-client-protocol.h"
 #include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h"
 #include "pointer-constraints-unstable-v1-client-protocol.h"
 #include "primary-selection-unstable-v1-client-protocol.h"
@@ -203,47 +202,6 @@ static bool Wayland_GetGNOMEPrimaryDisplayCoordinates(int *x, int *y)
     return false;
 }
 
-static void Wayland_FlushOutputOrder(SDL_VideoData *vid)
-{
-    SDL_WaylandConnectorName *c, *tmp;
-    wl_list_for_each_safe (c, tmp, &vid->output_order, link) {
-        WAYLAND_wl_list_remove(&c->link);
-        SDL_free(c);
-    }
-
-    vid->output_order_finalized = false;
-}
-
-/* The order of wl_output displays exposed by KDE doesn't correspond to any priority, but KDE does provide a protocol
- * that tells clients the preferred order or all connected displays via an ordered list of connector name strings.
- */
-static void handle_kde_output_order_output(void *data, struct kde_output_order_v1 *kde_output_order_v1, const char *output_name)
-{
-    SDL_VideoData *vid = (SDL_VideoData *)data;
-
-    // Starting a new list, flush the old.
-    if (vid->output_order_finalized) {
-        Wayland_FlushOutputOrder(vid);
-    }
-
-    const int len = SDL_strlen(output_name) + 1;
-    SDL_WaylandConnectorName *node = SDL_malloc(sizeof(SDL_WaylandConnectorName) + len);
-    SDL_strlcpy(node->wl_output_name, output_name, len);
-
-    WAYLAND_wl_list_insert(vid->output_order.prev, &node->link);
-}
-
-static void handle_kde_output_order_done(void *data, struct kde_output_order_v1 *kde_output_order_v1)
-{
-    SDL_VideoData *vid = (SDL_VideoData *)data;
-    vid->output_order_finalized = true;
-}
-
-static const struct kde_output_order_v1_listener kde_output_order_listener = {
-    handle_kde_output_order_output,
-    handle_kde_output_order_done
-};
-
 // Sort the list of displays into a deterministic order
 static int SDLCALL Wayland_DisplayPositionCompare(const void *a, const void *b)
 {
@@ -350,7 +308,7 @@ static int Wayland_GetPrimaryDisplay(SDL_VideoData *vid)
     return best_index;
 }
 
-static bool Wayland_SortOutputsByPriorityHint(SDL_VideoData *vid)
+static void Wayland_SortOutputsByPriorityHint(SDL_VideoData *vid)
 {
     const char *name_hint = SDL_GetHint(SDL_HINT_VIDEO_DISPLAY_PRIORITY);
 
@@ -358,9 +316,10 @@ static bool Wayland_SortOutputsByPriorityHint(SDL_VideoData *vid)
         char *saveptr;
         char *str = SDL_strdup(name_hint);
         SDL_DisplayData **sorted_list = SDL_malloc(sizeof(SDL_DisplayData *) * vid->output_count);
-        int sorted_index = 0;
 
         if (str && sorted_list) {
+            int sorted_index = 0;
+
             // Sort the requested displays to the front of the list.
             const char *token = SDL_strtok_r(str, ",", &saveptr);
             while (token) {
@@ -389,67 +348,24 @@ static bool Wayland_SortOutputsByPriorityHint(SDL_VideoData *vid)
 
         SDL_free(str);
         SDL_free(sorted_list);
-
-        return true;
     }
-
-    return false;
 }
 
 static void Wayland_SortOutputs(SDL_VideoData *vid)
 {
-    bool have_primary = false;
-
-    /* KDE provides the kde-output-order-v1 protocol, which gives us the full preferred display
-     * ordering in the form of a list of wl_output.name strings.
-     */
-    if (!WAYLAND_wl_list_empty(&vid->output_order)) {
-        SDL_WaylandConnectorName *c;
-        SDL_DisplayData **sorted_list = SDL_malloc(sizeof(SDL_DisplayData *) * vid->output_count);
-        int sorted_index = 0;
+    // Sort by position or connector name, so the order of outputs is deterministic.
+    SDL_qsort(vid->output_list, vid->output_count, sizeof(SDL_DisplayData *), Wayland_DisplayPositionCompare);
 
-        if (sorted_list) {
-            // Sort the outputs by connector name.
-            wl_list_for_each (c, &vid->output_order, link) {
-                for (int i = 0; i < vid->output_count; ++i) {
-                    SDL_DisplayData *d = vid->output_list[i];
-                    if (d && d->wl_output_name && SDL_strcmp(c->wl_output_name, d->wl_output_name) == 0) {
-                        sorted_list[sorted_index++] = d;
-                        vid->output_list[i] = NULL;
-                        break;
-                    }
-                }
-            }
-
-            /* If any displays were omitted during the sort, append them to the new list.
-             * This shouldn't happen, but better safe than sorry.
-             */
-            for (int i = 0; i < vid->output_count; ++i) {
-                if (vid->output_list[i]) {
-                    sorted_list[sorted_index++] = vid->output_list[i];
-                }
-            }
-
-            // Copy the sorted list to the output list.
-            SDL_memcpy(vid->output_list, sorted_list, sizeof(SDL_DisplayData *) * vid->output_count);
-            SDL_free(sorted_list);
-
-            have_primary = true;
-        }
-    } else {
-        // Sort by position or connector name, so the order of outputs is deterministic.
-        SDL_qsort(vid->output_list, vid->output_count, sizeof(SDL_DisplayData *), Wayland_DisplayPositionCompare);
+    // Find a suitable primary display and move it to the front of the list.
+    const int primary_index = Wayland_GetPrimaryDisplay(vid);
+    if (primary_index) {
+        SDL_DisplayData *primary = vid->output_list[primary_index];
+        SDL_memmove(&vid->output_list[1], &vid->output_list[0], sizeof(SDL_DisplayData *) * primary_index);
+        vid->output_list[0] = primary;
     }
 
-    // Apply the ordering hint if specified, otherwise, try to find the primary display, if no preferred order is known.
-    if (!Wayland_SortOutputsByPriorityHint(vid) && !have_primary) {
-        const int primary_index = Wayland_GetPrimaryDisplay(vid);
-        if (primary_index) {
-            SDL_DisplayData *primary = vid->output_list[primary_index];
-            SDL_memmove(&vid->output_list[1], &vid->output_list[0], sizeof(SDL_DisplayData *) * primary_index);
-            vid->output_list[0] = primary;
-        }
-    }
+    // Apply the ordering hint, if specified.
+    Wayland_SortOutputsByPriorityHint(vid);
 }
 
 static void display_handle_done(void *data, struct wl_output *output);
@@ -643,7 +559,6 @@ static SDL_VideoDevice *Wayland_CreateDevice(bool require_preferred_protocols)
     data->input = input;
     data->display_externally_owned = display_is_external;
     data->scale_to_display_enabled = SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_SCALE_TO_DISPLAY, false);
-    WAYLAND_wl_list_init(&data->output_order);
     WAYLAND_wl_list_init(&external_window_list);
 
     // Initialize all variables that we clean on shutdown
@@ -1353,9 +1268,6 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
         d->wp_alpha_modifier_v1 = wl_registry_bind(d->registry, id, &wp_alpha_modifier_v1_interface, 1);
     } else if (SDL_strcmp(interface, "xdg_toplevel_icon_manager_v1") == 0) {
         d->xdg_toplevel_icon_manager_v1 = wl_registry_bind(d->registry, id, &xdg_toplevel_icon_manager_v1_interface, 1);
-    } else if (SDL_strcmp(interface, "kde_output_order_v1") == 0) {
-        d->kde_output_order = wl_registry_bind(d->registry, id, &kde_output_order_v1_interface, 1);
-        kde_output_order_v1_add_listener(d->kde_output_order, &kde_output_order_listener, d);
     } else if (SDL_strcmp(interface, "frog_color_management_factory_v1") == 0) {
         d->frog_color_management_factory_v1 = wl_registry_bind(d->registry, id, &frog_color_management_factory_v1_interface, 1);
     }
@@ -1634,12 +1546,6 @@ static void Wayland_VideoCleanup(SDL_VideoDevice *_this)
         data->xdg_toplevel_icon_manager_v1 = NULL;
     }
 
-    if (data->kde_output_order) {
-        Wayland_FlushOutputOrder(data);
-        kde_output_order_v1_destroy(data->kde_output_order);
-        data->kde_output_order = NULL;
-    }
-
     if (data->frog_color_management_factory_v1) {
         frog_color_management_factory_v1_destroy(data->frog_color_management_factory_v1);
         data->frog_color_management_factory_v1 = NULL;
diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h
index 8d6c8a8627352..11ad075478206 100644
--- a/src/video/wayland/SDL_waylandvideo.h
+++ b/src/video/wayland/SDL_waylandvideo.h
@@ -91,9 +91,6 @@ struct SDL_VideoData
     SDL_DisplayData **output_list;
     int output_count;
     int output_max;
-    struct wl_list output_order;
-
-    bool output_order_finalized;
 
     int relative_mouse_mode;
     bool display_externally_owned;
diff --git a/wayland-protocols/kde-output-order-v1.xml b/wayland-protocols/kde-output-order-v1.xml
deleted file mode 100644
index cc50f09efabdf..0000000000000
--- a/wayland-protocols/kde-output-order-v1.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<protocol name="kde_output_order_v1">
-  <copyright><![CDATA[
-    SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
-
-    SPDX-License-Identifier: MIT-CMU
-    ]]></copyright>
-
-  <interface name="kde_output_order_v1" version="1">
-    <description summary="announce order of outputs">
-        Announce the order in which desktop environment components should be placed on outputs.
-        The compositor will send the list of outputs when the global is bound and whenever there is a change.
-    </description>
-
-    <event name="output">
-      <description summary="output name">
-        Specifies the output identified by their wl_output.name.
-      </description>
-      <arg name="output_name" type="string" summary="the name of the output"/>
-    </event>
-
-    <event name="done">
-      <description summary="done">
-        Specifies that the output list is complete. On the next output event, a new list begins.
-      </description>
-    </event>
-
-    <request name="destroy" type="destructor">
-      <description summary="Destroy the output order notifier."/>
-    </request>
-  </interface>
-
-</protocol>