From 1403fcf3168551eb3eb4a8cd0998d9c78baa5aa3 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Fri, 18 May 2018 14:16:13 +0100 Subject: [PATCH] Add XDG Output support Test Plan: Very minimal expansion of unit tests which uses WaylandScreens Wrote mini app to debug actual output of xdg-output for testing the DRM code Main relevant user of this is xwayland > 1.20 which I don't have, so that part remains untested Reviewers: #plasma, graesslin Reviewed By: #plasma, graesslin Subscribers: romangg, graesslin, bshah, kwin Tags: #kwin Maniphest Tasks: T8501 Differential Revision: https://phabricator.kde.org/D12243 --- autotests/integration/screen_changes_test.cpp | 17 +++++++++++++++++ plugins/platforms/drm/drm_output.cpp | 16 +++++++++++++++- plugins/platforms/drm/drm_output.h | 2 ++ wayland_server.cpp | 12 ++++++++++++ wayland_server.h | 6 ++++++ 5 files changed, 52 insertions(+), 1 deletion(-) diff --git a/autotests/integration/screen_changes_test.cpp b/autotests/integration/screen_changes_test.cpp index 112bbe535a..0a691124ef 100644 --- a/autotests/integration/screen_changes_test.cpp +++ b/autotests/integration/screen_changes_test.cpp @@ -24,6 +24,7 @@ along with this program. If not, see . #include "wayland_server.h" #include +#include #include using namespace KWin; @@ -84,6 +85,8 @@ void ScreenChangesTest::testScreenAddRemove() QVERIFY(registry.isValid()); registry.setup(); QVERIFY(allAnnounced.wait()); + const auto xdgOMData = registry.interface(Registry::Interface::XdgOutputUnstableV1); + auto xdgOutputManager = registry.createXdgOutputManager(xdgOMData.name, xdgOMData.version); // should be one output QCOMPARE(screens()->count(), 1); @@ -138,6 +141,20 @@ void ScreenChangesTest::testScreenAddRemove() QVERIFY(o2ChangedSpy.wait()); QCOMPARE(o2->geometry(), geometries.at(1)); + //and check XDGOutput is synced + QScopedPointer xdgO1(xdgOutputManager->getXdgOutput(o1.data())); + QSignalSpy xdgO1ChangedSpy(xdgO1.data(), &XdgOutput::changed); + QVERIFY(xdgO1ChangedSpy.isValid()); + QVERIFY(xdgO1ChangedSpy.wait()); + QCOMPARE(xdgO1->logicalPosition(), geometries.at(0).topLeft()); + QCOMPARE(xdgO1->logicalSize(), geometries.at(0).size()); + QScopedPointer xdgO2(xdgOutputManager->getXdgOutput(o2.data())); + QSignalSpy xdgO2ChangedSpy(xdgO2.data(), &XdgOutput::changed); + QVERIFY(xdgO2ChangedSpy.isValid()); + QVERIFY(xdgO2ChangedSpy.wait()); + QCOMPARE(xdgO2->logicalPosition(), geometries.at(1).topLeft()); + QCOMPARE(xdgO2->logicalSize(), geometries.at(1).size()); + // now let's try to remove one output again outputAnnouncedSpy.clear(); outputRemovedSpy.clear(); diff --git a/plugins/platforms/drm/drm_output.cpp b/plugins/platforms/drm/drm_output.cpp index fb09ae1d27..de7d511283 100644 --- a/plugins/platforms/drm/drm_output.cpp +++ b/plugins/platforms/drm/drm_output.cpp @@ -39,6 +39,7 @@ along with this program. If not, see . #include #include #include +#include // KF5 #include #include @@ -181,7 +182,7 @@ QSize DrmOutput::physicalSize() const QRect DrmOutput::geometry() const { - return QRect(m_globalPos, pixelSize() / scale()); + return QRect(m_globalPos, pixelSize() / m_scale); } qreal DrmOutput::scale() const @@ -344,12 +345,17 @@ void DrmOutput::initOutput() m_waylandOutput.clear(); } m_waylandOutput = waylandServer()->display()->createOutput(); + m_xdgOutput = waylandServer()->xdgOutputManager()->createXdgOutput(m_waylandOutput, m_waylandOutput); connect(this, &DrmOutput::modeChanged, this, [this] { if (m_waylandOutput.isNull()) { return; } m_waylandOutput->setCurrentMode(QSize(m_mode.hdisplay, m_mode.vdisplay), refreshRateForMode(&m_mode)); + if (m_xdgOutput) { + m_xdgOutput->setLogicalSize(pixelSize() / m_scale); + m_xdgOutput->done(); + } } ); m_waylandOutput->setManufacturer(m_waylandOutputDevice->manufacturer()); @@ -785,6 +791,10 @@ void DrmOutput::setGlobalPos(const QPoint &pos) if (m_waylandOutputDevice) { m_waylandOutputDevice->setGlobalPosition(pos); } + if (m_xdgOutput) { + m_xdgOutput->setLogicalPosition(pos); + m_xdgOutput->done(); + } } void DrmOutput::setScale(qreal scale) @@ -796,6 +806,10 @@ void DrmOutput::setScale(qreal scale) if (m_waylandOutputDevice) { m_waylandOutputDevice->setScale(scale); } + if (m_xdgOutput) { + m_xdgOutput->setLogicalSize(pixelSize() / m_scale); + m_xdgOutput->done(); + } } void DrmOutput::setChanges(KWayland::Server::OutputChangeSet *changes) diff --git a/plugins/platforms/drm/drm_output.h b/plugins/platforms/drm/drm_output.h index 2206bfac22..cbd4f997c1 100644 --- a/plugins/platforms/drm/drm_output.h +++ b/plugins/platforms/drm/drm_output.h @@ -41,6 +41,7 @@ class OutputInterface; class OutputDeviceInterface; class OutputChangeSet; class OutputManagementInterface; +class XdgOutputInterface; } } @@ -184,6 +185,7 @@ private: drmModeModeInfo m_mode; Edid m_edid; QPointer m_waylandOutput; + QPointer m_xdgOutput; QPointer m_waylandOutputDevice; QPointer m_changeset; KWin::ScopedDrmPointer<_drmModeProperty, &drmModeFreeProperty> m_dpms; diff --git a/wayland_server.cpp b/wayland_server.cpp index 78ab4c332e..d1d9a70627 100644 --- a/wayland_server.cpp +++ b/wayland_server.cpp @@ -58,6 +58,8 @@ along with this program. If not, see . #include #include #include +#include + // Qt #include @@ -354,6 +356,9 @@ bool WaylandServer::init(const QByteArray &socketName, InitalizationFlags flags) }); m_outputManagement->create(); + m_xdgOutputManager = m_display->createXdgOutputManager(m_display); + m_xdgOutputManager->create(); + m_display->createSubCompositor(m_display)->create(); m_XdgForeign = m_display->createXdgForeignInterface(m_display); @@ -453,11 +458,18 @@ void WaylandServer::syncOutputsToWayland() Q_ASSERT(s); for (int i = 0; i < s->count(); ++i) { OutputInterface *output = m_display->createOutput(m_display); + auto xdgOutput = xdgOutputManager()->createXdgOutput(output, output); + output->setScale(s->scale(i)); const QRect &geo = s->geometry(i); output->setGlobalPosition(geo.topLeft()); output->setPhysicalSize(s->physicalSize(i).toSize()); output->addMode(geo.size()); + + xdgOutput->setLogicalPosition(geo.topLeft()); + xdgOutput->setLogicalSize(geo.size()); + xdgOutput->done(); + output->create(); } } diff --git a/wayland_server.h b/wayland_server.h index 03ba8c8627..44c542dd00 100644 --- a/wayland_server.h +++ b/wayland_server.h @@ -60,6 +60,7 @@ class OutputManagementInterface; class OutputConfigurationInterface; class XdgShellInterface; class XdgForeignInterface; +class XdgOutputManagerInterface; } } @@ -104,6 +105,10 @@ public: KWayland::Server::ServerSideDecorationManagerInterface *decorationManager() const { return m_decorationManager; } + KWayland::Server::XdgOutputManagerInterface *xdgOutputManager() const { + return m_xdgOutputManager; + } + QList clients() const { return m_clients; } @@ -227,6 +232,7 @@ private: KWayland::Server::AppMenuManagerInterface *m_appMenuManager = nullptr; KWayland::Server::ServerSideDecorationPaletteManagerInterface *m_paletteManager = nullptr; KWayland::Server::IdleInterface *m_idle = nullptr; + KWayland::Server::XdgOutputManagerInterface *m_xdgOutputManager = nullptr; struct { KWayland::Server::ClientConnection *client = nullptr; QMetaObject::Connection destroyConnection;