From aa739c59cf6137e0e505f574405a7dfffc5059f0 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Sat, 16 Jul 2022 14:01:20 +0300 Subject: [PATCH] wayland: Make mapping from xinerama indices to Output correct We assume that outputs in kwinApp()->platform()->enabledOutputs() are stored in the xinerama order. However, this is not the case on Wayland and it's not going to be changed because it increases the complexity. This change makes Workspace::xineramaIndexToOutput() use Xinerama extension API to map a xinerama index to the associated Output object. With this, Xwayland applications will be able to put on outputs as expected. Note that xinerama indices are not cached because Workspace::xineramaIndexToOutput() is not used in any hot code path. If that changes, xinerama indices can be cached. The cache must be invalidated whenever we get screens changed notify event from RANDR. --- CMakeLists.txt | 1 + src/CMakeLists.txt | 1 + src/workspace.cpp | 34 +++++++++++++++++++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 202b06e30e..4916d0f47d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -281,6 +281,7 @@ find_package(XCB 1.10 REQUIRED COMPONENTS SYNC XCB XFIXES + XINERAMA ) set_package_properties(XCB PROPERTIES TYPE REQUIRED) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9fef87e009..0bd7e665fa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -200,6 +200,7 @@ target_link_libraries(kwin XCB::SYNC XCB::XCB XCB::XFIXES + XCB::XINERAMA UDev::UDev XKB::XKB diff --git a/src/workspace.cpp b/src/workspace.cpp index 57b569b73a..da1f354a3c 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -60,6 +60,8 @@ #include // Qt #include +// xcb +#include namespace KWin { @@ -2354,7 +2356,37 @@ int Workspace::oldDisplayHeight() const Output *Workspace::xineramaIndexToOutput(int index) const { - return kwinApp()->platform()->enabledOutputs().value(index); + xcb_connection_t *connection = kwinApp()->x11Connection(); + if (!connection) { + return nullptr; + } + + const ScopedCPointer active{xcb_xinerama_is_active_reply(connection, xcb_xinerama_is_active(connection), nullptr)}; + if (!active || !active->state) { + return nullptr; + } + + const ScopedCPointer screens(xcb_xinerama_query_screens_reply(connection, xcb_xinerama_query_screens(connection), nullptr)); + if (!screens) { + return nullptr; + } + + const int infoCount = xcb_xinerama_query_screens_screen_info_length(screens.data()); + if (index >= infoCount) { + return nullptr; + } + + const xcb_xinerama_screen_info_t *infos = xcb_xinerama_query_screens_screen_info(screens.data()); + const QRect needle(infos[index].x_org, infos[index].y_org, infos[index].width, infos[index].height); + + const auto haystack = kwinApp()->platform()->enabledOutputs(); + for (Output *output : haystack) { + if (Xcb::toXNative(output->geometry()) == needle) { + return output; + } + } + + return nullptr; } Output *Workspace::activeOutput() const