diff --git a/autotests/integration/shell_client_test.cpp b/autotests/integration/shell_client_test.cpp
index edfefc2720..a0573537f1 100644
--- a/autotests/integration/shell_client_test.cpp
+++ b/autotests/integration/shell_client_test.cpp
@@ -29,6 +29,7 @@ along with this program. If not, see .
#include
#include
#include
+#include
#include
#include
#include
@@ -59,6 +60,8 @@ private Q_SLOTS:
void testMapUnmapMap();
void testDesktopPresenceChanged();
void testTransientPositionAfterRemap();
+ void testWindowOutputs_data();
+ void testWindowOutputs();
void testMinimizeActiveWindow_data();
void testMinimizeActiveWindow();
void testFullscreen_data();
@@ -81,6 +84,8 @@ void TestShellClient::initTestCase()
{
qRegisterMetaType();
qRegisterMetaType();
+ qRegisterMetaType();
+
QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated);
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
@@ -269,6 +274,52 @@ void TestShellClient::testTransientPositionAfterRemap()
QCOMPARE(transient->geometry(), QRect(c->geometry().topLeft() + QPoint(5, 10), QSize(50, 40)));
}
+void TestShellClient::testWindowOutputs_data()
+{
+ QTest::addColumn("type");
+
+ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell;
+ QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5;
+}
+
+void TestShellClient::testWindowOutputs()
+{
+ QScopedPointer surface(Test::createSurface());
+ QFETCH(Test::ShellSurfaceType, type);
+ QScopedPointer shellSurface(Test::createShellSurface(type, surface.data()));
+ auto size = QSize(200,200);
+
+ QSignalSpy outputEnteredSpy(surface.data(), &Surface::outputEntered);
+ QSignalSpy outputLeftSpy(surface.data(), &Surface::outputLeft);
+
+ auto c = Test::renderAndWaitForShown(surface.data(), size, Qt::blue);
+ //move to be in the first screen
+ c->setGeometry(QRect(QPoint(100,100), size));
+ //we don't don't know where the compositor first placed this window,
+ //this might fire, it might not
+ outputEnteredSpy.wait(5);
+ outputEnteredSpy.clear();
+
+ QCOMPARE(surface->outputs().count(), 1);
+ QCOMPARE(surface->outputs().first()->globalPosition(), QPoint(0,0));
+
+ //move to overlapping both first and second screen
+ c->setGeometry(QRect(QPoint(1250,100), size));
+ QVERIFY(outputEnteredSpy.wait());
+ QCOMPARE(outputEnteredSpy.count(), 1);
+ QCOMPARE(outputLeftSpy.count(), 0);
+ QCOMPARE(surface->outputs().count(), 2);
+ QVERIFY(surface->outputs()[0] != surface->outputs()[1]);
+
+ //move entirely into second screen
+ c->setGeometry(QRect(QPoint(1400,100), size));
+ QVERIFY(outputLeftSpy.wait());
+ QCOMPARE(outputEnteredSpy.count(), 1);
+ QCOMPARE(outputLeftSpy.count(), 1);
+ QCOMPARE(surface->outputs().count(), 1);
+ QCOMPARE(surface->outputs().first()->globalPosition(), QPoint(1280,0));
+}
+
void TestShellClient::testMinimizeActiveWindow_data()
{
QTest::addColumn("type");
diff --git a/shell_client.cpp b/shell_client.cpp
index 82e6bb8753..6f11b225d4 100644
--- a/shell_client.cpp
+++ b/shell_client.cpp
@@ -28,12 +28,14 @@ along with this program. If not, see .
#include "workspace.h"
#include "virtualdesktops.h"
#include "workspace.h"
+#include "screens.h"
#include "decorations/decorationbridge.h"
#include "decorations/decoratedclient.h"
#include
#include
#include
+#include
#include
#include
#include
@@ -173,6 +175,9 @@ void ShellClient::initSurface(T *shellSurface)
connect(shellSurface, &T::fullscreenChanged, this, &ShellClient::clientFullScreenChanged);
connect(shellSurface, &T::transientForChanged, this, &ShellClient::setTransient);
+
+ connect(this, &ShellClient::geometryChanged, this, &ShellClient::updateClientOutputs);
+ connect(screens(), &Screens::changed, this, &ShellClient::updateClientOutputs);
}
void ShellClient::init()
@@ -1522,4 +1527,17 @@ void ShellClient::popupDone()
}
}
+void ShellClient::updateClientOutputs()
+{
+ QVector clientOutputs;
+ const auto outputs = waylandServer()->display()->outputs();
+ for (OutputInterface* output: qAsConst(outputs)) {
+ const QRect outputGeom(output->globalPosition(), output->pixelSize() / output->scale());
+ if (geometry().intersects(outputGeom)) {
+ clientOutputs << output;
+ }
+ }
+ surface()->setOutputs(clientOutputs);
+}
+
}
diff --git a/shell_client.h b/shell_client.h
index 1328ad747f..401de11ae0 100644
--- a/shell_client.h
+++ b/shell_client.h
@@ -185,6 +185,7 @@ private:
void markAsMapped();
void setTransient();
bool shouldExposeToWindowManagement();
+ void updateClientOutputs();
KWayland::Server::XdgShellSurfaceInterface::States xdgSurfaceStates() const;
void updateShowOnScreenEdge();
static void deleteClient(ShellClient *c);