Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit f0971532 authored by David Edmundson's avatar David Edmundson

Send output enter/leave events to surfaces

Summary:
A surface has an API to know which screen(s) it's on, this is useful
especially for knowing the scale it should render at.

In practice Qt currently doesn't do anything with this information; but
that's set to change.

Test_helpers is changed as we need to create output objects in order for
wl_surface to map them.

Closes task T4467

Test Plan:
Attached unit test.
As mentioned above, it doesn't have any real world impact currently, so not a lot
to test.

Reviewers: #plasma, graesslin

Reviewed By: #plasma, graesslin

Subscribers: johanhelsing, graesslin, plasma-devel, kwin, #kwin

Tags: #kwin

Maniphest Tasks: T4467

Differential Revision: https://phabricator.kde.org/D7359
parent 981662a6
......@@ -29,6 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <KWayland/Client/connection_thread.h>
#include <KWayland/Client/compositor.h>
#include <KWayland/Client/shell.h>
#include <KWayland/Client/output.h>
#include <KWayland/Client/server_decoration.h>
#include <KWayland/Client/surface.h>
#include <KWayland/Client/xdgshell.h>
......@@ -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<KWin::ShellClient*>();
qRegisterMetaType<KWin::AbstractClient*>();
qRegisterMetaType<KWayland::Client::Output*>();
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<Test::ShellSurfaceType>("type");
QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell;
QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5;
}
void TestShellClient::testWindowOutputs()
{
QScopedPointer<Surface> surface(Test::createSurface());
QFETCH(Test::ShellSurfaceType, type);
QScopedPointer<QObject> 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<Test::ShellSurfaceType>("type");
......
......@@ -28,12 +28,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "workspace.h"
#include "virtualdesktops.h"
#include "workspace.h"
#include "screens.h"
#include "decorations/decorationbridge.h"
#include "decorations/decoratedclient.h"
#include <KDecoration2/Decoration>
#include <KDecoration2/DecoratedClient>
#include <KWayland/Client/surface.h>
#include <KWayland/Server/display.h>
#include <KWayland/Server/clientconnection.h>
#include <KWayland/Server/seat_interface.h>
#include <KWayland/Server/shell_interface.h>
......@@ -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<OutputInterface*> 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);
}
}
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment