[server] Trigger error if a transient request tries to parent to itself
Summary: If the surface passed in the transient request is to the surface of the shell surface, KWin aborts. It's an obvious invalid request, so handle it properly by sending an error. Reviewers: #plasma Subscribers: plasma-devel Tags: #plasma Differential Revision: https://phabricator.kde.org/D1755
This commit is contained in:
parent
b3ccc12b75
commit
076e8ba253
2 changed files with 31 additions and 2 deletions
|
@ -42,6 +42,8 @@ private Q_SLOTS:
|
|||
void cleanup();
|
||||
|
||||
void testMultipleShellSurfacesForSurface();
|
||||
void testTransientForSameSurface_data();
|
||||
void testTransientForSameSurface();
|
||||
|
||||
private:
|
||||
Display *m_display = nullptr;
|
||||
|
@ -143,5 +145,27 @@ void ErrorTest::testMultipleShellSurfacesForSurface()
|
|||
QCOMPARE(m_connection->errorCode(), EPROTO);
|
||||
}
|
||||
|
||||
void ErrorTest::testTransientForSameSurface_data()
|
||||
{
|
||||
QTest::addColumn<ShellSurface::TransientFlag>("flag");
|
||||
|
||||
QTest::newRow("transient") << ShellSurface::TransientFlag::Default;
|
||||
QTest::newRow("transient no focus") << ShellSurface::TransientFlag::NoFocus;
|
||||
}
|
||||
|
||||
void ErrorTest::testTransientForSameSurface()
|
||||
{
|
||||
// this test verifies that creating a transient shell surface for itself triggers a protocol error
|
||||
QSignalSpy errorSpy(m_connection, &ConnectionThread::errorOccurred);
|
||||
QVERIFY(errorSpy.isValid());
|
||||
QScopedPointer<Surface> surface(m_compositor->createSurface());
|
||||
QScopedPointer<ShellSurface> shellSurface(m_shell->createSurface(surface.data()));
|
||||
QFETCH(ShellSurface::TransientFlag, flag);
|
||||
shellSurface->setTransient(surface.data(), QPoint(), flag);
|
||||
QVERIFY(errorSpy.wait());
|
||||
QVERIFY(m_connection->hasError());
|
||||
QCOMPARE(m_connection->errorCode(), EPROTO);
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(ErrorTest)
|
||||
#include "test_error.moc"
|
||||
|
|
|
@ -147,7 +147,7 @@ void ShellInterface::Private::createSurface(wl_client *client, uint32_t version,
|
|||
}
|
||||
);
|
||||
if (it != surfaces.constEnd()) {
|
||||
wl_resource_post_error(surface->resource(), WL_DISPLAY_ERROR_INVALID_OBJECT, "ShellSurface already created");
|
||||
wl_resource_post_error(surface->resource(), WL_SHELL_ERROR_ROLE, "ShellSurface already created");
|
||||
return;
|
||||
}
|
||||
ShellSurfaceInterface *shellSurface = new ShellSurfaceInterface(q, surface, parentResource);
|
||||
|
@ -312,7 +312,12 @@ void ShellSurfaceInterface::Private::setTransientCallback(wl_client *client, wl_
|
|||
Q_UNUSED(flags)
|
||||
auto s = cast<Private>(resource);
|
||||
Q_ASSERT(client == *s->client);
|
||||
s->transientFor = QPointer<SurfaceInterface>(SurfaceInterface::get(parent));
|
||||
auto surface = SurfaceInterface::get(parent);
|
||||
if (surface && s->surface == surface) {
|
||||
wl_resource_post_error(surface->resource(), WL_SHELL_ERROR_ROLE, "Cannot be a transient to itself");
|
||||
return;
|
||||
}
|
||||
s->transientFor = QPointer<SurfaceInterface>(surface);
|
||||
s->transientOffset = QPoint(x, y);
|
||||
emit s->q_func()->transientChanged(!s->transientFor.isNull());
|
||||
emit s->q_func()->transientOffsetChanged(s->transientOffset);
|
||||
|
|
Loading…
Reference in a new issue