[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 testResizeForVirtualKeyboard();
|
||||||
void testResizeForVirtualKeyboardWithMaximize();
|
void testResizeForVirtualKeyboardWithMaximize();
|
||||||
void testResizeForVirtualKeyboardWithFullScreen();
|
void testResizeForVirtualKeyboardWithFullScreen();
|
||||||
|
void testDestroyMoveClient();
|
||||||
|
void testDestroyResizeClient();
|
||||||
|
void testUnmapMoveClient();
|
||||||
|
void testUnmapResizeClient();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KWayland::Client::ConnectionThread *m_connection = nullptr;
|
KWayland::Client::ConnectionThread *m_connection = nullptr;
|
||||||
|
@ -986,6 +990,172 @@ void MoveResizeWindowTest::testResizeForVirtualKeyboardWithFullScreen()
|
||||||
QCOMPARE(client->geometry(), QRect(0, 0, 1280, 1024));
|
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)
|
WAYLANDTEST_MAIN(KWin::MoveResizeWindowTest)
|
||||||
|
|
|
@ -386,6 +386,9 @@ void ShellClient::finishInit() {
|
||||||
void ShellClient::destroyClient()
|
void ShellClient::destroyClient()
|
||||||
{
|
{
|
||||||
m_closing = true;
|
m_closing = true;
|
||||||
|
if (isMoveResize()) {
|
||||||
|
leaveMoveResize();
|
||||||
|
}
|
||||||
Deleted *del = nullptr;
|
Deleted *del = nullptr;
|
||||||
if (workspace()) {
|
if (workspace()) {
|
||||||
del = Deleted::create(this);
|
del = Deleted::create(this);
|
||||||
|
@ -1188,6 +1191,9 @@ void ShellClient::resizeWithChecks(int w, int h, ForceGeometry_t force)
|
||||||
void ShellClient::unmap()
|
void ShellClient::unmap()
|
||||||
{
|
{
|
||||||
m_unmapped = true;
|
m_unmapped = true;
|
||||||
|
if (isMoveResize()) {
|
||||||
|
leaveMoveResize();
|
||||||
|
}
|
||||||
m_requestedClientSize = QSize(0, 0);
|
m_requestedClientSize = QSize(0, 0);
|
||||||
destroyWindowManagementInterface();
|
destroyWindowManagementInterface();
|
||||||
if (Workspace::self()) {
|
if (Workspace::self()) {
|
||||||
|
|
Loading…
Reference in a new issue