From f10760d8a9bee194dd2d02008c6bb02f49ff2da3 Mon Sep 17 00:00:00 2001 From: Vlad Zagorodniy Date: Tue, 12 Mar 2019 11:35:17 +0200 Subject: [PATCH] [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 --- .../integration/move_resize_window_test.cpp | 170 ++++++++++++++++++ shell_client.cpp | 6 + 2 files changed, 176 insertions(+) diff --git a/autotests/integration/move_resize_window_test.cpp b/autotests/integration/move_resize_window_test.cpp index 3e5e460d06..e605c12ec0 100644 --- a/autotests/integration/move_resize_window_test.cpp +++ b/autotests/integration/move_resize_window_test.cpp @@ -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(Test::createSurface()); + QVERIFY(!surface.isNull()); + QScopedPointer 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(Test::createSurface()); + QVERIFY(!surface.isNull()); + QScopedPointer 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(Test::createSurface()); + QVERIFY(!surface.isNull()); + QScopedPointer 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(Test::createSurface()); + QVERIFY(!surface.isNull()); + QScopedPointer 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) diff --git a/shell_client.cpp b/shell_client.cpp index f354766005..1f46196983 100644 --- a/shell_client.cpp +++ b/shell_client.cpp @@ -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()) {