[wayland] Finish active move-resize op when client is destroyed or unmapped
Summary: It might happen that the moving client gets closed or crashes. In that case, we have to manually reset Workspace::movingClient, otherwise KWin will most likely crash later on. BUG: 405379 Reviewers: #kwin, davidedmundson Reviewed By: #kwin, davidedmundson Subscribers: davidedmundson, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D19708
This commit is contained in:
parent
3024a7358b
commit
f10760d8a9
2 changed files with 176 additions and 0 deletions
|
@ -80,6 +80,10 @@ private Q_SLOTS:
|
|||
void testResizeForVirtualKeyboard();
|
||||
void testResizeForVirtualKeyboardWithMaximize();
|
||||
void testResizeForVirtualKeyboardWithFullScreen();
|
||||
void testDestroyMoveClient();
|
||||
void testDestroyResizeClient();
|
||||
void testUnmapMoveClient();
|
||||
void testUnmapResizeClient();
|
||||
|
||||
private:
|
||||
KWayland::Client::ConnectionThread *m_connection = nullptr;
|
||||
|
@ -986,6 +990,172 @@ void MoveResizeWindowTest::testResizeForVirtualKeyboardWithFullScreen()
|
|||
QCOMPARE(client->geometry(), QRect(0, 0, 1280, 1024));
|
||||
}
|
||||
|
||||
void MoveResizeWindowTest::testDestroyMoveClient()
|
||||
{
|
||||
// This test verifies that active move operation gets finished when
|
||||
// the associated client is destroyed.
|
||||
|
||||
// Create the test client.
|
||||
using namespace KWayland::Client;
|
||||
QScopedPointer<Surface> surface(Test::createSurface());
|
||||
QVERIFY(!surface.isNull());
|
||||
QScopedPointer<XdgShellSurface> shellSurface(Test::createXdgShellStableSurface(surface.data()));
|
||||
QVERIFY(!shellSurface.isNull());
|
||||
ShellClient *client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(client);
|
||||
|
||||
// Start moving the client.
|
||||
QSignalSpy clientStartMoveResizedSpy(client, &AbstractClient::clientStartUserMovedResized);
|
||||
QVERIFY(clientStartMoveResizedSpy.isValid());
|
||||
QSignalSpy clientFinishUserMovedResizedSpy(client, &AbstractClient::clientFinishUserMovedResized);
|
||||
QVERIFY(clientFinishUserMovedResizedSpy.isValid());
|
||||
|
||||
QCOMPARE(workspace()->getMovingClient(), nullptr);
|
||||
QCOMPARE(client->isMove(), false);
|
||||
QCOMPARE(client->isResize(), false);
|
||||
workspace()->slotWindowMove();
|
||||
QCOMPARE(clientStartMoveResizedSpy.count(), 1);
|
||||
QCOMPARE(workspace()->getMovingClient(), client);
|
||||
QCOMPARE(client->isMove(), true);
|
||||
QCOMPARE(client->isResize(), false);
|
||||
|
||||
// Let's pretend that the client crashed.
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
QCOMPARE(clientFinishUserMovedResizedSpy.count(), 0);
|
||||
QCOMPARE(workspace()->getMovingClient(), nullptr);
|
||||
}
|
||||
|
||||
void MoveResizeWindowTest::testDestroyResizeClient()
|
||||
{
|
||||
// This test verifies that active resize operation gets finished when
|
||||
// the associated client is destroyed.
|
||||
|
||||
// Create the test client.
|
||||
using namespace KWayland::Client;
|
||||
QScopedPointer<Surface> surface(Test::createSurface());
|
||||
QVERIFY(!surface.isNull());
|
||||
QScopedPointer<XdgShellSurface> shellSurface(Test::createXdgShellStableSurface(surface.data()));
|
||||
QVERIFY(!shellSurface.isNull());
|
||||
ShellClient *client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(client);
|
||||
|
||||
// Start resizing the client.
|
||||
QSignalSpy clientStartMoveResizedSpy(client, &AbstractClient::clientStartUserMovedResized);
|
||||
QVERIFY(clientStartMoveResizedSpy.isValid());
|
||||
QSignalSpy clientFinishUserMovedResizedSpy(client, &AbstractClient::clientFinishUserMovedResized);
|
||||
QVERIFY(clientFinishUserMovedResizedSpy.isValid());
|
||||
|
||||
QCOMPARE(workspace()->getMovingClient(), nullptr);
|
||||
QCOMPARE(client->isMove(), false);
|
||||
QCOMPARE(client->isResize(), false);
|
||||
workspace()->slotWindowResize();
|
||||
QCOMPARE(clientStartMoveResizedSpy.count(), 1);
|
||||
QCOMPARE(workspace()->getMovingClient(), client);
|
||||
QCOMPARE(client->isMove(), false);
|
||||
QCOMPARE(client->isResize(), true);
|
||||
|
||||
// Let's pretend that the client crashed.
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
QCOMPARE(clientFinishUserMovedResizedSpy.count(), 0);
|
||||
QCOMPARE(workspace()->getMovingClient(), nullptr);
|
||||
}
|
||||
|
||||
void MoveResizeWindowTest::testUnmapMoveClient()
|
||||
{
|
||||
// This test verifies that active move operation gets cancelled when
|
||||
// the associated client is unmapped.
|
||||
|
||||
// Create the test client.
|
||||
using namespace KWayland::Client;
|
||||
QScopedPointer<Surface> surface(Test::createSurface());
|
||||
QVERIFY(!surface.isNull());
|
||||
QScopedPointer<XdgShellSurface> shellSurface(Test::createXdgShellStableSurface(surface.data()));
|
||||
QVERIFY(!shellSurface.isNull());
|
||||
ShellClient *client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(client);
|
||||
|
||||
// Start resizing the client.
|
||||
QSignalSpy clientStartMoveResizedSpy(client, &AbstractClient::clientStartUserMovedResized);
|
||||
QVERIFY(clientStartMoveResizedSpy.isValid());
|
||||
QSignalSpy clientFinishUserMovedResizedSpy(client, &AbstractClient::clientFinishUserMovedResized);
|
||||
QVERIFY(clientFinishUserMovedResizedSpy.isValid());
|
||||
|
||||
QCOMPARE(workspace()->getMovingClient(), nullptr);
|
||||
QCOMPARE(client->isMove(), false);
|
||||
QCOMPARE(client->isResize(), false);
|
||||
workspace()->slotWindowMove();
|
||||
QCOMPARE(clientStartMoveResizedSpy.count(), 1);
|
||||
QCOMPARE(workspace()->getMovingClient(), client);
|
||||
QCOMPARE(client->isMove(), true);
|
||||
QCOMPARE(client->isResize(), false);
|
||||
|
||||
// Unmap the client while we're moving it.
|
||||
QSignalSpy hiddenSpy(client, &ShellClient::windowHidden);
|
||||
QVERIFY(hiddenSpy.isValid());
|
||||
surface->attachBuffer(Buffer::Ptr());
|
||||
surface->commit(Surface::CommitFlag::None);
|
||||
QVERIFY(hiddenSpy.wait());
|
||||
QCOMPARE(clientFinishUserMovedResizedSpy.count(), 0);
|
||||
QCOMPARE(workspace()->getMovingClient(), nullptr);
|
||||
QCOMPARE(client->isMove(), false);
|
||||
QCOMPARE(client->isResize(), false);
|
||||
|
||||
// Destroy the client.
|
||||
shellSurface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
QCOMPARE(clientFinishUserMovedResizedSpy.count(), 0);
|
||||
}
|
||||
|
||||
void MoveResizeWindowTest::testUnmapResizeClient()
|
||||
{
|
||||
// This test verifies that active resize operation gets cancelled when
|
||||
// the associated client is unmapped.
|
||||
|
||||
// Create the test client.
|
||||
using namespace KWayland::Client;
|
||||
QScopedPointer<Surface> surface(Test::createSurface());
|
||||
QVERIFY(!surface.isNull());
|
||||
QScopedPointer<XdgShellSurface> shellSurface(Test::createXdgShellStableSurface(surface.data()));
|
||||
QVERIFY(!shellSurface.isNull());
|
||||
ShellClient *client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(client);
|
||||
|
||||
// Start resizing the client.
|
||||
QSignalSpy clientStartMoveResizedSpy(client, &AbstractClient::clientStartUserMovedResized);
|
||||
QVERIFY(clientStartMoveResizedSpy.isValid());
|
||||
QSignalSpy clientFinishUserMovedResizedSpy(client, &AbstractClient::clientFinishUserMovedResized);
|
||||
QVERIFY(clientFinishUserMovedResizedSpy.isValid());
|
||||
|
||||
QCOMPARE(workspace()->getMovingClient(), nullptr);
|
||||
QCOMPARE(client->isMove(), false);
|
||||
QCOMPARE(client->isResize(), false);
|
||||
workspace()->slotWindowResize();
|
||||
QCOMPARE(clientStartMoveResizedSpy.count(), 1);
|
||||
QCOMPARE(workspace()->getMovingClient(), client);
|
||||
QCOMPARE(client->isMove(), false);
|
||||
QCOMPARE(client->isResize(), true);
|
||||
|
||||
// Unmap the client while we're resizing it.
|
||||
QSignalSpy hiddenSpy(client, &ShellClient::windowHidden);
|
||||
QVERIFY(hiddenSpy.isValid());
|
||||
surface->attachBuffer(Buffer::Ptr());
|
||||
surface->commit(Surface::CommitFlag::None);
|
||||
QVERIFY(hiddenSpy.wait());
|
||||
QCOMPARE(clientFinishUserMovedResizedSpy.count(), 0);
|
||||
QCOMPARE(workspace()->getMovingClient(), nullptr);
|
||||
QCOMPARE(client->isMove(), false);
|
||||
QCOMPARE(client->isResize(), false);
|
||||
|
||||
// Destroy the client.
|
||||
shellSurface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
QCOMPARE(clientFinishUserMovedResizedSpy.count(), 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(KWin::MoveResizeWindowTest)
|
||||
|
|
|
@ -386,6 +386,9 @@ void ShellClient::finishInit() {
|
|||
void ShellClient::destroyClient()
|
||||
{
|
||||
m_closing = true;
|
||||
if (isMoveResize()) {
|
||||
leaveMoveResize();
|
||||
}
|
||||
Deleted *del = nullptr;
|
||||
if (workspace()) {
|
||||
del = Deleted::create(this);
|
||||
|
@ -1188,6 +1191,9 @@ void ShellClient::resizeWithChecks(int w, int h, ForceGeometry_t force)
|
|||
void ShellClient::unmap()
|
||||
{
|
||||
m_unmapped = true;
|
||||
if (isMoveResize()) {
|
||||
leaveMoveResize();
|
||||
}
|
||||
m_requestedClientSize = QSize(0, 0);
|
||||
destroyWindowManagementInterface();
|
||||
if (Workspace::self()) {
|
||||
|
|
Loading…
Reference in a new issue