@@ -15,6 +15,7 @@
1515 */
1616
1717#include <QtTest/QtTest>
18+#include <QSignalSpy>
1819
1920// WindowManager plugin
2021#include <TopLevelWindowModel.h>
@@ -32,6 +33,8 @@ private Q_SLOTS:
3233
3334 void singleSurfaceStartsHidden();
3435 void secondSurfaceIsHidden();
36+ void rootFocus();
37+ void rootFocusInhibit();
3538
3639private:
3740 ApplicationManager *applicationManager{nullptr};
@@ -125,6 +128,63 @@ void tst_TopLevelWindowModel::secondSurfaceIsHidden()
125128 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)firstSurface);
126129}
127130
131+// Ensure that rootFocus unfocuses and refocuses windows
132+void tst_TopLevelWindowModel::rootFocus()
133+{
134+ applicationManager->startApplication(QString("hello-world"), QStringList());
135+
136+ // We need to keep the window's surface null, unlike the other tests,
137+ // because then the TLWM assumes that the window is unknown to MirAL and
138+ // handles focus changes itself. If MirAL and QtMir are behaving properly,
139+ // they mirror this behavior for windows with surfaces.
140+ QCOMPARE(topLevelWindowModel->rowCount(), 1);
141+ QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)nullptr);
142+ auto dummyWindow = topLevelWindowModel->windowAt(0);
143+
144+ auto rootFocusChangedSpy = new QSignalSpy(topLevelWindowModel, &TopLevelWindowModel::rootFocusChanged);
145+
146+ // Unsetting rootFocus will remove focus from the dummy window
147+ topLevelWindowModel->setRootFocus(false);
148+ QVERIFY(!topLevelWindowModel->rootFocus());
149+ QVERIFY(!dummyWindow->focused());
150+ QCOMPARE(rootFocusChangedSpy->count(), 1);
151+
152+ // Setting rootFocus will add focus back to the dummy window
153+ topLevelWindowModel->setRootFocus(true);
154+ QVERIFY(topLevelWindowModel->rootFocus());
155+ QCOMPARE((void*)topLevelWindowModel->focusedWindow(), (void*)dummyWindow);
156+ QCOMPARE(rootFocusChangedSpy->count(), 2);
157+}
158+
159+// Ensure that rootFocus does not refocus a window if we focus another
160+void tst_TopLevelWindowModel::rootFocusInhibit()
161+{
162+ applicationManager->startApplication(QString("1"), QStringList());
163+
164+ auto dummyWindow1 = topLevelWindowModel->windowAt(0);
165+
166+ // Unsetting rootFocus will remove focus from the dummy window
167+ topLevelWindowModel->setRootFocus(false);
168+ QVERIFY(!topLevelWindowModel->rootFocus());
169+ QVERIFY(!dummyWindow1->focused());
170+
171+ // Starting an Application will cause a pendingActivation, setting
172+ // rootFocus but preventing the original window from becoming refocused
173+ auto dummyWindow1FocusSpy = new QSignalSpy(dummyWindow1, &Window::focusedChanged);
174+
175+ // Saying that dummyWindow1 is different than dummyWindow2 will have to do
176+ // since Applications don't know their Windows and we don't mock the other
177+ // way around.
178+ applicationManager->startApplication(QString("2"), QStringList());
179+ auto dummyWindow2 = topLevelWindowModel->windowAt(0);
180+ QVERIFY((void*)dummyWindow1 != (void*)dummyWindow2);
181+
182+ QVERIFY(topLevelWindowModel->rootFocus());
183+ QVERIFY(!dummyWindow1->focused());
184+ QVERIFY(dummyWindow2->focused());
185+ QVERIFY(dummyWindow1FocusSpy->empty());
186+}
187+
128188QTEST_MAIN(tst_TopLevelWindowModel)
129189
130190#include "tst_TopLevelWindowModel.moc"