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.
master
Vlad Zahorodnii 2 years ago
parent 5a8beacd2b
commit aa739c59cf

@ -281,6 +281,7 @@ find_package(XCB 1.10 REQUIRED COMPONENTS
SYNC
XCB
XFIXES
XINERAMA
)
set_package_properties(XCB PROPERTIES TYPE REQUIRED)

@ -200,6 +200,7 @@ target_link_libraries(kwin
XCB::SYNC
XCB::XCB
XCB::XFIXES
XCB::XINERAMA
UDev::UDev
XKB::XKB

@ -60,6 +60,8 @@
#include <KStartupInfo>
// Qt
#include <QtConcurrentRun>
// xcb
#include <xcb/xinerama.h>
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<xcb_xinerama_is_active_reply_t> active{xcb_xinerama_is_active_reply(connection, xcb_xinerama_is_active(connection), nullptr)};
if (!active || !active->state) {
return nullptr;
}
const ScopedCPointer<xcb_xinerama_query_screens_reply_t> 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

Loading…
Cancel
Save