on 700e2bd help sign in
unity8/tests/plugins/WindowManager/tst_TopLevelWindowModel.cpp
193 lines 7.2 kB history raw
1/*
2 * Copyright (C) 2017 Canonical, Ltd.
3 * Copyright (C) 2019 UBports Foundation
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
18// There is a companion set of QMLTests for TLWM in tst_QMLTopLevelWindowModel.qml.
20#include <QtTest/QtTest>
21#include <QSignalSpy>
23// WindowManager plugin
24#include <TopLevelWindowModel.h>
25#include <Window.h>
27#include "UnityApplicationMocks.h"
29class tst_TopLevelWindowModel : public QObject
31 Q_OBJECT
33private Q_SLOTS:
34 void init(); // called right before each and every test function is executed
35 void cleanup(); // called right after each and every test function is executed
37 void singleSurfaceStartsHidden();
38 void secondSurfaceIsHidden();
39 void rootFocus();
40 void rootFocusInhibit();
42private:
43 ApplicationManager *applicationManager{nullptr};
44 SurfaceManager *surfaceManager{nullptr};
45 TopLevelWindowModel *topLevelWindowModel{nullptr};
46};
48void tst_TopLevelWindowModel::init()
50 applicationManager = new ApplicationManager;
51 surfaceManager = new SurfaceManager;
53 topLevelWindowModel = new TopLevelWindowModel;
54 topLevelWindowModel->setApplicationManager(applicationManager);
55 topLevelWindowModel->setSurfaceManager(surfaceManager);
58void tst_TopLevelWindowModel::cleanup()
60 delete topLevelWindowModel;
61 topLevelWindowModel = nullptr;
63 delete surfaceManager;
64 surfaceManager = nullptr;
66 delete applicationManager;
67 applicationManager = nullptr;
70void tst_TopLevelWindowModel::singleSurfaceStartsHidden()
72 QCOMPARE(topLevelWindowModel->rowCount(), 0);
74 auto application = static_cast<Application*>(applicationManager->startApplication(QString("hello-world"), QStringList()));
76 QCOMPARE(topLevelWindowModel->rowCount(), 1);
77 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)nullptr);
79 auto surface = new MirSurface;
80 surface->m_state = Mir::HiddenState;
81 application->m_surfaceList.addSurface(surface);
82 Q_EMIT surfaceManager->surfaceCreated(surface);
84 QCOMPARE(topLevelWindowModel->rowCount(), 1);
85 // not showing the surface as it's still hidden
86 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)nullptr);
88 surface->requestState(Mir::RestoredState);
90 QCOMPARE(topLevelWindowModel->rowCount(), 1);
91 // Now that the surface is no longer hidden, TopLevelWindowModel should expose it.
92 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)surface);
95void tst_TopLevelWindowModel::secondSurfaceIsHidden()
97 QCOMPARE(topLevelWindowModel->rowCount(), 0);
99 auto application = static_cast<Application*>(applicationManager->startApplication(QString("hello-world"), QStringList()));
101 QCOMPARE(topLevelWindowModel->rowCount(), 1);
102 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)nullptr);
104 auto firstSurface = new MirSurface;
105 application->m_surfaceList.addSurface(firstSurface);
106 Q_EMIT surfaceManager->surfaceCreated(firstSurface);
108 QCOMPARE(topLevelWindowModel->rowCount(), 1);
109 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)firstSurface);
111 auto secondSurface = new MirSurface;
112 secondSurface->m_state = Mir::HiddenState;
113 application->m_surfaceList.addSurface(secondSurface);
114 Q_EMIT surfaceManager->surfaceCreated(secondSurface);
116 // still only the first surface is exposed by TopLevelWindowModel
117 QCOMPARE(topLevelWindowModel->rowCount(), 1);
118 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)firstSurface);
120 secondSurface->requestState(Mir::RestoredState);
122 // now the second surface finally shows up
123 QCOMPARE(topLevelWindowModel->rowCount(), 2);
124 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)secondSurface);
125 QCOMPARE((void*)topLevelWindowModel->windowAt(1)->surface(), (void*)firstSurface);
127 secondSurface->requestState(Mir::HiddenState);
129 // and it's gone again
130 QCOMPARE(topLevelWindowModel->rowCount(), 1);
131 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)firstSurface);
134// Ensure that rootFocus unfocuses and refocuses windows
135void tst_TopLevelWindowModel::rootFocus()
137 applicationManager->startApplication(QString("hello-world"), QStringList());
139 // We need to keep the window's surface null, unlike the other tests,
140 // because then the TLWM assumes that the window is unknown to MirAL and
141 // handles focus changes itself. If MirAL and QtMir are behaving properly,
142 // they mirror this behavior for windows with surfaces.
143 QCOMPARE(topLevelWindowModel->rowCount(), 1);
144 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)nullptr);
145 auto dummyWindow = topLevelWindowModel->windowAt(0);
147 auto rootFocusChangedSpy = new QSignalSpy(topLevelWindowModel, &TopLevelWindowModel::rootFocusChanged);
149 // Unsetting rootFocus will remove focus from the dummy window
150 topLevelWindowModel->setRootFocus(false);
151 QVERIFY(!topLevelWindowModel->rootFocus());
152 QVERIFY(!dummyWindow->focused());
153 QCOMPARE(rootFocusChangedSpy->count(), 1);
155 // Setting rootFocus will add focus back to the dummy window
156 topLevelWindowModel->setRootFocus(true);
157 QVERIFY(topLevelWindowModel->rootFocus());
158 QCOMPARE((void*)topLevelWindowModel->focusedWindow(), (void*)dummyWindow);
159 QCOMPARE(rootFocusChangedSpy->count(), 2);
162// Ensure that rootFocus does not refocus a window if we focus another
163void tst_TopLevelWindowModel::rootFocusInhibit()
165 applicationManager->startApplication(QString("1"), QStringList());
167 auto dummyWindow1 = topLevelWindowModel->windowAt(0);
169 // Unsetting rootFocus will remove focus from the dummy window
170 topLevelWindowModel->setRootFocus(false);
171 QVERIFY(!topLevelWindowModel->rootFocus());
172 QVERIFY(!dummyWindow1->focused());
174 // Starting an Application will cause a pendingActivation, setting
175 // rootFocus but preventing the original window from becoming refocused
176 auto dummyWindow1FocusSpy = new QSignalSpy(dummyWindow1, &Window::focusedChanged);
178 // Saying that dummyWindow1 is different than dummyWindow2 will have to do
179 // since Applications don't know their Windows and we don't mock the other
180 // way around.
181 applicationManager->startApplication(QString("2"), QStringList());
182 auto dummyWindow2 = topLevelWindowModel->windowAt(0);
183 QVERIFY((void*)dummyWindow1 != (void*)dummyWindow2);
185 QVERIFY(topLevelWindowModel->rootFocus());
186 QVERIFY(!dummyWindow1->focused());
187 QVERIFY(dummyWindow2->focused());
188 QVERIFY(dummyWindow1FocusSpy->empty());
191QTEST_MAIN(tst_TopLevelWindowModel)
193#include "tst_TopLevelWindowModel.moc"