[client] Ensure PlasmaWindowManagement updates active window if it goes away

Summary:
So far when the active PlasmaWindow got unmapped or destroyed, the
PlasmaWindowManagement didn't update the activeWindow. This means it
could expose a deleted object through it's API which could result in
a crash.

This change addresses the problem by updating the active window when
a window gets unmapped or destroyed.

Test Plan: Tests added which exposed the problem

Reviewers: #plasma, hein

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D1621
This commit is contained in:
Martin Gräßlin 2016-05-17 08:59:26 +02:00
parent 372955bf05
commit 2c5bc69d1d

View file

@ -46,6 +46,8 @@ private Q_SLOTS:
void testMinimizedGeometry();
void testUseAfterUnmap();
void testServerDelete();
void testActiveWindowOnUnmapped();
void testDeleteActiveWindow();
void cleanup();
@ -258,5 +260,54 @@ void TestWindowManagement::testServerDelete()
m_window = nullptr;
}
void TestWindowManagement::testActiveWindowOnUnmapped()
{
// This test verifies that unmapping the active window changes the active window.
// first make the window active
QVERIFY(!m_windowManagement->activeWindow());
QVERIFY(!m_window->isActive());
QSignalSpy activeWindowChangedSpy(m_windowManagement, &KWayland::Client::PlasmaWindowManagement::activeWindowChanged);
QVERIFY(activeWindowChangedSpy.isValid());
m_windowInterface->setActive(true);
QVERIFY(activeWindowChangedSpy.wait());
QCOMPARE(m_windowManagement->activeWindow(), m_window);
QVERIFY(m_window->isActive());
// now unmap should change the active window
QSignalSpy destroyedSpy(m_window, &QObject::destroyed);
QVERIFY(destroyedSpy.isValid());
QSignalSpy serverDestroyedSpy(m_windowInterface, &QObject::destroyed);
QVERIFY(serverDestroyedSpy.isValid());
m_windowManagementInterface->unmapWindow(m_windowInterface);
QVERIFY(activeWindowChangedSpy.wait());
QVERIFY(!m_windowManagement->activeWindow());
QVERIFY(destroyedSpy.wait());
QCOMPARE(destroyedSpy.count(), 1);
m_window = nullptr;
QVERIFY(serverDestroyedSpy.wait());
m_windowInterface = nullptr;
}
void TestWindowManagement::testDeleteActiveWindow()
{
// This test verifies that deleting the active window on client side changes the active window
// first make the window active
QVERIFY(!m_windowManagement->activeWindow());
QVERIFY(!m_window->isActive());
QSignalSpy activeWindowChangedSpy(m_windowManagement, &KWayland::Client::PlasmaWindowManagement::activeWindowChanged);
QVERIFY(activeWindowChangedSpy.isValid());
m_windowInterface->setActive(true);
QVERIFY(activeWindowChangedSpy.wait());
QCOMPARE(activeWindowChangedSpy.count(), 1);
QCOMPARE(m_windowManagement->activeWindow(), m_window);
QVERIFY(m_window->isActive());
// delete the client side window - that's semantically kind of wrong, but shouldn't make our code crash
delete m_window;
m_window = nullptr;
QCOMPARE(activeWindowChangedSpy.count(), 2);
QVERIFY(!m_windowManagement->activeWindow());
}
QTEST_GUILESS_MAIN(TestWindowManagement)
#include "test_wayland_windowmanagement.moc"