From e9c0d886d1dc4a20181e275345fc87be3e4c7d29 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 18 Jun 2026 10:31:37 +0800 Subject: [PATCH] DisplayServer (Linux): be compatible with KDE 6.7 This PR also removes usage of `kde-output-order-v1-protocol`, which disables detection of primary monitor for old KDE versions --- CMakeLists.txt | 5 - .../kde-output-order-v1-client-protocol.h | 134 ------------------ .../wayland/kde-output-order-v1-protocol.c | 37 ----- .../displayserver/linux/wayland/kde-output.c | 68 +++++---- .../displayserver/linux/wayland/wayland.c | 32 ++--- .../displayserver/linux/wayland/wayland.h | 6 +- 6 files changed, 60 insertions(+), 222 deletions(-) delete mode 100644 src/detection/displayserver/linux/wayland/kde-output-order-v1-client-protocol.h delete mode 100644 src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 24ba32666..ab13c6d0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -602,7 +602,6 @@ if(LINUX) src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c src/detection/displayserver/linux/wayland/kde-output.c src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c - src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c src/detection/displayserver/linux/wmde.c src/detection/displayserver/linux/xcb.c @@ -763,7 +762,6 @@ elseif(FreeBSD) src/detection/displayserver/linux/wayland/wl-output-protocol.c src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c - src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c src/detection/displayserver/linux/wmde.c src/detection/displayserver/linux/xcb.c @@ -859,7 +857,6 @@ elseif(NetBSD) src/detection/displayserver/linux/wayland/wl-output-protocol.c src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c - src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c src/detection/displayserver/linux/wmde.c src/detection/displayserver/linux/xcb.c @@ -944,7 +941,6 @@ elseif(OpenBSD) src/detection/displayserver/linux/wayland/wl-output-protocol.c src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c - src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c src/detection/displayserver/linux/wmde.c src/detection/displayserver/linux/xcb.c @@ -1189,7 +1185,6 @@ elseif(SunOS) src/detection/displayserver/linux/wayland/wl-output-protocol.c src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c - src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c src/detection/displayserver/linux/wmde.c src/detection/displayserver/linux/xcb.c diff --git a/src/detection/displayserver/linux/wayland/kde-output-order-v1-client-protocol.h b/src/detection/displayserver/linux/wayland/kde-output-order-v1-client-protocol.h deleted file mode 100644 index b9928c3fe..000000000 --- a/src/detection/displayserver/linux/wayland/kde-output-order-v1-client-protocol.h +++ /dev/null @@ -1,134 +0,0 @@ -/* Generated by wayland-scanner 1.22.0 */ - -#ifndef KDE_OUTPUT_ORDER_V1_CLIENT_PROTOCOL_H -#define KDE_OUTPUT_ORDER_V1_CLIENT_PROTOCOL_H - -#include -#include -#include "wayland-client.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @page page_kde_output_order_v1 The kde_output_order_v1 protocol - * @section page_ifaces_kde_output_order_v1 Interfaces - * - @subpage page_iface_kde_output_order_v1 - announce order of outputs - * @section page_copyright_kde_output_order_v1 Copyright - *
- *
- * SPDX-FileCopyrightText: 2022 Xaver Hugl 
- *
- * SPDX-License-Identifier: MIT-CMU
- * 
- */ -struct kde_output_order_v1; - -#ifndef KDE_OUTPUT_ORDER_V1_INTERFACE - #define KDE_OUTPUT_ORDER_V1_INTERFACE -/** - * @page page_iface_kde_output_order_v1 kde_output_order_v1 - * @section page_iface_kde_output_order_v1_desc Description - * - * 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. - * @section page_iface_kde_output_order_v1_api API - * See @ref iface_kde_output_order_v1. - */ -/** - * @defgroup iface_kde_output_order_v1 The kde_output_order_v1 interface - * - * 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. - */ -extern const struct wl_interface kde_output_order_v1_interface; -#endif - -/** - * @ingroup iface_kde_output_order_v1 - * @struct kde_output_order_v1_listener - */ -struct kde_output_order_v1_listener { - /** - * output name - * - * Specifies the output identified by their wl_output.name. - * @param output_name the name of the output - */ - void (*output)(void* data, - struct kde_output_order_v1* kde_output_order_v1, - const char* output_name); - /** - * done - * - * Specifies that the output list is complete. On the next output - * event, a new list begins. - */ - void (*done)(void* data, - struct kde_output_order_v1* kde_output_order_v1); -}; - -/** - * @ingroup iface_kde_output_order_v1 - */ -static inline int -kde_output_order_v1_add_listener(struct kde_output_order_v1* kde_output_order_v1, - const struct kde_output_order_v1_listener* listener, - void* data) { - return wl_proxy_add_listener((struct wl_proxy*) kde_output_order_v1, - (void (**)(void)) listener, - data); -} - -#define KDE_OUTPUT_ORDER_V1_DESTROY 0 - -/** - * @ingroup iface_kde_output_order_v1 - */ -#define KDE_OUTPUT_ORDER_V1_OUTPUT_SINCE_VERSION 1 -/** - * @ingroup iface_kde_output_order_v1 - */ -#define KDE_OUTPUT_ORDER_V1_DONE_SINCE_VERSION 1 - -/** - * @ingroup iface_kde_output_order_v1 - */ -#define KDE_OUTPUT_ORDER_V1_DESTROY_SINCE_VERSION 1 - -// /** @ingroup iface_kde_output_order_v1 */ -// static inline void -// kde_output_order_v1_set_user_data(struct kde_output_order_v1 *kde_output_order_v1, void *user_data) -// { -// wl_proxy_set_user_data((struct wl_proxy *) kde_output_order_v1, user_data); -// } - -// /** @ingroup iface_kde_output_order_v1 */ -// static inline void * -// kde_output_order_v1_get_user_data(struct kde_output_order_v1 *kde_output_order_v1) -// { -// return wl_proxy_get_user_data((struct wl_proxy *) kde_output_order_v1); -// } - -// static inline uint32_t -// kde_output_order_v1_get_version(struct kde_output_order_v1 *kde_output_order_v1) -// { -// return wl_proxy_get_version((struct wl_proxy *) kde_output_order_v1); -// } - -// /** -// * @ingroup iface_kde_output_order_v1 -// */ -// static inline void -// kde_output_order_v1_destroy(struct kde_output_order_v1 *kde_output_order_v1) -// { -// wl_proxy_marshal_flags((struct wl_proxy *) kde_output_order_v1, -// KDE_OUTPUT_ORDER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) kde_output_order_v1), WL_MARSHAL_FLAG_DESTROY); -// } - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c b/src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c deleted file mode 100644 index 00db32af5..000000000 --- a/src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c +++ /dev/null @@ -1,37 +0,0 @@ -#ifdef FF_HAVE_WAYLAND - -/* Generated by wayland-scanner 1.22.0 */ - -/* - * SPDX-FileCopyrightText: 2022 Xaver Hugl - * - * SPDX-License-Identifier: MIT-CMU - */ - - #include - #include - #include "wayland-util.h" - -static const struct wl_interface* kde_output_order_v1_types[] = { - NULL, -}; - -static const struct wl_message kde_output_order_v1_requests[] = { - { "destroy", "", kde_output_order_v1_types + 0 }, -}; - -static const struct wl_message kde_output_order_v1_events[] = { - { "output", "s", kde_output_order_v1_types + 0 }, - { "done", "", kde_output_order_v1_types + 0 }, -}; - -WL_EXPORT const struct wl_interface kde_output_order_v1_interface = { - "kde_output_order_v1", - 1, - 1, - kde_output_order_v1_requests, - 2, - kde_output_order_v1_events, -}; - -#endif diff --git a/src/detection/displayserver/linux/wayland/kde-output.c b/src/detection/displayserver/linux/wayland/kde-output.c index 90d5770cd..94be50cab 100644 --- a/src/detection/displayserver/linux/wayland/kde-output.c +++ b/src/detection/displayserver/linux/wayland/kde-output.c @@ -2,7 +2,6 @@ #include "wayland.h" #include "kde-output-device-v2-client-protocol.h" - #include "kde-output-order-v1-client-protocol.h" #include "common/edidHelper.h" #include "common/base64.h" @@ -142,6 +141,11 @@ static void waylandKdeMaxBitsPerColorListener(void* data, FF_A_UNUSED struct kde display->bitDepth = (uint8_t) max_bpc; } +static void waylandKdePriorityListener(void* data, FF_A_UNUSED struct kde_output_device_v2* kde_output_device_v2, uint32_t priority) { + WaylandDisplay* display = data; + display->primary = priority == 1; +} + static struct kde_output_device_v2_listener outputListener = { .geometry = waylandKdeGeometryListener, .current_mode = waylandKdeCurrentModeListener, @@ -176,15 +180,16 @@ static struct kde_output_device_v2_listener outputListener = { .max_bits_per_color_range = (void*) stubListener, .automatic_max_bits_per_color_limit = (void*) stubListener, .edr_policy = (void*) stubListener, + .sharpness = (void*) stubListener, + .priority = waylandKdePriorityListener, + .auto_brightness = (void*) stubListener, + .removed = (void*) stubListener, + .hdr_icc_profile_path = (void*) stubListener, + .hdr_color_profile_source = (void*) stubListener, + .abm_level = (void*) stubListener, }; -const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) { - uint32_t bindVersion = min(version, KDE_OUTPUT_DEVICE_V2_MAX_BITS_PER_COLOR_SINCE_VERSION); - struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &kde_output_device_v2_interface, bindVersion, name, kde_output_device_v2_interface.name, bindVersion, NULL); - if (output == NULL) { - return "Failed to create kde_output_device_v2"; - } - +static const char* waylandKdeHandleOutput(WaylandData* wldata, struct wl_proxy* output) { FF_LIST_AUTO_DESTROY modes = ffListCreate(); WaylandDisplay display = { .parent = wldata, @@ -236,7 +241,7 @@ const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* re ? &display.edidName : &display.name, display.type, - false, + display.primary, display.id, (uint32_t) display.physicalWidth, (uint32_t) display.physicalHeight, @@ -265,35 +270,42 @@ const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* re return NULL; } -static void waylandKdeOutputOrderListener(void* data, FF_A_UNUSED struct kde_output_order_v1* _, const char* output_name) { - uint64_t* id = (uint64_t*) data; - if (*id == 0) { - *id = ffWaylandGenerateIdFromName(output_name); +const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) { + // TODO: remove this in future versions + uint32_t bindVersion = min(version, KDE_OUTPUT_DEVICE_V2_PRIORITY_SINCE_VERSION); + struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &kde_output_device_v2_interface, bindVersion, name, kde_output_device_v2_interface.name, bindVersion, NULL); + if (output == NULL) { + return "Failed to create kde_output_device_v2"; } + + return waylandKdeHandleOutput(wldata, output); } -static const struct kde_output_order_v1_listener orderListener = { - .output = waylandKdeOutputOrderListener, - .done = (void*) stubListener, +static void waylandKdeOutputListener(void* data, FF_A_UNUSED struct kde_output_device_registry_v2* kde_output_device_registry_v2, struct kde_output_device_v2* output) { + waylandKdeHandleOutput((WaylandData*) data, (struct wl_proxy*) output); +} + +static struct kde_output_device_registry_v2_listener registryListener = { + .output = waylandKdeOutputListener, + .finished = (void*) stubListener, }; -const char* ffWaylandHandleKdeOutputOrder(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) { - uint32_t bindVersion = min(version, KDE_OUTPUT_ORDER_V1_OUTPUT_SINCE_VERSION); - struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &kde_output_order_v1_interface, bindVersion, name, kde_output_order_v1_interface.name, bindVersion, NULL); - if (output == NULL) { - return "Failed to create kde_output_order_v1"; +const char* ffWaylandHandleKdeOutputRegistry(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) { + uint32_t bindVersion = min(version, KDE_OUTPUT_DEVICE_REGISTRY_V2_OUTPUT_SINCE_VERSION); + struct wl_proxy* outputRegistry = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &kde_output_device_registry_v2_interface, bindVersion, name, kde_output_device_registry_v2_interface.name, bindVersion, NULL); + if (outputRegistry == NULL) { + return "Failed to create kde_output_device_registry_v2"; } - - if (wldata->ffwl_proxy_add_listener(output, (void (**)(void)) &orderListener, &wldata->primaryDisplayId) < 0) { - wldata->ffwl_proxy_destroy(output); - return "Failed to add listener to kde_output_order_v1"; + if (wldata->ffwl_proxy_add_listener(outputRegistry, (void (**)(void)) ®istryListener, wldata) < 0) { + wldata->ffwl_proxy_destroy(outputRegistry); + return "Failed to add listener to kde_output_device_registry_v2"; } if (wldata->ffwl_display_roundtrip(wldata->display) < 0) { - wldata->ffwl_proxy_destroy(output); - return "Failed to roundtrip kde_output_order_v1"; + wldata->ffwl_proxy_destroy(outputRegistry); + return "Failed to roundtrip kde_output_device_registry_v2"; } - wldata->ffwl_proxy_destroy(output); + wldata->ffwl_proxy_destroy(outputRegistry); return NULL; } diff --git a/src/detection/displayserver/linux/wayland/wayland.c b/src/detection/displayserver/linux/wayland/wayland.c index 69a42611b..096eef0ab 100644 --- a/src/detection/displayserver/linux/wayland/wayland.c +++ b/src/detection/displayserver/linux/wayland/wayland.c @@ -14,7 +14,6 @@ #include "wayland.h" #include "kde-output-device-v2-client-protocol.h" - #include "kde-output-order-v1-client-protocol.h" #include "xdg-output-unstable-v1-client-protocol.h" #include "wp-color-management-v1-client-protocol.h" @@ -86,13 +85,16 @@ static void waylandGlobalAddListener(void* data, struct wl_registry* registry, u if (ffWaylandHandleGlobalOutput(wldata, registry, name, version) != NULL) { wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_NONE; } - } else if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_KDE) && ffStrEquals(interface, kde_output_device_v2_interface.name)) { - wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_KDE; + } else if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE) && ffStrEquals(interface, kde_output_device_registry_v2_interface.name)) { + wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_KDE_REGISTRY; + if (ffWaylandHandleKdeOutputRegistry(wldata, registry, name, version) != NULL) { + wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_NONE; + } + } else if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_KDE_DEPRECATED) && ffStrEquals(interface, kde_output_device_v2_interface.name)) { + wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_KDE_DEPRECATED; if (ffWaylandHandleKdeOutput(wldata, registry, name, version) != NULL) { wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_NONE; } - } else if (ffStrEquals(interface, kde_output_order_v1_interface.name)) { - ffWaylandHandleKdeOutputOrder(wldata, registry, name, version); } else if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_GLOBAL || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE) && ffStrEquals(interface, zxdg_output_manager_v1_interface.name)) { ffWaylandHandleZxdgOutput(wldata, registry, name, version); } else if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_GLOBAL || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE) && ffStrEquals(interface, wp_color_manager_v1_interface.name)) { @@ -259,7 +261,7 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result) { data.ffwl_proxy_destroy(registry); ffwl_display_disconnect(data.display); - if (data.primaryDisplayId == 0 && result->wmProcessName.length > 0) { + { const char* fileName = ffStrbufEqualS(&result->wmProcessName, "gnome-shell") ? "monitors.xml" : ffStrbufEqualS(&result->wmProcessName, "cinnamon") @@ -306,7 +308,14 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result) { if (end < monitorsXml.length) { ffStrbufSubstrBefore(&monitorsXml, end); const char* name = monitorsXml.chars + start + strlen(""); - data.primaryDisplayId = ffWaylandGenerateIdFromName(name); + uint64_t primaryDisplayId = ffWaylandGenerateIdFromName(name); + + FF_LIST_FOR_EACH (FFDisplayResult, d, data.result->displays) { + if (d->id == primaryDisplayId) { + d->primary = true; + break; + } + } } } } @@ -314,15 +323,6 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result) { } } - if (data.primaryDisplayId) { - FF_LIST_FOR_EACH (FFDisplayResult, d, data.result->displays) { - if (d->id == data.primaryDisplayId) { - d->primary = true; - break; - } - } - } - // We successfully connected to wayland and detected the display. // So we can set set the session type to wayland. // This is used as an indicator that we are running wayland by the x11 backends. diff --git a/src/detection/displayserver/linux/wayland/wayland.h b/src/detection/displayserver/linux/wayland/wayland.h index 480a7ad58..90dc8c9d1 100644 --- a/src/detection/displayserver/linux/wayland/wayland.h +++ b/src/detection/displayserver/linux/wayland/wayland.h @@ -16,7 +16,8 @@ static inline uint32_t min(uint32_t a, uint32_t b) { typedef enum FF_A_PACKED WaylandProtocolType { FF_WAYLAND_PROTOCOL_TYPE_NONE, FF_WAYLAND_PROTOCOL_TYPE_GLOBAL, - FF_WAYLAND_PROTOCOL_TYPE_KDE, + FF_WAYLAND_PROTOCOL_TYPE_KDE_DEPRECATED, + FF_WAYLAND_PROTOCOL_TYPE_KDE_REGISTRY, } WaylandProtocolType; typedef struct WaylandData { @@ -27,7 +28,6 @@ typedef struct WaylandData { FF_LIBRARY_SYMBOL(wl_display_roundtrip) struct wl_display* display; WaylandProtocolType protocolType; - uint64_t primaryDisplayId; struct wl_proxy* zxdgOutputManager; struct wl_proxy* wpColorManager; } WaylandData; @@ -57,6 +57,7 @@ typedef struct WaylandDisplay { uint16_t mweek; uint32_t serial; uint8_t bitDepth; + bool primary; } WaylandDisplay; inline static void stubListener(void* data, ...) { @@ -80,6 +81,7 @@ void ffWaylandOutputDescriptionListener(void* data, FF_A_UNUSED void* output, co uint32_t ffWaylandHandleRotation(WaylandDisplay* display); const char* ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version); +const char* ffWaylandHandleKdeOutputRegistry(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version); const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version); const char* ffWaylandHandleKdeOutputOrder(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version); const char* ffWaylandHandleZxdgOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version);