on 7fb1979 help sign in
unity8/tests/plugins/WindowManager/tst_TopLevelWindowModel.cpp
190 lines 7.1 kB history raw
1/*
2 * Copyright (C) 2017 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17#include <QtTest/QtTest>
18#include <QSignalSpy>
20// WindowManager plugin
21#include <TopLevelWindowModel.h>
22#include <Window.h>
24#include "UnityApplicationMocks.h"
26class tst_TopLevelWindowModel : public QObject
28 Q_OBJECT
30private Q_SLOTS:
31 void init(); // called right before each and every test function is executed
32 void cleanup(); // called right after each and every test function is executed
34 void singleSurfaceStartsHidden();
35 void secondSurfaceIsHidden();
36 void rootFocus();
37 void rootFocusInhibit();
39private:
40 ApplicationManager *applicationManager{nullptr};
41 SurfaceManager *surfaceManager{nullptr};
42 TopLevelWindowModel *topLevelWindowModel{nullptr};
43};
45void tst_TopLevelWindowModel::init()
47 applicationManager = new ApplicationManager;
48 surfaceManager = new SurfaceManager;
50 topLevelWindowModel = new TopLevelWindowModel;
51 topLevelWindowModel->setApplicationManager(applicationManager);
52 topLevelWindowModel->setSurfaceManager(surfaceManager);
55void tst_TopLevelWindowModel::cleanup()
57 delete topLevelWindowModel;
58 topLevelWindowModel = nullptr;
60 delete surfaceManager;
61 surfaceManager = nullptr;
63 delete applicationManager;
64 applicationManager = nullptr;
67void tst_TopLevelWindowModel::singleSurfaceStartsHidden()
69 QCOMPARE(topLevelWindowModel->rowCount(), 0);
71 auto application = static_cast<Application*>(applicationManager->startApplication(QString("hello-world"), QStringList()));
73 QCOMPARE(topLevelWindowModel->rowCount(), 1);
74 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)nullptr);
76 auto surface = new MirSurface;
77 surface->m_state = Mir::HiddenState;
78 application->m_surfaceList.addSurface(surface);
79 Q_EMIT surfaceManager->surfaceCreated(surface);
81 QCOMPARE(topLevelWindowModel->rowCount(), 1);
82 // not showing the surface as it's still hidden
83 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)nullptr);
85 surface->requestState(Mir::RestoredState);
87 QCOMPARE(topLevelWindowModel->rowCount(), 1);
88 // Now that the surface is no longer hidden, TopLevelWindowModel should expose it.
89 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)surface);
92void tst_TopLevelWindowModel::secondSurfaceIsHidden()
94 QCOMPARE(topLevelWindowModel->rowCount(), 0);
96 auto application = static_cast<Application*>(applicationManager->startApplication(QString("hello-world"), QStringList()));
98 QCOMPARE(topLevelWindowModel->rowCount(), 1);
99 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)nullptr);
101 auto firstSurface = new MirSurface;
102 application->m_surfaceList.addSurface(firstSurface);
103 Q_EMIT surfaceManager->surfaceCreated(firstSurface);
105 QCOMPARE(topLevelWindowModel->rowCount(), 1);
106 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)firstSurface);
108 auto secondSurface = new MirSurface;
109 secondSurface->m_state = Mir::HiddenState;
110 application->m_surfaceList.addSurface(secondSurface);
111 Q_EMIT surfaceManager->surfaceCreated(secondSurface);
113 // still only the first surface is exposed by TopLevelWindowModel
114 QCOMPARE(topLevelWindowModel->rowCount(), 1);
115 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)firstSurface);
117 secondSurface->requestState(Mir::RestoredState);
119 // now the second surface finally shows up
120 QCOMPARE(topLevelWindowModel->rowCount(), 2);
121 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)secondSurface);
122 QCOMPARE((void*)topLevelWindowModel->windowAt(1)->surface(), (void*)firstSurface);
124 secondSurface->requestState(Mir::HiddenState);
126 // and it's gone again
127 QCOMPARE(topLevelWindowModel->rowCount(), 1);
128 QCOMPARE((void*)topLevelWindowModel->windowAt(0)->surface(), (void*)firstSurface);
131// Ensure that rootFocus unfocuses and refocuses windows
132void tst_TopLevelWindowModel::rootFocus()
134 applicationManager->startApplication(QString("hello-world"), QStringList());
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);
144 auto rootFocusChangedSpy = new QSignalSpy(topLevelWindowModel, &TopLevelWindowModel::rootFocusChanged);
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);
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);
159// Ensure that rootFocus does not refocus a window if we focus another
160void tst_TopLevelWindowModel::rootFocusInhibit()
162 applicationManager->startApplication(QString("1"), QStringList());
164 auto dummyWindow1 = topLevelWindowModel->windowAt(0);
166 // Unsetting rootFocus will remove focus from the dummy window
167 topLevelWindowModel->setRootFocus(false);
168 QVERIFY(!topLevelWindowModel->rootFocus());
169 QVERIFY(!dummyWindow1->focused());
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);
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);
182 QVERIFY(topLevelWindowModel->rootFocus());
183 QVERIFY(!dummyWindow1->focused());
184 QVERIFY(dummyWindow2->focused());
185 QVERIFY(dummyWindow1FocusSpy->empty());
188QTEST_MAIN(tst_TopLevelWindowModel)
190#include "tst_TopLevelWindowModel.moc"