Merge lp:~mzanetti/unity8/miral-qt54 into lp:unity8
- miral-qt54
- Merge into trunk
Proposed by
Michael Zanetti
Status: | Work in progress |
---|---|
Proposed branch: | lp:~mzanetti/unity8/miral-qt54 |
Merge into: | lp:unity8 |
Diff against target: |
4245 lines (+1588/-1275) 40 files modified
CMakeLists.txt (+1/-1) debian/control (+3/-3) debian/unity8-private.install (+0/-1) plugins/CMakeLists.txt (+0/-1) plugins/WindowManager/CMakeLists.txt (+0/-14) plugins/WindowManager/TopLevelSurfaceList.cpp (+0/-481) plugins/WindowManager/TopLevelSurfaceList.h (+0/-223) plugins/WindowManager/WindowManagerPlugin.cpp (+0/-28) plugins/WindowManager/WindowManagerPlugin.h (+0/-32) plugins/WindowManager/qmldir (+0/-2) qml/Components/InputMethod.qml (+5/-4) qml/Components/KeymapSwitcher.qml (+4/-1) qml/Shell.qml (+7/-6) qml/Stage/DecoratedWindow.qml (+8/-2) qml/Stage/FakeMaximizeDelegate.qml (+7/-7) qml/Stage/Stage.qml (+130/-117) qml/Stage/StagedFullscreenPolicy.qml (+4/-4) qml/Stage/TopLevelSurfaceRepeater.qml (+0/-67) qml/Stage/WindowedFullscreenPolicy.qml (+1/-1) tests/mocks/Unity/Application/ApplicationInfo.cpp (+18/-4) tests/mocks/Unity/Application/ApplicationManager.cpp (+78/-41) tests/mocks/Unity/Application/ApplicationManager.h (+28/-1) tests/mocks/Unity/Application/CMakeLists.txt (+4/-1) tests/mocks/Unity/Application/MirSurface.cpp (+70/-93) tests/mocks/Unity/Application/MirSurface.h (+24/-23) tests/mocks/Unity/Application/MirSurfaceItem.cpp (+4/-4) tests/mocks/Unity/Application/MirSurfaceItem.h (+1/-2) tests/mocks/Unity/Application/MirSurfaceListModel.cpp (+20/-2) tests/mocks/Unity/Application/MirSurfaceListModel.h (+2/-1) tests/mocks/Unity/Application/SurfaceManager.cpp (+9/-8) tests/mocks/Unity/Application/SurfaceManager.h (+4/-3) tests/mocks/Unity/Application/TopLevelWindowModel.cpp (+610/-0) tests/mocks/Unity/Application/TopLevelWindowModel.h (+146/-0) tests/mocks/Unity/Application/Window.cpp (+229/-0) tests/mocks/Unity/Application/Window.h (+69/-0) tests/mocks/Unity/Application/plugin.cpp (+7/-11) tests/qmltests/Stage/tst_DesktopStage.qml (+41/-36) tests/qmltests/Stage/tst_PhoneStage.qml (+5/-7) tests/qmltests/Stage/tst_TabletStage.qml (+3/-5) tests/qmltests/tst_Shell.qml (+46/-38) |
To merge this branch: | bzr merge lp:~mzanetti/unity8/miral-qt54 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity Team | Pending | ||
Review via email: mp+310439@code.launchpad.net |
Commit message
just so I can test this on something with a touchscreen
Description of the change
To post a comment you must log in.
lp:~mzanetti/unity8/miral-qt54
updated
- 2677. By Michael Zanetti
-
fix typo
Unmerged revisions
- 2677. By Michael Zanetti
-
fix typo
- 2676. By Michael Zanetti
-
make it build with Qt 5.4
- 2675. By Daniel d'Andrada
-
Let the model deal with some window management decisions
eg: which window to focus, whether to change surface state
unit8 requests and reacts to changes in the model instead of applying them
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2016-10-24 11:34:08 +0000 |
3 | +++ CMakeLists.txt 2016-11-09 15:21:35 +0000 |
4 | @@ -57,7 +57,7 @@ |
5 | find_package(Qt5Concurrent 5.4 REQUIRED) |
6 | find_package(Qt5Sql 5.4 REQUIRED) |
7 | |
8 | -pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=22) |
9 | +pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=23) |
10 | pkg_check_modules(GEONAMES REQUIRED geonames>=0.2) |
11 | pkg_check_modules(GIO REQUIRED gio-2.0>=2.32) |
12 | pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32) |
13 | |
14 | === modified file 'debian/control' |
15 | --- debian/control 2016-10-27 12:25:58 +0000 |
16 | +++ debian/control 2016-11-09 15:21:35 +0000 |
17 | @@ -38,7 +38,7 @@ |
18 | libubuntugestures5-private-dev (>= 1.3.2030), |
19 | libudev-dev, |
20 | libudm-common-dev, |
21 | - libunity-api-dev (>= 7.119), |
22 | + libunity-api-dev (>= 7.120), |
23 | libusermetricsoutput1-dev, |
24 | # Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop |
25 | libx11-dev[!arm64 !armhf], |
26 | @@ -158,7 +158,7 @@ |
27 | qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl, |
28 | ubuntu-thumbnailer-impl-0, |
29 | ubuntu-wallpapers, |
30 | - unity-application-impl-22, |
31 | + unity-application-impl-23, |
32 | unity-notifications-impl-3, |
33 | unity-plugin-scopes | unity-scopes-impl, |
34 | unity-scopes-impl-12, |
35 | @@ -204,7 +204,7 @@ |
36 | Depends: ${misc:Depends}, |
37 | ${shlibs:Depends}, |
38 | Provides: unity-application-impl, |
39 | - unity-application-impl-22, |
40 | + unity-application-impl-23, |
41 | Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1) |
42 | Description: Fake environment for running Unity 8 shell |
43 | Provides fake implementations of some QML modules used by Unity 8 shell |
44 | |
45 | === modified file 'debian/unity8-private.install' |
46 | --- debian/unity8-private.install 2016-08-30 14:06:47 +0000 |
47 | +++ debian/unity8-private.install 2016-11-09 15:21:35 +0000 |
48 | @@ -14,7 +14,6 @@ |
49 | usr/lib/*/unity8/qml/Unity |
50 | usr/lib/*/unity8/qml/UInput |
51 | usr/lib/*/unity8/qml/Utils |
52 | -usr/lib/*/unity8/qml/WindowManager |
53 | usr/lib/*/unity8/qml/Wizard |
54 | usr/share/accountsservice/interfaces |
55 | usr/share/dbus-1/interfaces |
56 | |
57 | === modified file 'plugins/CMakeLists.txt' |
58 | --- plugins/CMakeLists.txt 2016-08-30 14:06:47 +0000 |
59 | +++ plugins/CMakeLists.txt 2016-11-09 15:21:35 +0000 |
60 | @@ -26,5 +26,4 @@ |
61 | add_subdirectory(UInput) |
62 | add_subdirectory(Unity) |
63 | add_subdirectory(Utils) |
64 | -add_subdirectory(WindowManager) |
65 | add_subdirectory(Wizard) |
66 | |
67 | === removed directory 'plugins/WindowManager' |
68 | === removed file 'plugins/WindowManager/CMakeLists.txt' |
69 | --- plugins/WindowManager/CMakeLists.txt 2016-06-20 09:43:38 +0000 |
70 | +++ plugins/WindowManager/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
71 | @@ -1,14 +0,0 @@ |
72 | -set(WINDOWMANAGER_SRC |
73 | - TopLevelSurfaceList.cpp |
74 | - WindowManagerPlugin.cpp |
75 | - ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h |
76 | - ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h |
77 | - ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h |
78 | - ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceListInterface.h |
79 | - ) |
80 | - |
81 | -add_library(windowmanager-qml SHARED ${WINDOWMANAGER_SRC}) |
82 | - |
83 | -qt5_use_modules(windowmanager-qml Qml Quick Gui) |
84 | - |
85 | -add_unity8_plugin(WindowManager 0.1 WindowManager TARGETS windowmanager-qml) |
86 | |
87 | === removed file 'plugins/WindowManager/TopLevelSurfaceList.cpp' |
88 | --- plugins/WindowManager/TopLevelSurfaceList.cpp 2016-09-14 15:02:01 +0000 |
89 | +++ plugins/WindowManager/TopLevelSurfaceList.cpp 1970-01-01 00:00:00 +0000 |
90 | @@ -1,481 +0,0 @@ |
91 | -/* |
92 | - * Copyright (C) 2016 Canonical, Ltd. |
93 | - * |
94 | - * This program is free software; you can redistribute it and/or modify |
95 | - * it under the terms of the GNU General Public License as published by |
96 | - * the Free Software Foundation; version 3. |
97 | - * |
98 | - * This program is distributed in the hope that it will be useful, |
99 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
100 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
101 | - * GNU General Public License for more details. |
102 | - * |
103 | - * You should have received a copy of the GNU General Public License |
104 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
105 | - */ |
106 | - |
107 | -#include "TopLevelSurfaceList.h" |
108 | - |
109 | -// unity-api |
110 | -#include <unity/shell/application/ApplicationInfoInterface.h> |
111 | -#include <unity/shell/application/MirSurfaceInterface.h> |
112 | -#include <unity/shell/application/MirSurfaceListInterface.h> |
113 | - |
114 | -#include <QMetaObject> |
115 | - |
116 | -Q_LOGGING_CATEGORY(UNITY_TOPSURFACELIST, "unity.topsurfacelist", QtDebugMsg) |
117 | - |
118 | -#define DEBUG_MSG qCDebug(UNITY_TOPSURFACELIST).nospace().noquote() << __func__ |
119 | - |
120 | -using namespace unity::shell::application; |
121 | - |
122 | -TopLevelSurfaceList::TopLevelSurfaceList(QObject *parent) : |
123 | - QAbstractListModel(parent) |
124 | -{ |
125 | - DEBUG_MSG << "()"; |
126 | -} |
127 | - |
128 | -TopLevelSurfaceList::~TopLevelSurfaceList() |
129 | -{ |
130 | - DEBUG_MSG << "()"; |
131 | -} |
132 | - |
133 | -int TopLevelSurfaceList::rowCount(const QModelIndex &parent) const |
134 | -{ |
135 | - return !parent.isValid() ? m_surfaceList.size() : 0; |
136 | -} |
137 | - |
138 | -QVariant TopLevelSurfaceList::data(const QModelIndex& index, int role) const |
139 | -{ |
140 | - if (index.row() < 0 || index.row() >= m_surfaceList.size()) |
141 | - return QVariant(); |
142 | - |
143 | - if (role == SurfaceRole) { |
144 | - MirSurfaceInterface *surface = m_surfaceList.at(index.row()).surface; |
145 | - return QVariant::fromValue(surface); |
146 | - } else if (role == ApplicationRole) { |
147 | - return QVariant::fromValue(m_surfaceList.at(index.row()).application); |
148 | - } else if (role == IdRole) { |
149 | - return QVariant::fromValue(m_surfaceList.at(index.row()).id); |
150 | - } else { |
151 | - return QVariant(); |
152 | - } |
153 | -} |
154 | - |
155 | -void TopLevelSurfaceList::raise(MirSurfaceInterface *surface) |
156 | -{ |
157 | - if (!surface) |
158 | - return; |
159 | - |
160 | - DEBUG_MSG << "(MirSurface[" << (void*)surface << "])"; |
161 | - |
162 | - int i = indexOf(surface); |
163 | - if (i != -1) { |
164 | - raiseId(m_surfaceList.at(i).id); |
165 | - } |
166 | -} |
167 | - |
168 | -void TopLevelSurfaceList::appendPlaceholder(ApplicationInfoInterface *application) |
169 | -{ |
170 | - DEBUG_MSG << "(" << application->appId() << ")"; |
171 | - |
172 | - appendSurfaceHelper(nullptr, application); |
173 | -} |
174 | - |
175 | -void TopLevelSurfaceList::appendSurface(MirSurfaceInterface *surface, ApplicationInfoInterface *application) |
176 | -{ |
177 | - Q_ASSERT(surface != nullptr); |
178 | - |
179 | - bool filledPlaceholder = false; |
180 | - for (int i = 0; i < m_surfaceList.count() && !filledPlaceholder; ++i) { |
181 | - ModelEntry &entry = m_surfaceList[i]; |
182 | - if (entry.application == application && entry.surface == nullptr) { |
183 | - entry.surface = surface; |
184 | - connectSurface(surface); |
185 | - DEBUG_MSG << " appId=" << application->appId() << " surface=" << surface |
186 | - << ", filling out placeholder. after: " << toString(); |
187 | - Q_EMIT dataChanged(index(i) /* topLeft */, index(i) /* bottomRight */, QVector<int>() << SurfaceRole); |
188 | - filledPlaceholder = true; |
189 | - } |
190 | - } |
191 | - |
192 | - if (!filledPlaceholder) { |
193 | - DEBUG_MSG << " appId=" << application->appId() << " surface=" << surface << ", adding new row"; |
194 | - appendSurfaceHelper(surface, application); |
195 | - } |
196 | -} |
197 | - |
198 | -void TopLevelSurfaceList::appendSurfaceHelper(MirSurfaceInterface *surface, ApplicationInfoInterface *application) |
199 | -{ |
200 | - if (m_modelState == IdleState) { |
201 | - m_modelState = InsertingState; |
202 | - beginInsertRows(QModelIndex(), m_surfaceList.size() /*first*/, m_surfaceList.size() /*last*/); |
203 | - } else { |
204 | - Q_ASSERT(m_modelState == ResettingState); |
205 | - // No point in signaling anything if we're resetting the whole model |
206 | - } |
207 | - |
208 | - int id = generateId(); |
209 | - m_surfaceList.append(ModelEntry(surface, application, id)); |
210 | - if (surface) { |
211 | - connectSurface(surface); |
212 | - } |
213 | - |
214 | - if (m_modelState == InsertingState) { |
215 | - endInsertRows(); |
216 | - Q_EMIT countChanged(); |
217 | - Q_EMIT listChanged(); |
218 | - m_modelState = IdleState; |
219 | - } |
220 | - |
221 | - DEBUG_MSG << " after " << toString(); |
222 | -} |
223 | - |
224 | -void TopLevelSurfaceList::connectSurface(MirSurfaceInterface *surface) |
225 | -{ |
226 | - connect(surface, &MirSurfaceInterface::liveChanged, this, [this, surface](bool live){ |
227 | - if (!live) { |
228 | - onSurfaceDied(surface); |
229 | - } |
230 | - }); |
231 | - connect(surface, &QObject::destroyed, this, [this, surface](){ this->onSurfaceDestroyed(surface); }); |
232 | -} |
233 | - |
234 | -void TopLevelSurfaceList::onSurfaceDied(MirSurfaceInterface *surface) |
235 | -{ |
236 | - int i = indexOf(surface); |
237 | - if (i == -1) { |
238 | - return; |
239 | - } |
240 | - |
241 | - auto application = m_surfaceList[i].application; |
242 | - |
243 | - // can't be starting if it already has a surface |
244 | - Q_ASSERT(application->state() != ApplicationInfoInterface::Starting); |
245 | - |
246 | - if (application->state() == ApplicationInfoInterface::Running) { |
247 | - m_surfaceList[i].removeOnceSurfaceDestroyed = true; |
248 | - } else { |
249 | - // assume it got killed by the out-of-memory daemon. |
250 | - // |
251 | - // So leave entry in the model and only remove its surface, so shell can display a screenshot |
252 | - // in its place. |
253 | - m_surfaceList[i].removeOnceSurfaceDestroyed = false; |
254 | - } |
255 | -} |
256 | - |
257 | -void TopLevelSurfaceList::onSurfaceDestroyed(MirSurfaceInterface *surface) |
258 | -{ |
259 | - int i = indexOf(surface); |
260 | - if (i == -1) { |
261 | - return; |
262 | - } |
263 | - |
264 | - if (m_surfaceList[i].removeOnceSurfaceDestroyed) { |
265 | - removeAt(i); |
266 | - } else { |
267 | - m_surfaceList[i].surface = nullptr; |
268 | - Q_EMIT dataChanged(index(i) /* topLeft */, index(i) /* bottomRight */, QVector<int>() << SurfaceRole); |
269 | - DEBUG_MSG << " Removed surface from entry. After: " << toString(); |
270 | - } |
271 | -} |
272 | - |
273 | -void TopLevelSurfaceList::removeAt(int index) |
274 | -{ |
275 | - if (m_modelState == IdleState) { |
276 | - beginRemoveRows(QModelIndex(), index, index); |
277 | - m_modelState = RemovingState; |
278 | - } else { |
279 | - Q_ASSERT(m_modelState == ResettingState); |
280 | - // No point in signaling anything if we're resetting the whole model |
281 | - } |
282 | - |
283 | - m_surfaceList.removeAt(index); |
284 | - |
285 | - if (m_modelState == RemovingState) { |
286 | - endRemoveRows(); |
287 | - Q_EMIT countChanged(); |
288 | - Q_EMIT listChanged(); |
289 | - m_modelState = IdleState; |
290 | - } |
291 | - |
292 | - DEBUG_MSG << " after " << toString(); |
293 | -} |
294 | - |
295 | -int TopLevelSurfaceList::indexOf(MirSurfaceInterface *surface) |
296 | -{ |
297 | - for (int i = 0; i < m_surfaceList.count(); ++i) { |
298 | - if (m_surfaceList.at(i).surface == surface) { |
299 | - return i; |
300 | - } |
301 | - } |
302 | - return -1; |
303 | -} |
304 | - |
305 | -void TopLevelSurfaceList::move(int from, int to) |
306 | -{ |
307 | - if (from == to) return; |
308 | - DEBUG_MSG << " from=" << from << " to=" << to; |
309 | - |
310 | - if (from >= 0 && from < m_surfaceList.size() && to >= 0 && to < m_surfaceList.size()) { |
311 | - QModelIndex parent; |
312 | - /* When moving an item down, the destination index needs to be incremented |
313 | - by one, as explained in the documentation: |
314 | - http://qt-project.org/doc/qt-5.0/qtcore/qabstractitemmodel.html#beginMoveRows */ |
315 | - |
316 | - Q_ASSERT(m_modelState == IdleState); |
317 | - m_modelState = MovingState; |
318 | - |
319 | - beginMoveRows(parent, from, from, parent, to + (to > from ? 1 : 0)); |
320 | - m_surfaceList.move(from, to); |
321 | - endMoveRows(); |
322 | - Q_EMIT listChanged(); |
323 | - |
324 | - m_modelState = IdleState; |
325 | - |
326 | - DEBUG_MSG << " after " << toString(); |
327 | - } |
328 | -} |
329 | - |
330 | -MirSurfaceInterface *TopLevelSurfaceList::surfaceAt(int index) const |
331 | -{ |
332 | - if (index >=0 && index < m_surfaceList.count()) { |
333 | - return m_surfaceList[index].surface; |
334 | - } else { |
335 | - return nullptr; |
336 | - } |
337 | -} |
338 | - |
339 | -ApplicationInfoInterface *TopLevelSurfaceList::applicationAt(int index) const |
340 | -{ |
341 | - if (index >=0 && index < m_surfaceList.count()) { |
342 | - return m_surfaceList[index].application; |
343 | - } else { |
344 | - return nullptr; |
345 | - } |
346 | -} |
347 | - |
348 | -int TopLevelSurfaceList::idAt(int index) const |
349 | -{ |
350 | - if (index >=0 && index < m_surfaceList.count()) { |
351 | - return m_surfaceList[index].id; |
352 | - } else { |
353 | - return 0; |
354 | - } |
355 | -} |
356 | - |
357 | -int TopLevelSurfaceList::indexForId(int id) const |
358 | -{ |
359 | - for (int i = 0; i < m_surfaceList.count(); ++i) { |
360 | - if (m_surfaceList[i].id == id) { |
361 | - return i; |
362 | - } |
363 | - } |
364 | - return -1; |
365 | -} |
366 | - |
367 | -void TopLevelSurfaceList::doRaiseId(int id) |
368 | -{ |
369 | - int fromIndex = indexForId(id); |
370 | - if (fromIndex != -1) { |
371 | - move(fromIndex, 0 /* toIndex */); |
372 | - } |
373 | -} |
374 | - |
375 | -void TopLevelSurfaceList::raiseId(int id) |
376 | -{ |
377 | - if (m_modelState == IdleState) { |
378 | - DEBUG_MSG << "(id=" << id << ") - do it now."; |
379 | - doRaiseId(id); |
380 | - } else { |
381 | - DEBUG_MSG << "(id=" << id << ") - Model busy (modelState=" << m_modelState << "). Try again in the next event loop."; |
382 | - // The model has just signalled some change. If we have a Repeater responding to this update, it will get nuts |
383 | - // if we perform yet another model change straight away. |
384 | - // |
385 | - // A bad sympton of this problem is a Repeater.itemAt(index) call returning null event though Repeater.count says |
386 | - // the index is definitely within bounds. |
387 | - QMetaObject::invokeMethod(this, "raiseId", Qt::QueuedConnection, Q_ARG(int, id)); |
388 | - } |
389 | -} |
390 | - |
391 | -int TopLevelSurfaceList::generateId() |
392 | -{ |
393 | - int id = m_nextId; |
394 | - m_nextId = nextFreeId(m_nextId + 1); |
395 | - Q_EMIT nextIdChanged(); |
396 | - return id; |
397 | -} |
398 | - |
399 | -int TopLevelSurfaceList::nextFreeId(int candidateId) |
400 | -{ |
401 | - if (candidateId > m_maxId) { |
402 | - return nextFreeId(1); |
403 | - } else { |
404 | - if (indexForId(candidateId) == -1) { |
405 | - // it's indeed free |
406 | - return candidateId; |
407 | - } else { |
408 | - return nextFreeId(candidateId + 1); |
409 | - } |
410 | - } |
411 | -} |
412 | - |
413 | -QString TopLevelSurfaceList::toString() |
414 | -{ |
415 | - QString str; |
416 | - for (int i = 0; i < m_surfaceList.count(); ++i) { |
417 | - auto item = m_surfaceList.at(i); |
418 | - |
419 | - QString itemStr = QString("(index=%1,appId=%2,surface=0x%3,id=%4)") |
420 | - .arg(i) |
421 | - .arg(item.application->appId()) |
422 | - .arg((qintptr)item.surface, 0, 16) |
423 | - .arg(item.id); |
424 | - |
425 | - if (i > 0) { |
426 | - str.append(","); |
427 | - } |
428 | - str.append(itemStr); |
429 | - } |
430 | - return str; |
431 | -} |
432 | - |
433 | -void TopLevelSurfaceList::addApplication(ApplicationInfoInterface *application) |
434 | -{ |
435 | - DEBUG_MSG << "(" << application->appId() << ")"; |
436 | - Q_ASSERT(!m_applications.contains(application)); |
437 | - m_applications.append(application); |
438 | - |
439 | - MirSurfaceListInterface *surfaceList = application->surfaceList(); |
440 | - |
441 | - if (application->state() != ApplicationInfoInterface::Stopped) { |
442 | - if (surfaceList->count() == 0) { |
443 | - appendPlaceholder(application); |
444 | - } else { |
445 | - for (int i = 0; i < surfaceList->count(); ++i) { |
446 | - appendSurface(surfaceList->get(i), application); |
447 | - } |
448 | - } |
449 | - } |
450 | - |
451 | - connect(surfaceList, &QAbstractItemModel::rowsInserted, this, |
452 | - [this, application, surfaceList](const QModelIndex & /*parent*/, int first, int last) |
453 | - { |
454 | - for (int i = last; i >= first; --i) { |
455 | - this->appendSurface(surfaceList->get(i), application); |
456 | - } |
457 | - }); |
458 | -} |
459 | - |
460 | -void TopLevelSurfaceList::removeApplication(ApplicationInfoInterface *application) |
461 | -{ |
462 | - DEBUG_MSG << "(" << application->appId() << ")"; |
463 | - Q_ASSERT(m_applications.contains(application)); |
464 | - |
465 | - MirSurfaceListInterface *surfaceList = application->surfaceList(); |
466 | - |
467 | - disconnect(surfaceList, 0, this, 0); |
468 | - |
469 | - Q_ASSERT(m_modelState == IdleState); |
470 | - m_modelState = RemovingState; |
471 | - |
472 | - int i = 0; |
473 | - while (i < m_surfaceList.count()) { |
474 | - if (m_surfaceList.at(i).application == application) { |
475 | - beginRemoveRows(QModelIndex(), i, i); |
476 | - m_surfaceList.removeAt(i); |
477 | - endRemoveRows(); |
478 | - Q_EMIT countChanged(); |
479 | - Q_EMIT listChanged(); |
480 | - } else { |
481 | - ++i; |
482 | - } |
483 | - } |
484 | - |
485 | - m_modelState = IdleState; |
486 | - |
487 | - DEBUG_MSG << " after " << toString(); |
488 | - |
489 | - m_applications.removeAll(application); |
490 | -} |
491 | - |
492 | -QAbstractListModel *TopLevelSurfaceList::applicationsModel() const |
493 | -{ |
494 | - return m_applicationsModel; |
495 | -} |
496 | - |
497 | -void TopLevelSurfaceList::setApplicationsModel(QAbstractListModel* value) |
498 | -{ |
499 | - if (m_applicationsModel == value) { |
500 | - return; |
501 | - } |
502 | - |
503 | - DEBUG_MSG << "(" << value << ")"; |
504 | - |
505 | - Q_ASSERT(m_modelState == IdleState); |
506 | - m_modelState = ResettingState; |
507 | - |
508 | - beginResetModel(); |
509 | - |
510 | - if (m_applicationsModel) { |
511 | - m_surfaceList.clear(); |
512 | - m_applications.clear(); |
513 | - disconnect(m_applicationsModel, 0, this, 0); |
514 | - } |
515 | - |
516 | - m_applicationsModel = value; |
517 | - |
518 | - if (m_applicationsModel) { |
519 | - findApplicationRole(); |
520 | - |
521 | - connect(m_applicationsModel, &QAbstractItemModel::rowsInserted, |
522 | - this, [this](const QModelIndex &/*parent*/, int first, int last) { |
523 | - for (int i = first; i <= last; ++i) { |
524 | - auto application = getApplicationFromModelAt(i); |
525 | - addApplication(application); |
526 | - } |
527 | - }); |
528 | - |
529 | - connect(m_applicationsModel, &QAbstractItemModel::rowsAboutToBeRemoved, |
530 | - this, [this](const QModelIndex &/*parent*/, int first, int last) { |
531 | - for (int i = first; i <= last; ++i) { |
532 | - auto application = getApplicationFromModelAt(i); |
533 | - removeApplication(application); |
534 | - } |
535 | - }); |
536 | - |
537 | - for (int i = 0; i < m_applicationsModel->rowCount(); ++i) { |
538 | - auto application = getApplicationFromModelAt(i); |
539 | - addApplication(application); |
540 | - } |
541 | - } |
542 | - |
543 | - endResetModel(); |
544 | - m_modelState = IdleState; |
545 | -} |
546 | - |
547 | -ApplicationInfoInterface *TopLevelSurfaceList::getApplicationFromModelAt(int index) |
548 | -{ |
549 | - QModelIndex modelIndex = m_applicationsModel->index(index); |
550 | - |
551 | - QVariant variant = m_applicationsModel->data(modelIndex, m_applicationRole); |
552 | - |
553 | - // variant.value<ApplicationInfoInterface*>() returns null for some reason. |
554 | - return static_cast<ApplicationInfoInterface*>(variant.value<QObject*>()); |
555 | -} |
556 | - |
557 | -void TopLevelSurfaceList::findApplicationRole() |
558 | -{ |
559 | - QHash<int, QByteArray> namesHash = m_applicationsModel->roleNames(); |
560 | - |
561 | - m_applicationRole = -1; |
562 | - for (auto i = namesHash.begin(); i != namesHash.end() && m_applicationRole == -1; ++i) { |
563 | - if (i.value() == "application") { |
564 | - m_applicationRole = i.key(); |
565 | - } |
566 | - } |
567 | - |
568 | - if (m_applicationRole == -1) { |
569 | - qFatal("TopLevelSurfaceList: applicationsModel must have a \"application\" role."); |
570 | - } |
571 | -} |
572 | |
573 | === removed file 'plugins/WindowManager/TopLevelSurfaceList.h' |
574 | --- plugins/WindowManager/TopLevelSurfaceList.h 2016-04-04 13:39:44 +0000 |
575 | +++ plugins/WindowManager/TopLevelSurfaceList.h 1970-01-01 00:00:00 +0000 |
576 | @@ -1,223 +0,0 @@ |
577 | -/* |
578 | - * Copyright (C) 2016 Canonical, Ltd. |
579 | - * |
580 | - * This program is free software; you can redistribute it and/or modify |
581 | - * it under the terms of the GNU General Public License as published by |
582 | - * the Free Software Foundation; version 3. |
583 | - * |
584 | - * This program is distributed in the hope that it will be useful, |
585 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
586 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
587 | - * GNU General Public License for more details. |
588 | - * |
589 | - * You should have received a copy of the GNU General Public License |
590 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
591 | - */ |
592 | - |
593 | -#ifndef TOPLEVELSURFACELIST_H |
594 | -#define TOPLEVELSURFACELIST_H |
595 | - |
596 | -#include <QAbstractListModel> |
597 | -#include <QList> |
598 | -#include <QLoggingCategory> |
599 | - |
600 | -Q_DECLARE_LOGGING_CATEGORY(UNITY_TOPSURFACELIST) |
601 | - |
602 | -namespace unity { |
603 | - namespace shell { |
604 | - namespace application { |
605 | - class ApplicationInfoInterface; |
606 | - class MirSurfaceInterface; |
607 | - } |
608 | - } |
609 | -} |
610 | - |
611 | -/** |
612 | - * @brief A model of top-level surfaces |
613 | - * |
614 | - * It's an abstraction of top-level application windows. |
615 | - * |
616 | - * When an entry first appears, it normaly doesn't have a surface yet, meaning that the application is |
617 | - * still starting up. A shell should then display a splash screen or saved screenshot of the application |
618 | - * until its surface comes up. |
619 | - * |
620 | - * As applications can have multiple surfaces and you can also have entries without surfaces at all, |
621 | - * the only way to unambiguously refer to an entry in this model is through its id. |
622 | - */ |
623 | -class TopLevelSurfaceList : public QAbstractListModel |
624 | -{ |
625 | - |
626 | - Q_OBJECT |
627 | - |
628 | - /** |
629 | - * @brief A list model of applications. |
630 | - * |
631 | - * It's expected to have a role called "application" which returns a ApplicationInfoInterface |
632 | - */ |
633 | - Q_PROPERTY(QAbstractListModel* applicationsModel READ applicationsModel |
634 | - WRITE setApplicationsModel |
635 | - NOTIFY applicationsModelChanged) |
636 | - |
637 | - /** |
638 | - * @brief Number of top-level surfaces in this model |
639 | - * |
640 | - * This is the same as rowCount, added in order to keep compatibility with QML ListModels. |
641 | - */ |
642 | - Q_PROPERTY(int count READ rowCount NOTIFY countChanged) |
643 | - |
644 | - /** |
645 | - The id to be used on the next entry created |
646 | - Useful for tests |
647 | - */ |
648 | - Q_PROPERTY(int nextId READ nextId NOTIFY nextIdChanged) |
649 | -public: |
650 | - |
651 | - /** |
652 | - * @brief The Roles supported by the model |
653 | - * |
654 | - * SurfaceRole - A MirSurfaceInterface. It will be null if the application is still starting up |
655 | - * ApplicationRole - An ApplicationInfoInterface |
656 | - * IdRole - A unique identifier for this entry. Useful to unambiguosly track elements as they move around in the list |
657 | - */ |
658 | - enum Roles { |
659 | - SurfaceRole = Qt::UserRole, |
660 | - ApplicationRole = Qt::UserRole + 1, |
661 | - IdRole = Qt::UserRole + 2, |
662 | - }; |
663 | - |
664 | - explicit TopLevelSurfaceList(QObject *parent = nullptr); |
665 | - virtual ~TopLevelSurfaceList(); |
666 | - |
667 | - // QAbstractItemModel methods |
668 | - int rowCount(const QModelIndex &parent = QModelIndex()) const override; |
669 | - QVariant data(const QModelIndex& index, int role) const override; |
670 | - QHash<int, QByteArray> roleNames() const override { |
671 | - QHash<int, QByteArray> roleNames { {SurfaceRole, "surface"}, |
672 | - {ApplicationRole, "application"}, |
673 | - {IdRole, "id"} }; |
674 | - return roleNames; |
675 | - } |
676 | - |
677 | - int nextId() const { return m_nextId; } |
678 | - |
679 | - QAbstractListModel *applicationsModel() const; |
680 | - void setApplicationsModel(QAbstractListModel*); |
681 | - |
682 | -public Q_SLOTS: |
683 | - /** |
684 | - * @brief Returns the surface at the given index |
685 | - * |
686 | - * It will be a nullptr if the application is still starting up and thus hasn't yet created |
687 | - * and drawn into a surface. |
688 | - */ |
689 | - unity::shell::application::MirSurfaceInterface *surfaceAt(int index) const; |
690 | - |
691 | - /** |
692 | - * @brief Returns the application at the given index |
693 | - */ |
694 | - unity::shell::application::ApplicationInfoInterface *applicationAt(int index) const; |
695 | - |
696 | - /** |
697 | - * @brief Returns the unique id of the element at the given index |
698 | - */ |
699 | - int idAt(int index) const; |
700 | - |
701 | - /** |
702 | - * @brief Returns the index where the row with the given id is located |
703 | - * |
704 | - * Returns -1 if there's no row with the given id. |
705 | - */ |
706 | - int indexForId(int id) const; |
707 | - |
708 | - /** |
709 | - * @brief Raises the row with the given id to index 0 |
710 | - */ |
711 | - void raiseId(int id); |
712 | - |
713 | - void doRaiseId(int id); |
714 | - |
715 | -Q_SIGNALS: |
716 | - void countChanged(); |
717 | - |
718 | - /** |
719 | - * @brief Emitted when the list changes |
720 | - * |
721 | - * Emitted when model gains an element, loses an element or when elements exchange positions. |
722 | - */ |
723 | - void listChanged(); |
724 | - |
725 | - void nextIdChanged(); |
726 | - |
727 | - void applicationsModelChanged(); |
728 | - |
729 | -private: |
730 | - void addApplication(unity::shell::application::ApplicationInfoInterface *application); |
731 | - void removeApplication(unity::shell::application::ApplicationInfoInterface *application); |
732 | - |
733 | - int indexOf(unity::shell::application::MirSurfaceInterface *surface); |
734 | - void raise(unity::shell::application::MirSurfaceInterface *surface); |
735 | - void move(int from, int to); |
736 | - void appendSurfaceHelper(unity::shell::application::MirSurfaceInterface *surface, |
737 | - unity::shell::application::ApplicationInfoInterface *application); |
738 | - void connectSurface(unity::shell::application::MirSurfaceInterface *surface); |
739 | - int generateId(); |
740 | - int nextFreeId(int candidateId); |
741 | - QString toString(); |
742 | - void onSurfaceDestroyed(unity::shell::application::MirSurfaceInterface *surface); |
743 | - void onSurfaceDied(unity::shell::application::MirSurfaceInterface *surface); |
744 | - void removeAt(int index); |
745 | - void findApplicationRole(); |
746 | - |
747 | - unity::shell::application::ApplicationInfoInterface *getApplicationFromModelAt(int index); |
748 | - |
749 | - /* |
750 | - Placeholder for a future surface from a starting or running application. |
751 | - Enables shell to give immediate feedback to the user by showing, eg, |
752 | - a splash screen. |
753 | - |
754 | - It's a model row containing a null surface and the given application. |
755 | - */ |
756 | - void appendPlaceholder(unity::shell::application::ApplicationInfoInterface *application); |
757 | - |
758 | - /* |
759 | - Adds a model row with the given surface and application |
760 | - |
761 | - Alternatively, if a placeholder exists for the given application it's |
762 | - filled with the given surface instead. |
763 | - */ |
764 | - void appendSurface(unity::shell::application::MirSurfaceInterface *surface, |
765 | - unity::shell::application::ApplicationInfoInterface *application); |
766 | - |
767 | - struct ModelEntry { |
768 | - ModelEntry(unity::shell::application::MirSurfaceInterface *surface, unity::shell::application::ApplicationInfoInterface *application, int id) |
769 | - : surface(surface), application(application), id(id) {} |
770 | - unity::shell::application::MirSurfaceInterface *surface; |
771 | - unity::shell::application::ApplicationInfoInterface *application; |
772 | - int id; |
773 | - bool removeOnceSurfaceDestroyed{false}; |
774 | - }; |
775 | - |
776 | - QList<ModelEntry> m_surfaceList; |
777 | - int m_nextId{1}; |
778 | - static const int m_maxId{1000000}; |
779 | - |
780 | - // applications that are being monitored |
781 | - QList<unity::shell::application::ApplicationInfoInterface *> m_applications; |
782 | - |
783 | - QAbstractListModel* m_applicationsModel{nullptr}; |
784 | - int m_applicationRole{-1}; |
785 | - |
786 | - enum ModelState { |
787 | - IdleState, |
788 | - InsertingState, |
789 | - RemovingState, |
790 | - MovingState, |
791 | - ResettingState |
792 | - }; |
793 | - ModelState m_modelState{IdleState}; |
794 | -}; |
795 | - |
796 | -Q_DECLARE_METATYPE(TopLevelSurfaceList*) |
797 | -Q_DECLARE_METATYPE(QAbstractListModel*) |
798 | - |
799 | -#endif // TOPLEVELSURFACELIST_H |
800 | |
801 | === removed file 'plugins/WindowManager/WindowManagerPlugin.cpp' |
802 | --- plugins/WindowManager/WindowManagerPlugin.cpp 2016-04-04 13:37:49 +0000 |
803 | +++ plugins/WindowManager/WindowManagerPlugin.cpp 1970-01-01 00:00:00 +0000 |
804 | @@ -1,28 +0,0 @@ |
805 | -/* |
806 | - * Copyright (C) 2016 Canonical, Ltd. |
807 | - * |
808 | - * This program is free software; you can redistribute it and/or modify |
809 | - * it under the terms of the GNU General Public License as published by |
810 | - * the Free Software Foundation; version 3. |
811 | - * |
812 | - * This program is distributed in the hope that it will be useful, |
813 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
814 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
815 | - * GNU General Public License for more details. |
816 | - * |
817 | - * You should have received a copy of the GNU General Public License |
818 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
819 | - */ |
820 | - |
821 | -#include "WindowManagerPlugin.h" |
822 | - |
823 | -#include "TopLevelSurfaceList.h" |
824 | - |
825 | -#include <QtQml> |
826 | - |
827 | -void WindowManagerPlugin::registerTypes(const char *uri) |
828 | -{ |
829 | - qmlRegisterType<TopLevelSurfaceList>(uri, 0, 1, "TopLevelSurfaceList"); |
830 | - |
831 | - qRegisterMetaType<QAbstractListModel*>("QAbstractListModel*"); |
832 | -} |
833 | |
834 | === removed file 'plugins/WindowManager/WindowManagerPlugin.h' |
835 | --- plugins/WindowManager/WindowManagerPlugin.h 2016-04-04 13:37:49 +0000 |
836 | +++ plugins/WindowManager/WindowManagerPlugin.h 1970-01-01 00:00:00 +0000 |
837 | @@ -1,32 +0,0 @@ |
838 | -/* |
839 | - * Copyright (C) 2016 Canonical, Ltd. |
840 | - * |
841 | - * This program is free software; you can redistribute it and/or modify |
842 | - * it under the terms of the GNU General Public License as published by |
843 | - * the Free Software Foundation; version 3. |
844 | - * |
845 | - * This program is distributed in the hope that it will be useful, |
846 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
847 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
848 | - * GNU General Public License for more details. |
849 | - * |
850 | - * You should have received a copy of the GNU General Public License |
851 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
852 | - */ |
853 | - |
854 | -#ifndef WINDOWMANAGER_PLUGIN_H |
855 | -#define WINDOWMANAGER_PLUGIN_H |
856 | - |
857 | -#include <QtQml/QQmlEngine> |
858 | -#include <QtQml/QQmlExtensionPlugin> |
859 | - |
860 | -class WindowManagerPlugin : public QQmlExtensionPlugin |
861 | -{ |
862 | - Q_OBJECT |
863 | - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") |
864 | - |
865 | -public: |
866 | - void registerTypes(const char *uri) override; |
867 | -}; |
868 | - |
869 | -#endif // WINDOWMANAGER_PLUGIN_H |
870 | |
871 | === removed file 'plugins/WindowManager/qmldir' |
872 | --- plugins/WindowManager/qmldir 2016-04-04 13:37:49 +0000 |
873 | +++ plugins/WindowManager/qmldir 1970-01-01 00:00:00 +0000 |
874 | @@ -1,2 +0,0 @@ |
875 | -module WindowManager |
876 | -plugin windowmanager-qml |
877 | |
878 | === modified file 'qml/Components/InputMethod.qml' |
879 | --- qml/Components/InputMethod.qml 2016-10-06 13:06:31 +0000 |
880 | +++ qml/Components/InputMethod.qml 2016-11-09 15:21:35 +0000 |
881 | @@ -23,6 +23,8 @@ |
882 | |
883 | readonly property rect visibleRect: surfaceItem.surface && visible ? surfaceItem.surface.inputBounds : Qt.rect(0, 0, 0, 0) |
884 | |
885 | + property var surface |
886 | + |
887 | MirSurfaceItem { |
888 | id: surfaceItem |
889 | anchors.fill: parent |
890 | @@ -31,7 +33,7 @@ |
891 | |
892 | surfaceWidth: root.enabled ? width : -1 |
893 | surfaceHeight: root.enabled ? height : -1 |
894 | - surface: SurfaceManager.inputMethodSurface |
895 | + surface: root.surface |
896 | |
897 | onLiveChanged: { |
898 | if (surface !== null && !live) { |
899 | @@ -50,7 +52,6 @@ |
900 | } |
901 | |
902 | visible: surfaceItem.surface && |
903 | - surfaceItem.surfaceState != Mir.HiddenState && |
904 | - surfaceItem.surfaceState != Mir.MinimizedState && |
905 | - root.enabled |
906 | + surfaceItem.surface.visible && |
907 | + root.enabled |
908 | } |
909 | |
910 | === modified file 'qml/Components/KeymapSwitcher.qml' |
911 | --- qml/Components/KeymapSwitcher.qml 2016-07-11 14:40:56 +0000 |
912 | +++ qml/Components/KeymapSwitcher.qml 2016-11-09 15:21:35 +0000 |
913 | @@ -23,6 +23,9 @@ |
914 | QtObject { |
915 | id: root |
916 | |
917 | + // to be set from outside |
918 | + property var focusedSurface: null |
919 | + |
920 | property GlobalShortcut shortcutNext: GlobalShortcut { |
921 | shortcut: Qt.MetaModifier|Qt.Key_Space |
922 | onTriggered: root.nextKeymap() |
923 | @@ -60,7 +63,7 @@ |
924 | } |
925 | |
926 | property Binding surfaceKeymapBinding: Binding { |
927 | - target: MirFocusController.focusedSurface |
928 | + target: root.focusedSurface |
929 | property: "keymap" |
930 | value: root.currentKeymap |
931 | } |
932 | |
933 | === modified file 'qml/Shell.qml' |
934 | --- qml/Shell.qml 2016-10-03 11:15:27 +0000 |
935 | +++ qml/Shell.qml 2016-11-09 15:21:35 +0000 |
936 | @@ -43,7 +43,6 @@ |
937 | import Unity.DashCommunicator 0.1 |
938 | import Unity.Indicators 0.1 as Indicators |
939 | import Cursor 1.1 |
940 | -import WindowManager 0.1 |
941 | |
942 | |
943 | StyledItem { |
944 | @@ -264,10 +263,9 @@ |
945 | width: parent.width |
946 | height: parent.height |
947 | |
948 | - TopLevelSurfaceList { |
949 | + TopLevelWindowModel { |
950 | id: topLevelSurfaceList |
951 | objectName: "topLevelSurfaceList" |
952 | - applicationsModel: ApplicationManager |
953 | } |
954 | |
955 | Stage { |
956 | @@ -320,6 +318,7 @@ |
957 | InputMethod { |
958 | id: inputMethod |
959 | objectName: "inputMethod" |
960 | + surface: topLevelSurfaceList.inputMethodSurface |
961 | anchors { |
962 | fill: parent |
963 | topMargin: panel.panelHeight |
964 | @@ -485,8 +484,8 @@ |
965 | greeterShown: greeter.shown |
966 | } |
967 | |
968 | - readonly property bool focusedSurfaceIsFullscreen: MirFocusController.focusedSurface |
969 | - ? MirFocusController.focusedSurface.state === Mir.FullscreenState |
970 | + readonly property bool focusedSurfaceIsFullscreen: topLevelSurfaceList.focusedWindow |
971 | + ? topLevelSurfaceList.focusedWindow.state === Mir.FullscreenState |
972 | : false |
973 | fullscreenMode: (focusedSurfaceIsFullscreen && !LightDMService.greeter.active && launcher.progress == 0) |
974 | || greeter.hasLockedApp |
975 | @@ -785,7 +784,9 @@ |
976 | } |
977 | |
978 | // non-visual object |
979 | - KeymapSwitcher {} |
980 | + KeymapSwitcher { |
981 | + focusedSurface: topLevelSurfaceList.focusedWindow ? topLevelSurfaceList.focusedWindow.surface : null |
982 | + } |
983 | |
984 | Rectangle { |
985 | id: shutdownFadeOutRectangle |
986 | |
987 | === modified file 'qml/Stage/DecoratedWindow.qml' |
988 | --- qml/Stage/DecoratedWindow.qml 2016-10-07 11:20:09 +0000 |
989 | +++ qml/Stage/DecoratedWindow.qml 2016-11-09 15:21:35 +0000 |
990 | @@ -70,11 +70,13 @@ |
991 | |
992 | readonly property Item clientAreaItem: applicationWindow |
993 | |
994 | + readonly property real contentX: applicationWindow.x |
995 | + readonly property real contentY: applicationWindow.y |
996 | + |
997 | signal closeClicked() |
998 | signal maximizeClicked() |
999 | signal maximizeHorizontallyClicked() |
1000 | signal maximizeVerticallyClicked() |
1001 | - signal minimizeClicked() |
1002 | signal decorationPressed() |
1003 | signal decorationReleased() |
1004 | |
1005 | @@ -163,7 +165,11 @@ |
1006 | onMaximizeClicked: { root.decorationPressed(); root.maximizeClicked(); } |
1007 | onMaximizeHorizontallyClicked: { root.decorationPressed(); root.maximizeHorizontallyClicked(); } |
1008 | onMaximizeVerticallyClicked: { root.decorationPressed(); root.maximizeVerticallyClicked(); } |
1009 | - onMinimizeClicked: root.minimizeClicked(); |
1010 | + onMinimizeClicked: { |
1011 | + if (applicationWindow.surface) { |
1012 | + applicationWindow.surface.requestState(Mir.MinimizedState); |
1013 | + } |
1014 | + } |
1015 | onPressed: root.decorationPressed(); |
1016 | |
1017 | onPressedChanged: moveHandler.handlePressedChanged(pressed, pressedButtons, mouseX, mouseY) |
1018 | |
1019 | === modified file 'qml/Stage/FakeMaximizeDelegate.qml' |
1020 | --- qml/Stage/FakeMaximizeDelegate.qml 2016-09-13 11:53:40 +0000 |
1021 | +++ qml/Stage/FakeMaximizeDelegate.qml 2016-11-09 15:21:35 +0000 |
1022 | @@ -98,19 +98,19 @@ |
1023 | function commit() { |
1024 | if (progress > hintThreshold && edge != -1) { |
1025 | if (edge == Item.Top) { |
1026 | - target.maximize(); |
1027 | + target.requestMaximize(); |
1028 | } else if (edge == Item.Left) { |
1029 | - target.maximizeLeft(); |
1030 | + target.requestMaximizeLeft(); |
1031 | } else if (edge == Item.Right) { |
1032 | - target.maximizeRight(); |
1033 | + target.requestMaximizeRight(); |
1034 | } else if (edge == Item.TopLeft) { |
1035 | - target.maximizeTopLeft(); |
1036 | + target.requestMaximizeTopLeft(); |
1037 | } else if (edge == Item.TopRight) { |
1038 | - target.maximizeTopRight(); |
1039 | + target.requestMaximizeTopRight(); |
1040 | } else if (edge == Item.BottomLeft) { |
1041 | - target.maximizeBottomLeft(); |
1042 | + target.requestMaximizeBottomLeft(); |
1043 | } else if (edge == Item.BottomRight) { |
1044 | - target.maximizeBottomRight(); |
1045 | + target.requestMaximizeBottomRight(); |
1046 | } |
1047 | } else { |
1048 | stop(); |
1049 | |
1050 | === modified file 'qml/Stage/Stage.qml' |
1051 | --- qml/Stage/Stage.qml 2016-10-24 11:34:20 +0000 |
1052 | +++ qml/Stage/Stage.qml 2016-11-09 15:21:35 +0000 |
1053 | @@ -92,8 +92,7 @@ |
1054 | |
1055 | onAltTabPressedChanged: priv.goneToSpread = altTabPressed |
1056 | |
1057 | - property Item itemConfiningMouseCursor: !spreadShown && priv.focusedAppDelegate && priv.focusedAppDelegate.surface && |
1058 | - priv.focusedAppDelegate.surface.confinesMousePointer ? |
1059 | + property Item itemConfiningMouseCursor: !spreadShown && priv.focusedAppDelegate && priv.focusedAppDelegate.window.confinesMousePointer ? |
1060 | priv.focusedAppDelegate.clientAreaItem : null; |
1061 | |
1062 | signal itemSnapshotRequested(Item item) |
1063 | @@ -152,29 +151,34 @@ |
1064 | GlobalShortcut { |
1065 | id: maximizeWindowShortcut |
1066 | shortcut: Qt.MetaModifier|Qt.ControlModifier|Qt.Key_Up |
1067 | - onTriggered: priv.focusedAppDelegate.maximize() |
1068 | + onTriggered: priv.focusedAppDelegate.requestMaximize() |
1069 | active: root.state == "windowed" && priv.focusedAppDelegate && priv.focusedAppDelegate.canBeMaximized |
1070 | } |
1071 | |
1072 | GlobalShortcut { |
1073 | id: maximizeWindowLeftShortcut |
1074 | shortcut: Qt.MetaModifier|Qt.ControlModifier|Qt.Key_Left |
1075 | - onTriggered: priv.focusedAppDelegate.maximizeLeft() |
1076 | + onTriggered: priv.focusedAppDelegate.requestMaximizeLeft() |
1077 | active: root.state == "windowed" && priv.focusedAppDelegate && priv.focusedAppDelegate.canBeMaximizedLeftRight |
1078 | } |
1079 | |
1080 | GlobalShortcut { |
1081 | id: maximizeWindowRightShortcut |
1082 | shortcut: Qt.MetaModifier|Qt.ControlModifier|Qt.Key_Right |
1083 | - onTriggered: priv.focusedAppDelegate.maximizeRight() |
1084 | + onTriggered: priv.focusedAppDelegate.requestMaximizeRight() |
1085 | active: root.state == "windowed" && priv.focusedAppDelegate && priv.focusedAppDelegate.canBeMaximizedLeftRight |
1086 | } |
1087 | |
1088 | GlobalShortcut { |
1089 | id: minimizeRestoreShortcut |
1090 | shortcut: Qt.MetaModifier|Qt.ControlModifier|Qt.Key_Down |
1091 | - onTriggered: priv.focusedAppDelegate.anyMaximized |
1092 | - ? priv.focusedAppDelegate.restoreFromMaximized() : priv.focusedAppDelegate.minimize() |
1093 | + onTriggered: { |
1094 | + if (priv.focusedAppDelegate.anyMaximized) { |
1095 | + priv.focusedAppDelegate.requestRestore(); |
1096 | + } else { |
1097 | + priv.focusedAppDelegate.requestMinimize(); |
1098 | + } |
1099 | + } |
1100 | active: root.state == "windowed" && priv.focusedAppDelegate |
1101 | } |
1102 | |
1103 | @@ -210,20 +214,10 @@ |
1104 | } |
1105 | |
1106 | function minimizeAllWindows() { |
1107 | - for (var i = 0; i < appRepeater.count; i++) { |
1108 | - var appDelegate = appRepeater.itemAt(i); |
1109 | - if (appDelegate && !appDelegate.minimized) { |
1110 | - appDelegate.minimize(); |
1111 | - } |
1112 | - } |
1113 | - } |
1114 | - |
1115 | - function focusNext() { |
1116 | - for (var i = 0; i < appRepeater.count; i++) { |
1117 | - var appDelegate = appRepeater.itemAt(i); |
1118 | - if (appDelegate && !appDelegate.minimized) { |
1119 | - appDelegate.focus = true; |
1120 | - return; |
1121 | + for (var i = appRepeater.count - 1; i >= 0; i--) { |
1122 | + var appDelegate = appRepeater.itemAt(i); |
1123 | + if (appDelegate && !appDelegate.minimized) { |
1124 | + appDelegate.requestMinimize(); |
1125 | } |
1126 | } |
1127 | } |
1128 | @@ -251,7 +245,7 @@ |
1129 | priv.sideStageItemId = 0; |
1130 | priv.sideStageAppId = ""; |
1131 | priv.mainStageDelegate = appRepeater.itemAt(0); |
1132 | - priv.mainStageAppId = topLevelSurfaceList.idAt(0); |
1133 | + priv.mainStageItemId = topLevelSurfaceList.idAt(0); |
1134 | priv.mainStageAppId = topLevelSurfaceList.applicationAt(0) ? topLevelSurfaceList.applicationAt(0).appId : "" |
1135 | return; |
1136 | } |
1137 | @@ -318,8 +312,8 @@ |
1138 | Connections { |
1139 | target: PanelState |
1140 | onCloseClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.close(); } } |
1141 | - onMinimizeClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.minimize(); } } |
1142 | - onRestoreClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.restoreFromMaximized(); } } |
1143 | + onMinimizeClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.requestMinimize(); } } |
1144 | + onRestoreClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.requestRestore(); } } |
1145 | } |
1146 | |
1147 | Binding { |
1148 | @@ -394,13 +388,6 @@ |
1149 | } |
1150 | } |
1151 | |
1152 | - Binding { |
1153 | - target: MirFocusController |
1154 | - property: "focusedSurface" |
1155 | - value: priv.focusedAppDelegate ? priv.focusedAppDelegate.focusedSurface : null |
1156 | - when: !appRepeater.startingUp && root.parent |
1157 | - } |
1158 | - |
1159 | states: [ |
1160 | State { |
1161 | name: "spread"; when: priv.goneToSpread |
1162 | @@ -567,7 +554,7 @@ |
1163 | |
1164 | onShownChanged: { |
1165 | if (!shown && priv.mainStageDelegate) { |
1166 | - priv.mainStageDelegate.claimFocus(); |
1167 | + priv.mainStageDelegate.requestFocus(); |
1168 | } |
1169 | } |
1170 | |
1171 | @@ -600,14 +587,23 @@ |
1172 | } |
1173 | } |
1174 | |
1175 | - TopLevelSurfaceRepeater { |
1176 | + Repeater { |
1177 | id: appRepeater |
1178 | model: topLevelSurfaceList |
1179 | objectName: "appRepeater" |
1180 | |
1181 | + function indexOf(delegateItem) { |
1182 | + for (var i = 0; i < count; i++) { |
1183 | + if (itemAt(i) === delegateItem) { |
1184 | + return i; |
1185 | + } |
1186 | + } |
1187 | + return -1; |
1188 | + } |
1189 | + |
1190 | delegate: FocusScope { |
1191 | id: appDelegate |
1192 | - objectName: "appDelegate_" + model.id |
1193 | + objectName: "appDelegate_" + model.window.id |
1194 | property int itemIndex: index // We need this from outside the repeater |
1195 | // z might be overriden in some cases by effects, but we need z ordering |
1196 | // to calculate occlusion detection |
1197 | @@ -619,11 +615,11 @@ |
1198 | } |
1199 | z: normalZ |
1200 | |
1201 | - // Normally we want x/y where we request it to be. Width/height of our delegate will |
1202 | + // Normally we want x/y where the surface thinks it is. Width/height of our delegate will |
1203 | // match what the actual surface size is. |
1204 | // Don't write to those, they will be set by states |
1205 | - x: requestedX |
1206 | - y: requestedY |
1207 | + x: model.window.position.x - decoratedWindow.contentX |
1208 | + y: model.window.position.y - decoratedWindow.contentY |
1209 | width: decoratedWindow.implicitWidth |
1210 | height: decoratedWindow.implicitHeight |
1211 | |
1212 | @@ -633,6 +629,12 @@ |
1213 | property real requestedY: windowedY |
1214 | property real requestedWidth: windowedWidth |
1215 | property real requestedHeight: windowedHeight |
1216 | + Binding { |
1217 | + target: model.window; property: "requestedPosition" |
1218 | + // miral doesn't know about our window decorations. So we have to deduct them |
1219 | + value: Qt.point(appDelegate.requestedX + decoratedWindow.contentX, |
1220 | + appDelegate.requestedY + decoratedWindow.contentY) |
1221 | + } |
1222 | |
1223 | // In those are for windowed mode. Those values basically store the window's properties |
1224 | // when having a floating window. If you want to move/resize a window in normal mode, this is what you want to write to. |
1225 | @@ -649,7 +651,7 @@ |
1226 | Binding { |
1227 | target: appDelegate |
1228 | property: "y" |
1229 | - value: appDelegate.requestedY - |
1230 | + value: model.window.position.y - |
1231 | Math.min(appDelegate.requestedY - PanelState.panelHeight, |
1232 | Math.max(0, priv.virtualKeyboardHeight - (appContainer.height - (appDelegate.requestedY + appDelegate.height)))) |
1233 | when: root.oskEnabled && appDelegate.focus && (appDelegate.state == "normal" || appDelegate.state == "restored") |
1234 | @@ -705,7 +707,7 @@ |
1235 | maximizedTopLeft || maximizedTopRight || maximizedBottomLeft || maximizedBottomRight |
1236 | |
1237 | readonly property bool minimized: windowState & WindowStateStorage.WindowStateMinimized |
1238 | - readonly property bool fullscreen: surface ? surface.state === Mir.FullscreenState : application.fullscreen |
1239 | + readonly property bool fullscreen: window.state === Mir.FullscreenState |
1240 | |
1241 | readonly property bool canBeMaximized: canBeMaximizedHorizontally && canBeMaximizedVertically |
1242 | readonly property bool canBeMaximizedLeftRight: (maximumWidth == 0 || maximumWidth >= appContainer.width/2) && |
1243 | @@ -731,7 +733,9 @@ |
1244 | priv.updateMainAndSideStageIndexes() |
1245 | } |
1246 | |
1247 | - readonly property var surface: model.surface |
1248 | + readonly property var surface: model.window.surface |
1249 | + readonly property var window: model.window |
1250 | + |
1251 | readonly property alias resizeArea: resizeArea |
1252 | readonly property alias focusedSurface: decoratedWindow.focusedSurface |
1253 | readonly property bool dragging: touchControls.overlayShown ? touchControls.dragging : decoratedWindow.dragging |
1254 | @@ -740,6 +744,19 @@ |
1255 | readonly property bool isDash: appId == "unity8-dash" |
1256 | readonly property alias clientAreaItem: decoratedWindow.clientAreaItem |
1257 | |
1258 | + function requestFocus() { model.window.requestFocus(); } |
1259 | + function requestMaximize() { model.window.requestState(Mir.MaximizedState); } |
1260 | + function requestMaximizeVertically() { model.window.requestState(Mir.VertMaximizedState); } |
1261 | + function requestMaximizeHorizontally() { model.window.requestState(Mir.HorizMaximizedState); } |
1262 | + function requestMaximizeLeft() { model.window.requestState(Mir.MaximizedLeftState); } |
1263 | + function requestMaximizeRight() { model.window.requestState(Mir.MaximizedRightState); } |
1264 | + function requestMaximizeTopLeft() { model.window.requestState(Mir.MaximizedTopLeftState); } |
1265 | + function requestMaximizeTopRight() { model.window.requestState(Mir.MaximizedTopRightState); } |
1266 | + function requestMaximizeBottomLeft() { model.window.requestState(Mir.MaximizedBottomLeftState); } |
1267 | + function requestMaximizeBottomRight() { model.window.requestState(Mir.MaximizedBottomRightState); } |
1268 | + function requestMinimize() { model.window.requestState(Mir.MinimizedState); } |
1269 | + function requestRestore() { model.window.requestState(Mir.RestoredState); } |
1270 | + |
1271 | function claimFocus() { |
1272 | if (root.state == "spread") { |
1273 | spreadItem.highlightedIndex = index |
1274 | @@ -751,45 +768,63 @@ |
1275 | } |
1276 | priv.updateMainAndSideStageIndexes(); |
1277 | } |
1278 | - |
1279 | if (root.mode == "windowed") { |
1280 | appDelegate.restore(true /* animated */, appDelegate.windowState); |
1281 | - } else { |
1282 | - appDelegate.focus = true; |
1283 | } |
1284 | + appDelegate.focus = true; |
1285 | } |
1286 | - Connections { |
1287 | - target: model.surface |
1288 | - onFocusRequested: { |
1289 | + |
1290 | + function updateQmlFocusFromMirSurfaceFocus() { |
1291 | + if (model.window.focused) { |
1292 | claimFocus(); |
1293 | + priv.focusedAppDelegate = appDelegate; |
1294 | + //} else if (priv.focusedAppDelegate === appDelegate && root.state != "spread") { |
1295 | + // priv.focusedAppDelegate = null; |
1296 | } |
1297 | } |
1298 | + |
1299 | Connections { |
1300 | - target: model.application |
1301 | + target: model.window |
1302 | + onFocusedChanged: { |
1303 | + updateQmlFocusFromMirSurfaceFocus(); |
1304 | + } |
1305 | onFocusRequested: { |
1306 | - if (!model.surface) { |
1307 | - // when an app has no surfaces, we assume there's only one entry representing it: |
1308 | - // this delegate. |
1309 | + if (model.window.focused && priv.focusedAppDelegate === appDelegate) { |
1310 | + // it's already properly focused. Just ensure we show it on foreground |
1311 | claimFocus(); |
1312 | - } else { |
1313 | - // if the application has surfaces, focus request should be at surface-level. |
1314 | - } |
1315 | - } |
1316 | - } |
1317 | - |
1318 | - onFocusChanged: { |
1319 | - if (appRepeater.startingUp) |
1320 | - return; |
1321 | - |
1322 | - if (focus) { |
1323 | - topLevelSurfaceList.raiseId(model.id); |
1324 | - priv.focusedAppDelegate = appDelegate; |
1325 | - } else if (!focus && priv.focusedAppDelegate === appDelegate && root.state != "spread") { |
1326 | - priv.focusedAppDelegate = null; |
1327 | - // FIXME: No idea why the Binding{} doens't update when focusedAppDelegate turns null |
1328 | - MirFocusController.focusedSurface = null; |
1329 | - } |
1330 | - } |
1331 | + } |
1332 | + } |
1333 | + onStateChanged: { |
1334 | + if (model.window.state === Mir.MinimizedState) { |
1335 | + appDelegate.minimize(); |
1336 | + } else if (model.window.state === Mir.MaximizedState) { |
1337 | + appDelegate.maximize(); |
1338 | + } else if (model.window.state === Mir.VertMaximizedState) { |
1339 | + appDelegate.maximizeVertically(); |
1340 | + } else if (model.window.state === Mir.HorizMaximizedState) { |
1341 | + appDelegate.maximizeHorizontally(); |
1342 | + } else if (model.window.state === Mir.MaximizedLeftState) { |
1343 | + appDelegate.maximizeLeft(); |
1344 | + } else if (model.window.state === Mir.MaximizedRightState) { |
1345 | + appDelegate.maximizeRight(); |
1346 | + } else if (model.window.state === Mir.MaximizedTopLeftState) { |
1347 | + appDelegate.maximizeTopLeft(); |
1348 | + } else if (model.window.state === Mir.MaximizedTopRightState) { |
1349 | + appDelegate.maximizeTopRight(); |
1350 | + } else if (model.window.state === Mir.MaximizedBottomLeftState) { |
1351 | + appDelegate.maximizeBottomLeft(); |
1352 | + } else if (model.window.state === Mir.MaximizedBottomRightState) { |
1353 | + appDelegate.maximizeBottomRight(); |
1354 | + } else if (model.window.state === Mir.RestoredState) { |
1355 | + if (appDelegate.anyMaximized) { |
1356 | + appDelegate.restoreFromMaximized() |
1357 | + } else { |
1358 | + appDelegate.restore(); |
1359 | + } |
1360 | + } |
1361 | + } |
1362 | + } |
1363 | + |
1364 | Component.onCompleted: { |
1365 | if (application && application.rotatesWindowContents) { |
1366 | decoratedWindow.surfaceOrientationAngle = shellOrientationAngle; |
1367 | @@ -803,16 +838,7 @@ |
1368 | // Now load any saved state. This needs to happen *after* the cascading! |
1369 | resizeArea.loadWindowState(); |
1370 | |
1371 | - // NB: We're differentiating if this delegate was created in response to a new entry in the model |
1372 | - // or if the Repeater is just populating itself with delegates to match the model it received. |
1373 | - if (!appRepeater.startingUp) { |
1374 | - // a top level window is always the focused one when it first appears, unfocusing |
1375 | - // any preexisting one |
1376 | - if (root.state == "spread") { |
1377 | - spreadItem.highlightedIndex = index; |
1378 | - } |
1379 | - claimFocus(); |
1380 | - } |
1381 | + updateQmlFocusFromMirSurfaceFocus(); |
1382 | |
1383 | refreshStage(); |
1384 | _constructing = false; |
1385 | @@ -827,16 +853,6 @@ |
1386 | priv.updateForegroundMaximizedApp(); |
1387 | } |
1388 | |
1389 | - if (focus) { |
1390 | - // focus some other window |
1391 | - for (var i = 0; i < appRepeater.count; i++) { |
1392 | - var appDelegate = appRepeater.itemAt(i); |
1393 | - if (appDelegate && !appDelegate.minimized && i != index) { |
1394 | - appDelegate.focus = true; |
1395 | - return; |
1396 | - } |
1397 | - } |
1398 | - } |
1399 | } |
1400 | |
1401 | onVisuallyMaximizedChanged: priv.updateForegroundMaximizedApp() |
1402 | @@ -857,7 +873,7 @@ |
1403 | || focusAnimation.running || rightEdgeFocusAnimation.running || hidingAnimation.running |
1404 | |
1405 | function close() { |
1406 | - model.surface.close(); |
1407 | + model.window.close(); |
1408 | } |
1409 | |
1410 | function maximize(animated) { |
1411 | @@ -908,7 +924,6 @@ |
1412 | animationsEnabled = (animated === undefined) || animated; |
1413 | windowState = state || WindowStateStorage.WindowStateRestored; |
1414 | windowState &= ~WindowStateStorage.WindowStateMinimized; // clear the minimized bit |
1415 | - focus = true; |
1416 | } |
1417 | |
1418 | function playFocusAnimation() { |
1419 | @@ -922,7 +937,7 @@ |
1420 | rightEdgeFocusAnimation.start() |
1421 | } |
1422 | } else if (state == "windowedRightEdge" || state == "windowed") { |
1423 | - claimFocus(); |
1424 | + requestFocus(); |
1425 | } else { |
1426 | focusAnimation.start() |
1427 | } |
1428 | @@ -960,10 +975,10 @@ |
1429 | to: 1 |
1430 | duration: UbuntuAnimation.SnapDuration |
1431 | onStarted: { |
1432 | - topLevelSurfaceList.raiseId(model.id); |
1433 | + topLevelSurfaceList.raiseId(model.window.id); |
1434 | } |
1435 | onStopped: { |
1436 | - appDelegate.claimFocus(); |
1437 | + appDelegate.requestFocus(); |
1438 | } |
1439 | } |
1440 | ParallelAnimation { |
1441 | @@ -973,7 +988,7 @@ |
1442 | UbuntuNumberAnimation { target: decoratedWindow; properties: "angle"; to: 0; duration: priv.animationDuration } |
1443 | UbuntuNumberAnimation { target: decoratedWindow; properties: "itemScale"; to: 1; duration: priv.animationDuration } |
1444 | onStopped: { |
1445 | - appDelegate.focus = true |
1446 | + appDelegate.requestFocus(); |
1447 | } |
1448 | } |
1449 | ParallelAnimation { |
1450 | @@ -1333,14 +1348,6 @@ |
1451 | SequentialAnimation { |
1452 | UbuntuNumberAnimation { target: appDelegate; properties: "requestedX,requestedY,opacity,scale,requestedWidth,requestedHeight" } |
1453 | PropertyAction { target: appDelegate; property: "visuallyMinimized" } |
1454 | - ScriptAction { |
1455 | - script: { |
1456 | - if (appDelegate.minimized) { |
1457 | - appDelegate.focus = false; |
1458 | - priv.focusNext(); |
1459 | - } |
1460 | - } |
1461 | - } |
1462 | } |
1463 | }, |
1464 | Transition { |
1465 | @@ -1430,7 +1437,7 @@ |
1466 | visible: enabled |
1467 | |
1468 | onPressed: { |
1469 | - appDelegate.focus = true; |
1470 | + appDelegate.requestFocus(); |
1471 | } |
1472 | |
1473 | Component.onDestruction: { |
1474 | @@ -1444,7 +1451,7 @@ |
1475 | anchors.left: appDelegate.left |
1476 | anchors.top: appDelegate.top |
1477 | application: model.application |
1478 | - surface: model.surface |
1479 | + surface: model.window.surface |
1480 | active: appDelegate.focus |
1481 | focus: true |
1482 | interactive: root.interactive |
1483 | @@ -1467,11 +1474,20 @@ |
1484 | onRequestedHeightChanged: oldRequestedHeight = requestedHeight |
1485 | |
1486 | onCloseClicked: { appDelegate.close(); } |
1487 | - onMaximizeClicked: appDelegate.anyMaximized ? appDelegate.restoreFromMaximized() : appDelegate.maximize(); |
1488 | - onMaximizeHorizontallyClicked: appDelegate.maximizedHorizontally ? appDelegate.restoreFromMaximized() : appDelegate.maximizeHorizontally() |
1489 | - onMaximizeVerticallyClicked: appDelegate.maximizedVertically ? appDelegate.restoreFromMaximized() : appDelegate.maximizeVertically() |
1490 | - onMinimizeClicked: appDelegate.minimize() |
1491 | - onDecorationPressed: { appDelegate.focus = true; } |
1492 | + onMaximizeClicked: appDelegate.anyMaximized ? appDelegate.requestRestore() : appDelegate.requestMaximize(); |
1493 | + onMaximizeHorizontallyClicked: { |
1494 | + if (appDelegate.maximizedHorizontally) |
1495 | + appDelegate.requestRestore(); |
1496 | + else |
1497 | + appDelegate.requestMaximizeHorizontally(); |
1498 | + } |
1499 | + onMaximizeVerticallyClicked: { |
1500 | + if (appDelegate.maximizedVertically) |
1501 | + appDelegate.requestRestore(); |
1502 | + else |
1503 | + appDelegate.requestMaximizeVertically(); |
1504 | + } |
1505 | + onDecorationPressed: { appDelegate.requestFocus(); } |
1506 | onDecorationReleased: fakeRectangle.commit(); |
1507 | |
1508 | property real angle: 0 |
1509 | @@ -1518,12 +1534,12 @@ |
1510 | WindowedFullscreenPolicy { |
1511 | id: windowedFullscreenPolicy |
1512 | active: root.mode == "windowed" |
1513 | - surface: model.surface |
1514 | + surface: model.window.surface |
1515 | } |
1516 | StagedFullscreenPolicy { |
1517 | id: stagedFullscreenPolicy |
1518 | active: root.mode == "staged" || root.mode == "stagedWithSideStage" |
1519 | - surface: model.surface |
1520 | + surface: model.window.surface |
1521 | } |
1522 | |
1523 | SpreadDelegateInputArea { |
1524 | @@ -1536,16 +1552,13 @@ |
1525 | onClicked: { |
1526 | spreadItem.highlightedIndex = index; |
1527 | if (distance == 0) { |
1528 | + model.window.requestFocus(); |
1529 | priv.goneToSpread = false; |
1530 | } |
1531 | } |
1532 | onClose: { |
1533 | priv.closingIndex = index |
1534 | - if (model.surface) { // could be stopped by OOM |
1535 | - model.surface.close() |
1536 | - } else if (model.application) { |
1537 | - root.applicationManager.stopApplication(model.application.appId); |
1538 | - } |
1539 | + model.window.close(); |
1540 | } |
1541 | } |
1542 | |
1543 | |
1544 | === modified file 'qml/Stage/StagedFullscreenPolicy.qml' |
1545 | --- qml/Stage/StagedFullscreenPolicy.qml 2016-04-04 13:41:19 +0000 |
1546 | +++ qml/Stage/StagedFullscreenPolicy.qml 2016-11-09 15:21:35 +0000 |
1547 | @@ -32,7 +32,7 @@ |
1548 | onSurfaceChanged: { |
1549 | if (!active || !surface) return; |
1550 | if (surface.shellChrome === Mir.LowChrome) { |
1551 | - surface.state = Mir.FullscreenState; |
1552 | + surface.requestState(Mir.FullscreenState); |
1553 | } |
1554 | } |
1555 | |
1556 | @@ -41,15 +41,15 @@ |
1557 | onShellChromeChanged: { |
1558 | if (!active || !surface) return; |
1559 | if (surface.shellChrome === Mir.LowChrome) { |
1560 | - surface.state = Mir.FullscreenState; |
1561 | + surface.requestState(Mir.FullscreenState); |
1562 | } else { |
1563 | - surface.state = Mir.RestoredState; |
1564 | + surface.requestState(Mir.RestoredState); |
1565 | } |
1566 | } |
1567 | onStateChanged: { |
1568 | if (!active) return; |
1569 | if (surface.state === Mir.RestoredState && surface.shellChrome === Mir.LowChrome) { |
1570 | - surface.state = Mir.FullscreenState; |
1571 | + surface.requestState(Mir.FullscreenState); |
1572 | } |
1573 | } |
1574 | } |
1575 | |
1576 | === removed file 'qml/Stage/TopLevelSurfaceRepeater.qml' |
1577 | --- qml/Stage/TopLevelSurfaceRepeater.qml 2016-09-12 17:05:43 +0000 |
1578 | +++ qml/Stage/TopLevelSurfaceRepeater.qml 1970-01-01 00:00:00 +0000 |
1579 | @@ -1,67 +0,0 @@ |
1580 | -/* |
1581 | - * Copyright (C) 2016 Canonical, Ltd. |
1582 | - * |
1583 | - * This program is free software; you can redistribute it and/or modify |
1584 | - * it under the terms of the GNU General Public License as published by |
1585 | - * the Free Software Foundation; version 3. |
1586 | - * |
1587 | - * This program is distributed in the hope that it will be useful, |
1588 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1589 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1590 | - * GNU General Public License for more details. |
1591 | - * |
1592 | - * You should have received a copy of the GNU General Public License |
1593 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1594 | - */ |
1595 | - |
1596 | -import QtQuick 2.4 |
1597 | - |
1598 | -Repeater { |
1599 | - id: root |
1600 | - // FIXME: This is a hack around us not knowing whether the Repeater has finished creating its |
1601 | - // delegates on start up. |
1602 | - // This is a problem when the stage gets a TopLevelSurfaceList already populated with several |
1603 | - // rows. |
1604 | - property bool startingUp: true |
1605 | - onStartingUpChanged: { |
1606 | - if (!startingUp) { |
1607 | - // the top-most surface must be the focused one. |
1608 | - var topmostDelegate = itemAt(0); |
1609 | - if (topmostDelegate.focus) { |
1610 | - // Delegate got focused while we were still starting up. Not good. |
1611 | - // Force signal handler to run again |
1612 | - topmostDelegate.onFocusChanged(true); |
1613 | - } else { |
1614 | - topmostDelegate.focus = true; |
1615 | - } |
1616 | - } |
1617 | - } |
1618 | - |
1619 | - onItemAdded: { |
1620 | - if (startingUp) { |
1621 | - checkIfStillStartingUp(); |
1622 | - } |
1623 | - } |
1624 | - |
1625 | - function checkIfStillStartingUp() { |
1626 | - var i = 0; |
1627 | - var missingDelegate = false; |
1628 | - for (i = 0; i < model.count && !missingDelegate; ++i) { |
1629 | - if (!itemAt(i)) { |
1630 | - missingDelegate = true; |
1631 | - } |
1632 | - } |
1633 | - if (!missingDelegate) { |
1634 | - startingUp = false; |
1635 | - } |
1636 | - } |
1637 | - |
1638 | - function indexOf(delegateItem) { |
1639 | - for (var i = 0; i < count; i++) { |
1640 | - if (itemAt(i) === delegateItem) { |
1641 | - return i; |
1642 | - } |
1643 | - } |
1644 | - return -1; |
1645 | - } |
1646 | -} |
1647 | |
1648 | === modified file 'qml/Stage/WindowedFullscreenPolicy.qml' |
1649 | --- qml/Stage/WindowedFullscreenPolicy.qml 2016-04-04 13:37:49 +0000 |
1650 | +++ qml/Stage/WindowedFullscreenPolicy.qml 2016-11-09 15:21:35 +0000 |
1651 | @@ -33,7 +33,7 @@ |
1652 | _firstTimeSurface = false; |
1653 | |
1654 | if (surface.state === Mir.FullscreenState && surface.shellChrome === Mir.LowChrome) { |
1655 | - surface.state = Mir.RestoredState; |
1656 | + surface.requestState(Mir.RestoredState); |
1657 | } |
1658 | } |
1659 | } |
1660 | |
1661 | === modified file 'tests/mocks/Unity/Application/ApplicationInfo.cpp' |
1662 | --- tests/mocks/Unity/Application/ApplicationInfo.cpp 2016-09-12 17:05:43 +0000 |
1663 | +++ tests/mocks/Unity/Application/ApplicationInfo.cpp 2016-11-09 15:21:35 +0000 |
1664 | @@ -90,14 +90,17 @@ |
1665 | return; |
1666 | } |
1667 | |
1668 | + bool wasFocused = focused(); |
1669 | + |
1670 | auto surface = surfaceManager->createSurface(surfaceName, |
1671 | Mir::NormalType, |
1672 | - fullscreen() ? Mir::FullscreenState : Mir::MaximizedState, |
1673 | - m_screenshotFileName); |
1674 | + fullscreen() ? Mir::FullscreenState : Mir::RestoredState, |
1675 | + m_screenshotFileName, |
1676 | + this); |
1677 | |
1678 | surface->setShellChrome(m_shellChrome); |
1679 | |
1680 | - m_surfaceList->appendSurface(surface); |
1681 | + m_surfaceList->addSurface(surface); |
1682 | |
1683 | ++m_liveSurfaceCount; |
1684 | connect(surface, &MirSurface::liveChanged, this, [this, surface](){ |
1685 | @@ -125,8 +128,19 @@ |
1686 | setState(Running); |
1687 | } |
1688 | }); |
1689 | + connect(surface, &MirSurfaceInterface::focusedChanged, this, [&](bool /*value*/) { |
1690 | + #if APPLICATION_DEBUG |
1691 | + qDebug().nospace() << "Application[" << appId() << "].focusedChanged(" << focused() << ")"; |
1692 | + #endif |
1693 | + Q_EMIT focusedChanged(focused()); |
1694 | + }); |
1695 | + |
1696 | connect(surface, &MirSurface::focusRequested, this, &ApplicationInfo::focusRequested); |
1697 | |
1698 | + if (wasFocused != focused()) { |
1699 | + Q_EMIT focusedChanged(focused()); |
1700 | + } |
1701 | + |
1702 | if (m_state == Starting) { |
1703 | if (m_requestedState == RequestedRunning) { |
1704 | setState(Running); |
1705 | @@ -218,7 +232,7 @@ |
1706 | { |
1707 | m_fullscreen = value; |
1708 | if (m_surfaceList->rowCount() > 0) { |
1709 | - m_surfaceList->get(0)->setState(Mir::FullscreenState); |
1710 | + m_surfaceList->get(0)->requestState(Mir::FullscreenState); |
1711 | } |
1712 | } |
1713 | |
1714 | |
1715 | === modified file 'tests/mocks/Unity/Application/ApplicationManager.cpp' |
1716 | --- tests/mocks/Unity/Application/ApplicationManager.cpp 2016-08-23 12:04:11 +0000 |
1717 | +++ tests/mocks/Unity/Application/ApplicationManager.cpp 2016-11-09 15:21:35 +0000 |
1718 | @@ -40,10 +40,14 @@ |
1719 | |
1720 | namespace unityapi = unity::shell::application; |
1721 | |
1722 | + |
1723 | ApplicationManager::ApplicationManager(QObject *parent) |
1724 | : ApplicationManagerInterface(parent) |
1725 | { |
1726 | DEBUG_MSG(""); |
1727 | + |
1728 | + ApplicationManagerNotifier::instance()->setApplicationManager(this); |
1729 | + |
1730 | buildListOfAvailableApplications(); |
1731 | |
1732 | // polling to find out when the toplevel window has been created as there's |
1733 | @@ -53,11 +57,6 @@ |
1734 | m_windowCreatedTimer.setSingleShot(false); |
1735 | m_windowCreatedTimer.start(200); |
1736 | |
1737 | - Q_ASSERT(MirFocusController::instance()); |
1738 | - connect(MirFocusController::instance(), &MirFocusController::focusedSurfaceChanged, |
1739 | - this, &ApplicationManager::updateFocusedApplication, Qt::QueuedConnection); |
1740 | - |
1741 | - |
1742 | // Emit signal to notify Upstart that Mir is ready to receive client connections |
1743 | // see http://upstart.ubuntu.com/cookbook/#expect-stop |
1744 | // We do this because some autopilot tests actually use this mock Unity.Application module, |
1745 | @@ -69,6 +68,7 @@ |
1746 | |
1747 | ApplicationManager::~ApplicationManager() |
1748 | { |
1749 | + ApplicationManagerNotifier::instance()->setApplicationManager(nullptr); |
1750 | } |
1751 | |
1752 | void ApplicationManager::onWindowCreatedTimerTimeout() |
1753 | @@ -158,6 +158,10 @@ |
1754 | QModelIndex appIndex = findIndex(application); |
1755 | if (!appIndex.isValid()) return; |
1756 | Q_EMIT dataChanged(appIndex, appIndex, QVector<int>() << ApplicationManager::RoleFocused); |
1757 | + Q_EMIT focusedApplicationIdChanged(); |
1758 | + if (application->focused()) { |
1759 | + raiseApp(application->appId()); |
1760 | + } |
1761 | }); |
1762 | connect(application, &ApplicationInfo::stateChanged, this, [application, this]() { |
1763 | QModelIndex appIndex = findIndex(application); |
1764 | @@ -181,15 +185,40 @@ |
1765 | |
1766 | void ApplicationManager::remove(ApplicationInfo *application) { |
1767 | int i = m_runningApplications.indexOf(application); |
1768 | + application->disconnect(this); |
1769 | if (i != -1) { |
1770 | DEBUG_MSG(application->appId()); |
1771 | + Q_ASSERT(!m_modelBusy); |
1772 | + m_modelBusy = true; |
1773 | beginRemoveRows(QModelIndex(), i, i); |
1774 | m_runningApplications.removeAt(i); |
1775 | endRemoveRows(); |
1776 | + m_modelBusy = false; |
1777 | Q_EMIT countChanged(); |
1778 | if (isEmpty()) Q_EMIT emptyChanged(isEmpty()); |
1779 | - } |
1780 | - application->disconnect(this); |
1781 | + DEBUG_MSG(application->appId() << " after: " << qPrintable(toString())); |
1782 | + } |
1783 | +} |
1784 | + |
1785 | +void ApplicationManager::raiseApp(const QString &appId) |
1786 | +{ |
1787 | + |
1788 | + int index = -1; |
1789 | + for (int i = 0; i < m_runningApplications.count() && index == -1; ++i) { |
1790 | + if (m_runningApplications[i]->appId() == appId) { |
1791 | + index = i; |
1792 | + } |
1793 | + } |
1794 | + |
1795 | + if (index >= 0) { |
1796 | + if (m_modelBusy) { |
1797 | + DEBUG_MSG(appId << " - model busy. Try again later."); |
1798 | + QMetaObject::invokeMethod(this, "raiseApp", Qt::QueuedConnection, Q_ARG(QString, appId)); |
1799 | + } else { |
1800 | + DEBUG_MSG(appId); |
1801 | + move(index, 0); |
1802 | + } |
1803 | + } |
1804 | } |
1805 | |
1806 | void ApplicationManager::move(int from, int to) { |
1807 | @@ -197,12 +226,15 @@ |
1808 | |
1809 | if (from >= 0 && from < m_runningApplications.size() && to >= 0 && to < m_runningApplications.size()) { |
1810 | QModelIndex parent; |
1811 | + Q_ASSERT(!m_modelBusy); |
1812 | + m_modelBusy = true; |
1813 | /* When moving an item down, the destination index needs to be incremented |
1814 | * by one, as explained in the documentation: |
1815 | * http://qt-project.org/doc/qt-5.0/qtcore/qabstractitemmodel.html#beginMoveRows */ |
1816 | beginMoveRows(parent, from, from, parent, to + (to > from ? 1 : 0)); |
1817 | m_runningApplications.move(from, to); |
1818 | endMoveRows(); |
1819 | + m_modelBusy = false; |
1820 | } |
1821 | } |
1822 | |
1823 | @@ -473,40 +505,6 @@ |
1824 | return m_runningApplications.isEmpty(); |
1825 | } |
1826 | |
1827 | -void ApplicationManager::updateFocusedApplication() |
1828 | -{ |
1829 | - ApplicationInfo *focusedApplication = nullptr; |
1830 | - ApplicationInfo *previouslyFocusedApplication = nullptr; |
1831 | - |
1832 | - auto controller = MirFocusController::instance(); |
1833 | - if (!controller) { |
1834 | - return; |
1835 | - } |
1836 | - |
1837 | - MirSurface *surface = static_cast<MirSurface*>(controller->focusedSurface()); |
1838 | - if (surface) { |
1839 | - focusedApplication = findApplication(surface); |
1840 | - } |
1841 | - |
1842 | - surface = static_cast<MirSurface*>(controller->previouslyFocusedSurface()); |
1843 | - if (surface) { |
1844 | - previouslyFocusedApplication = findApplication(surface); |
1845 | - } |
1846 | - |
1847 | - if (focusedApplication != previouslyFocusedApplication) { |
1848 | - if (focusedApplication) { |
1849 | - DEBUG_MSG("focused " << focusedApplication->appId()); |
1850 | - Q_EMIT focusedApplication->focusedChanged(true); |
1851 | - this->move(this->m_runningApplications.indexOf(focusedApplication), 0); |
1852 | - } |
1853 | - if (previouslyFocusedApplication) { |
1854 | - DEBUG_MSG("unfocused " << previouslyFocusedApplication->appId()); |
1855 | - Q_EMIT previouslyFocusedApplication->focusedChanged(false); |
1856 | - } |
1857 | - Q_EMIT focusedApplicationIdChanged(); |
1858 | - } |
1859 | -} |
1860 | - |
1861 | ApplicationInfo *ApplicationManager::findApplication(MirSurface* surface) |
1862 | { |
1863 | for (ApplicationInfo *app : m_runningApplications) { |
1864 | @@ -517,3 +515,42 @@ |
1865 | } |
1866 | return nullptr; |
1867 | } |
1868 | + |
1869 | +QString ApplicationManager::toString() |
1870 | +{ |
1871 | + QString str; |
1872 | + for (int i = 0; i < m_runningApplications.count(); ++i) { |
1873 | + auto *application = m_runningApplications.at(i); |
1874 | + |
1875 | + QString itemStr = QString("(index=%1,appId=%2)") |
1876 | + .arg(i) |
1877 | + .arg(application->appId()); |
1878 | + |
1879 | + if (i > 0) { |
1880 | + str.append(","); |
1881 | + } |
1882 | + str.append(itemStr); |
1883 | + } |
1884 | + return str; |
1885 | +} |
1886 | + |
1887 | +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
1888 | +// ApplicationManagerNotifier |
1889 | + |
1890 | +ApplicationManagerNotifier *ApplicationManagerNotifier::m_instance = nullptr; |
1891 | + |
1892 | +ApplicationManagerNotifier *ApplicationManagerNotifier::instance() |
1893 | +{ |
1894 | + if (!m_instance) { |
1895 | + m_instance = new ApplicationManagerNotifier; |
1896 | + } |
1897 | + return m_instance; |
1898 | +} |
1899 | + |
1900 | +void ApplicationManagerNotifier::setApplicationManager(ApplicationManager *appMan) |
1901 | +{ |
1902 | + if (appMan != m_applicationManager) { |
1903 | + m_applicationManager = appMan; |
1904 | + Q_EMIT applicationManagerChanged(m_applicationManager); |
1905 | + } |
1906 | +} |
1907 | |
1908 | === modified file 'tests/mocks/Unity/Application/ApplicationManager.h' |
1909 | --- tests/mocks/Unity/Application/ApplicationManager.h 2016-04-27 15:01:10 +0000 |
1910 | +++ tests/mocks/Unity/Application/ApplicationManager.h 2016-11-09 15:21:35 +0000 |
1911 | @@ -77,17 +77,44 @@ |
1912 | |
1913 | private Q_SLOTS: |
1914 | void onWindowCreatedTimerTimeout(); |
1915 | - void updateFocusedApplication(); |
1916 | + void raiseApp(const QString &appId); |
1917 | |
1918 | private: |
1919 | bool add(ApplicationInfo *application); |
1920 | void remove(ApplicationInfo* application); |
1921 | void buildListOfAvailableApplications(); |
1922 | void onWindowCreated(); |
1923 | + QString toString(); |
1924 | ApplicationInfo *findApplication(MirSurface* surface); |
1925 | QList<ApplicationInfo*> m_runningApplications; |
1926 | QList<ApplicationInfo*> m_availableApplications; |
1927 | QTimer m_windowCreatedTimer; |
1928 | + bool m_modelBusy{false}; |
1929 | +}; |
1930 | + |
1931 | +/* |
1932 | + Lifecycle of the ApplicationManager instance belongs to the QML plugin. |
1933 | + So this guy here is used to notify other parts of the system when the plugin creates and destroys |
1934 | + the ApplicationManager. |
1935 | + |
1936 | + Unlike ApplicationManager, we create ApplicationManagerNotifier whenever we want. |
1937 | + */ |
1938 | +class ApplicationManagerNotifier : public QObject { |
1939 | + Q_OBJECT |
1940 | +public: |
1941 | + static ApplicationManagerNotifier *instance(); |
1942 | + |
1943 | + ApplicationManager *applicationManager() { return m_applicationManager; } |
1944 | + |
1945 | +Q_SIGNALS: |
1946 | + void applicationManagerChanged(ApplicationManager *applicationManager); |
1947 | + |
1948 | +private: |
1949 | + void setApplicationManager(ApplicationManager *); |
1950 | + static ApplicationManagerNotifier *m_instance; |
1951 | + ApplicationManager *m_applicationManager{nullptr}; |
1952 | + |
1953 | +friend class ApplicationManager; |
1954 | }; |
1955 | |
1956 | Q_DECLARE_METATYPE(ApplicationManager*) |
1957 | |
1958 | === modified file 'tests/mocks/Unity/Application/CMakeLists.txt' |
1959 | --- tests/mocks/Unity/Application/CMakeLists.txt 2016-06-30 13:51:32 +0000 |
1960 | +++ tests/mocks/Unity/Application/CMakeLists.txt 2016-11-09 15:21:35 +0000 |
1961 | @@ -7,14 +7,17 @@ |
1962 | MirSurfaceListModel.cpp |
1963 | ObjectListModel.h |
1964 | SurfaceManager.cpp |
1965 | + TopLevelWindowModel.cpp |
1966 | VirtualKeyboard.cpp |
1967 | + Window.cpp |
1968 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h |
1969 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h |
1970 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h |
1971 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h |
1972 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceItemInterface.h |
1973 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceListInterface.h |
1974 | - ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirFocusControllerInterface.h |
1975 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/TopLevelWindowModelInterface.h |
1976 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/WindowInterface.h |
1977 | resources/surfaces.qrc |
1978 | ) |
1979 | |
1980 | |
1981 | === modified file 'tests/mocks/Unity/Application/MirSurface.cpp' |
1982 | --- tests/mocks/Unity/Application/MirSurface.cpp 2016-09-26 12:25:19 +0000 |
1983 | +++ tests/mocks/Unity/Application/MirSurface.cpp 2016-11-09 15:21:35 +0000 |
1984 | @@ -26,7 +26,7 @@ |
1985 | |
1986 | const char *stateToStr(Mir::State state) |
1987 | { |
1988 | - switch(state) { |
1989 | + switch (state) { |
1990 | case Mir::UnknownState: |
1991 | return "unknown"; |
1992 | case Mir::RestoredState: |
1993 | @@ -36,16 +36,28 @@ |
1994 | case Mir::MaximizedState: |
1995 | return "maximized"; |
1996 | case Mir::VertMaximizedState: |
1997 | - return "vert-maximized"; |
1998 | + return "vertMaximized"; |
1999 | case Mir::FullscreenState: |
2000 | return "fullscreen"; |
2001 | case Mir::HorizMaximizedState: |
2002 | - return "horiz-maximized"; |
2003 | + return "horizMaximized"; |
2004 | + case Mir::MaximizedLeftState: |
2005 | + return "maximizedLeft"; |
2006 | + case Mir::MaximizedRightState: |
2007 | + return "maximizedRight"; |
2008 | + case Mir::MaximizedTopLeftState: |
2009 | + return "maximizedTopLeft"; |
2010 | + case Mir::MaximizedTopRightState: |
2011 | + return "maximizedTopRight"; |
2012 | + case Mir::MaximizedBottomLeftState: |
2013 | + return "maximizedBottomLeft"; |
2014 | + case Mir::MaximizedBottomRightState: |
2015 | + return "maximizedBottomRight"; |
2016 | case Mir::HiddenState: |
2017 | return "hidden"; |
2018 | default: |
2019 | return "???"; |
2020 | - }; |
2021 | + } |
2022 | } |
2023 | |
2024 | #else |
2025 | @@ -54,8 +66,6 @@ |
2026 | |
2027 | using namespace unity::shell::application; |
2028 | |
2029 | -MirFocusController *MirFocusController::m_instance = nullptr; |
2030 | - |
2031 | MirSurface::MirSurface(const QString& name, |
2032 | Mir::Type type, |
2033 | Mir::State state, |
2034 | @@ -69,7 +79,7 @@ |
2035 | , m_screenshotUrl(screenshot) |
2036 | , m_qmlFilePath(qmlFilePath) |
2037 | , m_live(true) |
2038 | - , m_visible(true) |
2039 | + , m_focused(false) |
2040 | , m_activeFocus(false) |
2041 | , m_width(-1) |
2042 | , m_height(-1) |
2043 | @@ -95,11 +105,8 @@ |
2044 | { |
2045 | DEBUG_MSG(""); |
2046 | |
2047 | - // controller instance might have been already destroyed by QQmlEngine destructor |
2048 | - auto controller = MirFocusController::instance(); |
2049 | - if (controller && controller->focusedSurface() == this) { |
2050 | - controller->clear(); |
2051 | - } |
2052 | + // Early warning, while MirSurface methods can still be accessed. |
2053 | + Q_EMIT destroyed(this); |
2054 | } |
2055 | |
2056 | QString MirSurface::name() const |
2057 | @@ -122,14 +129,30 @@ |
2058 | return m_state; |
2059 | } |
2060 | |
2061 | +void MirSurface::requestState(Mir::State state) |
2062 | +{ |
2063 | + if (state == m_state) { |
2064 | + return; |
2065 | + } |
2066 | + DEBUG_MSG(stateToStr(state)); |
2067 | + Q_EMIT stateRequested(state); |
2068 | +} |
2069 | + |
2070 | void MirSurface::setState(Mir::State state) |
2071 | { |
2072 | - if (state == m_state) |
2073 | + if (state == m_state) { |
2074 | return; |
2075 | - |
2076 | + } |
2077 | DEBUG_MSG(stateToStr(state)); |
2078 | + |
2079 | + bool oldVisible = visible(); |
2080 | + |
2081 | m_state = state; |
2082 | Q_EMIT stateChanged(state); |
2083 | + |
2084 | + if (visible() != oldVisible) { |
2085 | + Q_EMIT visibleChanged(visible()); |
2086 | + } |
2087 | } |
2088 | |
2089 | bool MirSurface::live() const |
2090 | @@ -139,7 +162,7 @@ |
2091 | |
2092 | bool MirSurface::visible() const |
2093 | { |
2094 | - return m_visible; |
2095 | + return m_state != Mir::MinimizedState && m_state != Mir::HiddenState; |
2096 | } |
2097 | |
2098 | void MirSurface::setLive(bool live) |
2099 | @@ -231,31 +254,30 @@ |
2100 | if (!m_live && m_views.count() == 0) { |
2101 | deleteLater(); |
2102 | } |
2103 | - updateVisibility(); |
2104 | + updateExposure(); |
2105 | } |
2106 | |
2107 | -void MirSurface::setViewVisibility(qintptr viewId, bool visible) |
2108 | +void MirSurface::setViewExposure(qintptr viewId, bool visible) |
2109 | { |
2110 | if (!m_views.contains(viewId)) return; |
2111 | |
2112 | m_views[viewId].visible = visible; |
2113 | - updateVisibility(); |
2114 | + updateExposure(); |
2115 | } |
2116 | |
2117 | -void MirSurface::updateVisibility() |
2118 | +void MirSurface::updateExposure() |
2119 | { |
2120 | - bool newVisible = false; |
2121 | + bool newExposure = false; |
2122 | QHashIterator<qintptr, View> i(m_views); |
2123 | while (i.hasNext()) { |
2124 | i.next(); |
2125 | - newVisible |= i.value().visible; |
2126 | + newExposure |= i.value().visible; |
2127 | } |
2128 | |
2129 | - if (newVisible != visible()) { |
2130 | -// qDebug().nospace() << "MirSurface[" << name() << "]::updateVisibility(" << newVisible << ")"; |
2131 | - |
2132 | - m_visible = newVisible; |
2133 | - Q_EMIT visibleChanged(m_visible); |
2134 | + if (newExposure != m_exposed) { |
2135 | + m_exposed = newExposure; |
2136 | + DEBUG_MSG(m_exposed); |
2137 | + Q_EMIT exposedChanged(m_exposed); |
2138 | updateInputBoundsAfterResize(); |
2139 | } |
2140 | } |
2141 | @@ -273,6 +295,10 @@ |
2142 | m_activeFocus = value; |
2143 | |
2144 | Q_EMIT activeFocusChanged(value); |
2145 | + |
2146 | + if (m_activeFocus && !m_focused) { |
2147 | + requestFocus(); |
2148 | + } |
2149 | } |
2150 | |
2151 | int MirSurface::width() const |
2152 | @@ -431,27 +457,18 @@ |
2153 | |
2154 | void MirSurface::setFocused(bool value) |
2155 | { |
2156 | - DEBUG_MSG(value); |
2157 | - |
2158 | - auto controller = MirFocusController::instance(); |
2159 | - // controller instance might have been already destroyed by QQmlEngine destructor |
2160 | - if (!controller) { |
2161 | + if (m_focused == value) |
2162 | return; |
2163 | - } |
2164 | - |
2165 | - if (value) { |
2166 | - controller->setFocusedSurface(this); |
2167 | - } else if (controller->focusedSurface() == this) { |
2168 | - controller->setFocusedSurface(nullptr); |
2169 | - } |
2170 | + |
2171 | + DEBUG_MSG("(" << value << ")"); |
2172 | + |
2173 | + m_focused = value; |
2174 | + Q_EMIT focusedChanged(value); |
2175 | } |
2176 | |
2177 | bool MirSurface::focused() const |
2178 | { |
2179 | - auto controller = MirFocusController::instance(); |
2180 | - |
2181 | - // controller instance might have been already destroyed by QQmlEngine destructor |
2182 | - return controller ? controller->focusedSurface() == this : false; |
2183 | + return m_focused; |
2184 | } |
2185 | |
2186 | QRect MirSurface::inputBounds() const |
2187 | @@ -466,55 +483,15 @@ |
2188 | Q_EMIT inputBoundsChanged(m_inputBounds); |
2189 | } |
2190 | } |
2191 | -#if MIRSURFACE_DEBUG |
2192 | -#undef DEBUG_MSG |
2193 | -#define DEBUG_MSG(params) qDebug().nospace() << "MirFocusController::" << __func__ << " " << params |
2194 | -#endif |
2195 | - |
2196 | -void MirFocusController::setFocusedSurface(MirSurfaceInterface *surface) |
2197 | -{ |
2198 | - if (m_focusedSurface == surface) { |
2199 | - return; |
2200 | - } |
2201 | - DEBUG_MSG("MirSurface[" << (void*)surface << "," << (surface?surface->name():"") << "]"); |
2202 | - |
2203 | - m_previouslyFocusedSurface = m_focusedSurface; |
2204 | - m_focusedSurface = surface; |
2205 | - |
2206 | - if (m_previouslyFocusedSurface != m_focusedSurface) { |
2207 | - Q_EMIT focusedSurfaceChanged(); |
2208 | - } |
2209 | - |
2210 | - if (m_previouslyFocusedSurface) { |
2211 | - Q_EMIT m_previouslyFocusedSurface->focusedChanged(false); |
2212 | - } |
2213 | - |
2214 | - if (m_focusedSurface) { |
2215 | - Q_EMIT m_focusedSurface->focusedChanged(true); |
2216 | - m_focusedSurface->raise(); |
2217 | - } |
2218 | -} |
2219 | - |
2220 | -MirFocusController* MirFocusController::instance() |
2221 | -{ |
2222 | - return m_instance; |
2223 | -} |
2224 | - |
2225 | -MirFocusController::MirFocusController() |
2226 | -{ |
2227 | - DEBUG_MSG(""); |
2228 | - Q_ASSERT(m_instance == nullptr); |
2229 | - m_instance = this; |
2230 | -} |
2231 | - |
2232 | -MirFocusController::~MirFocusController() |
2233 | -{ |
2234 | - Q_ASSERT(m_instance == this); |
2235 | - m_instance = nullptr; |
2236 | -} |
2237 | - |
2238 | -void MirFocusController::clear() |
2239 | -{ |
2240 | - m_focusedSurface = m_previouslyFocusedSurface = nullptr; |
2241 | - Q_EMIT focusedSurfaceChanged(); |
2242 | + |
2243 | +void MirSurface::setRequestedPosition(const QPoint &value) |
2244 | +{ |
2245 | + if (value != m_requestedPosition) { |
2246 | + m_requestedPosition = value; |
2247 | + Q_EMIT requestedPositionChanged(value); |
2248 | + |
2249 | + // fake-miral: always comply |
2250 | + m_position = m_requestedPosition; |
2251 | + Q_EMIT positionChanged(m_position); |
2252 | + } |
2253 | } |
2254 | |
2255 | === modified file 'tests/mocks/Unity/Application/MirSurface.h' |
2256 | --- tests/mocks/Unity/Application/MirSurface.h 2016-09-07 08:50:19 +0000 |
2257 | +++ tests/mocks/Unity/Application/MirSurface.h 2016-11-09 15:21:35 +0000 |
2258 | @@ -23,31 +23,12 @@ |
2259 | #include <QHash> |
2260 | |
2261 | // unity-api |
2262 | -#include <unity/shell/application/MirFocusControllerInterface.h> |
2263 | #include <unity/shell/application/MirSurfaceInterface.h> |
2264 | |
2265 | #include "MirSurfaceListModel.h" |
2266 | |
2267 | class MirSurface; |
2268 | |
2269 | -class MirFocusController : public unity::shell::application::MirFocusControllerInterface |
2270 | -{ |
2271 | - Q_OBJECT |
2272 | -public: |
2273 | - MirFocusController(); |
2274 | - virtual ~MirFocusController(); |
2275 | - static MirFocusController* instance(); |
2276 | - |
2277 | - void setFocusedSurface(unity::shell::application::MirSurfaceInterface *surface) override; |
2278 | - unity::shell::application::MirSurfaceInterface* focusedSurface() const override { return m_focusedSurface; } |
2279 | - unity::shell::application::MirSurfaceInterface* previouslyFocusedSurface() { return m_previouslyFocusedSurface; } |
2280 | - void clear(); |
2281 | -private: |
2282 | - static MirFocusController *m_instance; |
2283 | - unity::shell::application::MirSurfaceInterface* m_previouslyFocusedSurface{nullptr}; |
2284 | - unity::shell::application::MirSurfaceInterface* m_focusedSurface{nullptr}; |
2285 | -}; |
2286 | - |
2287 | class MirSurface : public unity::shell::application::MirSurfaceInterface |
2288 | { |
2289 | Q_OBJECT |
2290 | @@ -58,6 +39,7 @@ |
2291 | Q_PROPERTY(int height READ height NOTIFY heightChanged) |
2292 | Q_PROPERTY(bool activeFocus READ activeFocus NOTIFY activeFocusChanged) |
2293 | Q_PROPERTY(bool slowToResize READ isSlowToResize WRITE setSlowToResize NOTIFY slowToResizeChanged) |
2294 | + Q_PROPERTY(bool exposed READ exposed NOTIFY exposedChanged) |
2295 | |
2296 | public: |
2297 | MirSurface(const QString& name, |
2298 | @@ -76,13 +58,14 @@ |
2299 | |
2300 | QString persistentId() const override; |
2301 | |
2302 | + QPoint position() const override { return m_position; } |
2303 | + |
2304 | QSize size() const override { return QSize(width(),height()); } |
2305 | void resize(int width, int height) override; |
2306 | void resize(const QSize &size) override { resize(size.width(), size.height()); } |
2307 | |
2308 | |
2309 | Mir::State state() const override; |
2310 | - Q_INVOKABLE void setState(Mir::State) override; |
2311 | |
2312 | bool live() const override; |
2313 | |
2314 | @@ -108,6 +91,9 @@ |
2315 | |
2316 | bool confinesMousePointer() const override { return false; } |
2317 | |
2318 | + QPoint requestedPosition() const override { return m_requestedPosition; } |
2319 | + void setRequestedPosition(const QPoint &) override; |
2320 | + |
2321 | Q_INVOKABLE void requestFocus() override; |
2322 | |
2323 | Q_INVOKABLE void close() override; |
2324 | @@ -126,6 +112,8 @@ |
2325 | bool isSlowToResize() const; |
2326 | void setSlowToResize(bool value); |
2327 | |
2328 | + bool exposed() const { return m_exposed; } |
2329 | + |
2330 | Q_INVOKABLE void setMinimumWidth(int); |
2331 | Q_INVOKABLE void setMaximumWidth(int); |
2332 | Q_INVOKABLE void setMinimumHeight(int); |
2333 | @@ -148,17 +136,25 @@ |
2334 | |
2335 | void registerView(qintptr viewId); |
2336 | void unregisterView(qintptr viewId); |
2337 | - void setViewVisibility(qintptr viewId, bool visible); |
2338 | + void setViewExposure(qintptr viewId, bool visible); |
2339 | int viewCount() const { return m_views.count(); } |
2340 | |
2341 | void setFocused(bool value); |
2342 | |
2343 | + void setState(Mir::State state); |
2344 | + |
2345 | +public Q_SLOTS: |
2346 | + //// |
2347 | + // unity.shell.application.MirSurface |
2348 | + void requestState(Mir::State) override; |
2349 | + |
2350 | Q_SIGNALS: |
2351 | //// |
2352 | // API for tests |
2353 | void widthChanged(); |
2354 | void heightChanged(); |
2355 | void slowToResizeChanged(); |
2356 | + void exposedChanged(bool exposed); |
2357 | |
2358 | //// |
2359 | // internal mock stuff |
2360 | @@ -166,6 +162,7 @@ |
2361 | void activeFocusChanged(bool); |
2362 | void raiseRequested(); |
2363 | void closeRequested(); |
2364 | + void stateRequested(Mir::State); |
2365 | |
2366 | protected: |
2367 | virtual void updateInputBoundsAfterResize(); |
2368 | @@ -175,7 +172,7 @@ |
2369 | |
2370 | private: |
2371 | void doResize(int width, int height); |
2372 | - void updateVisibility(); |
2373 | + void updateExposure(); |
2374 | |
2375 | const QString m_name; |
2376 | const Mir::Type m_type; |
2377 | @@ -185,7 +182,7 @@ |
2378 | QUrl m_screenshotUrl; |
2379 | QUrl m_qmlFilePath; |
2380 | bool m_live; |
2381 | - bool m_visible; |
2382 | + bool m_focused; |
2383 | bool m_activeFocus; |
2384 | int m_width; |
2385 | int m_height; |
2386 | @@ -210,10 +207,14 @@ |
2387 | bool visible; |
2388 | }; |
2389 | QHash<qintptr, View> m_views; |
2390 | + bool m_exposed{false}; |
2391 | |
2392 | QTimer m_zombieTimer; |
2393 | |
2394 | QRect m_inputBounds; |
2395 | + |
2396 | + QPoint m_position; |
2397 | + QPoint m_requestedPosition; |
2398 | }; |
2399 | |
2400 | #endif // MOCK_MIR_SURFACE_H |
2401 | |
2402 | === modified file 'tests/mocks/Unity/Application/MirSurfaceItem.cpp' |
2403 | --- tests/mocks/Unity/Application/MirSurfaceItem.cpp 2016-08-23 11:11:32 +0000 |
2404 | +++ tests/mocks/Unity/Application/MirSurfaceItem.cpp 2016-11-09 15:21:35 +0000 |
2405 | @@ -59,7 +59,7 @@ |
2406 | Qt::ExtraButton12 | Qt::ExtraButton13); |
2407 | |
2408 | connect(this, &QQuickItem::activeFocusChanged, this, &MirSurfaceItem::updateMirSurfaceActiveFocus); |
2409 | - connect(this, &QQuickItem::visibleChanged, this, &MirSurfaceItem::updateMirSurfaceVisibility); |
2410 | + connect(this, &QQuickItem::visibleChanged, this, &MirSurfaceItem::updateMirSurfaceExposure); |
2411 | |
2412 | connect(this, &MirSurfaceItem::consumesInputChanged, this, [this]() { |
2413 | updateMirSurfaceActiveFocus(hasActiveFocus()); |
2414 | @@ -278,7 +278,7 @@ |
2415 | m_qmlSurface->registerView((qintptr)this); |
2416 | |
2417 | updateSurfaceSize(); |
2418 | - updateMirSurfaceVisibility(); |
2419 | + updateMirSurfaceExposure(); |
2420 | |
2421 | if (m_orientationAngle) { |
2422 | m_qmlSurface->setOrientationAngle(*m_orientationAngle); |
2423 | @@ -335,11 +335,11 @@ |
2424 | } |
2425 | } |
2426 | |
2427 | -void MirSurfaceItem::updateMirSurfaceVisibility() |
2428 | +void MirSurfaceItem::updateMirSurfaceExposure() |
2429 | { |
2430 | if (!m_qmlSurface) return; |
2431 | |
2432 | - m_qmlSurface->setViewVisibility((qintptr)this, isVisible()); |
2433 | + m_qmlSurface->setViewExposure((qintptr)this, isVisible()); |
2434 | } |
2435 | |
2436 | void MirSurfaceItem::setConsumesInput(bool value) |
2437 | |
2438 | === modified file 'tests/mocks/Unity/Application/MirSurfaceItem.h' |
2439 | --- tests/mocks/Unity/Application/MirSurfaceItem.h 2016-06-22 13:53:00 +0000 |
2440 | +++ tests/mocks/Unity/Application/MirSurfaceItem.h 2016-11-09 15:21:35 +0000 |
2441 | @@ -50,7 +50,6 @@ |
2442 | Mir::ShellChrome shellChrome() const override; |
2443 | |
2444 | Mir::State surfaceState() const override; |
2445 | - void setSurfaceState(Mir::State) override {} |
2446 | |
2447 | Mir::OrientationAngle orientationAngle() const override; |
2448 | void setOrientationAngle(Mir::OrientationAngle angle) override; |
2449 | @@ -102,7 +101,7 @@ |
2450 | private Q_SLOTS: |
2451 | void onComponentStatusChanged(QQmlComponent::Status status); |
2452 | void updateScreenshot(QUrl screenshot); |
2453 | - void updateMirSurfaceVisibility(); |
2454 | + void updateMirSurfaceExposure(); |
2455 | void updateMirSurfaceActiveFocus(bool focused); |
2456 | |
2457 | private: |
2458 | |
2459 | === modified file 'tests/mocks/Unity/Application/MirSurfaceListModel.cpp' |
2460 | --- tests/mocks/Unity/Application/MirSurfaceListModel.cpp 2016-09-23 13:38:46 +0000 |
2461 | +++ tests/mocks/Unity/Application/MirSurfaceListModel.cpp 2016-11-09 15:21:35 +0000 |
2462 | @@ -21,8 +21,9 @@ |
2463 | |
2464 | #define MIRSURFACELISTMODEL_DEBUG 0 |
2465 | |
2466 | -#ifdef MIRSURFACELISTMODEL_DEBUG |
2467 | -#define DEBUG_MSG(params) qDebug().nospace() << "MirSurfaceListModel::" << __func__ << " " << params |
2468 | +#if MIRSURFACELISTMODEL_DEBUG |
2469 | +#include <QDebug> |
2470 | +#define DEBUG_MSG(params) qDebug().nospace() << "MirSurfaceListModel::" << __func__ << params |
2471 | #else |
2472 | #define DEBUG_MSG(params) ((void)0) |
2473 | #endif |
2474 | @@ -54,14 +55,25 @@ |
2475 | |
2476 | void MirSurfaceListModel::raise(MirSurface *surface) |
2477 | { |
2478 | + DEBUG_MSG("(" << surface << ")"); |
2479 | int i = m_surfaceList.indexOf(surface); |
2480 | if (i != -1) { |
2481 | moveSurface(i, 0); |
2482 | } |
2483 | } |
2484 | |
2485 | +void MirSurfaceListModel::addSurface(MirSurface *surface) |
2486 | +{ |
2487 | + if (surface->focused()) { |
2488 | + prependSurface(surface); |
2489 | + } else { |
2490 | + appendSurface(surface); |
2491 | + } |
2492 | +} |
2493 | + |
2494 | void MirSurfaceListModel::appendSurface(MirSurface *surface) |
2495 | { |
2496 | + DEBUG_MSG("(" << surface << ")"); |
2497 | beginInsertRows(QModelIndex(), m_surfaceList.size(), m_surfaceList.size()); |
2498 | m_surfaceList.append(surface); |
2499 | connectSurface(surface); |
2500 | @@ -74,6 +86,7 @@ |
2501 | |
2502 | void MirSurfaceListModel::prependSurface(MirSurface *surface) |
2503 | { |
2504 | + DEBUG_MSG("(" << surface << ")"); |
2505 | beginInsertRows(QModelIndex(), 0, 0); |
2506 | m_surfaceList.prepend(surface); |
2507 | connectSurface(surface); |
2508 | @@ -85,6 +98,11 @@ |
2509 | void MirSurfaceListModel::connectSurface(MirSurface *surface) |
2510 | { |
2511 | connect(surface, &QObject::destroyed, this, [this, surface](){ this->removeSurface(surface); }); |
2512 | + connect(surface, &MirSurfaceInterface::focusedChanged, this, [this, surface](bool surfaceFocused){ |
2513 | + if (surfaceFocused) { |
2514 | + raise(surface); |
2515 | + } |
2516 | + }); |
2517 | } |
2518 | |
2519 | void MirSurfaceListModel::removeSurface(MirSurface *surface) |
2520 | |
2521 | === modified file 'tests/mocks/Unity/Application/MirSurfaceListModel.h' |
2522 | --- tests/mocks/Unity/Application/MirSurfaceListModel.h 2016-06-02 12:02:35 +0000 |
2523 | +++ tests/mocks/Unity/Application/MirSurfaceListModel.h 2016-11-09 15:21:35 +0000 |
2524 | @@ -38,7 +38,7 @@ |
2525 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; |
2526 | QVariant data(const QModelIndex& index, int role) const override; |
2527 | |
2528 | - void appendSurface(MirSurface *surface); |
2529 | + void addSurface(MirSurface *surface); |
2530 | void removeSurface(MirSurface *surface); |
2531 | |
2532 | bool contains(MirSurface *surface) const { return m_surfaceList.contains(surface); } |
2533 | @@ -49,6 +49,7 @@ |
2534 | Q_INVOKABLE unity::shell::application::MirSurfaceInterface *createSurface(); |
2535 | |
2536 | private: |
2537 | + void appendSurface(MirSurface *surface); |
2538 | void prependSurface(MirSurface *surface); |
2539 | void raise(MirSurface *surface); |
2540 | void moveSurface(int from, int to); |
2541 | |
2542 | === modified file 'tests/mocks/Unity/Application/SurfaceManager.cpp' |
2543 | --- tests/mocks/Unity/Application/SurfaceManager.cpp 2016-04-27 15:01:10 +0000 |
2544 | +++ tests/mocks/Unity/Application/SurfaceManager.cpp 2016-11-09 15:21:35 +0000 |
2545 | @@ -21,19 +21,19 @@ |
2546 | |
2547 | #include <paths.h> |
2548 | |
2549 | -SurfaceManager *SurfaceManager::the_surface_manager = nullptr; |
2550 | +SurfaceManager *SurfaceManager::m_instance = nullptr; |
2551 | |
2552 | SurfaceManager *SurfaceManager::instance() |
2553 | { |
2554 | - return the_surface_manager; |
2555 | + return m_instance; |
2556 | } |
2557 | |
2558 | SurfaceManager::SurfaceManager(QObject *parent) : |
2559 | QObject(parent) |
2560 | , m_virtualKeyboard(nullptr) |
2561 | { |
2562 | - Q_ASSERT(the_surface_manager == nullptr); |
2563 | - the_surface_manager = this; |
2564 | + Q_ASSERT(m_instance == nullptr); |
2565 | + m_instance = this; |
2566 | |
2567 | m_virtualKeyboard = new VirtualKeyboard; |
2568 | connect(m_virtualKeyboard, &QObject::destroyed, this, [this](QObject *obj) { |
2569 | @@ -46,14 +46,15 @@ |
2570 | |
2571 | SurfaceManager::~SurfaceManager() |
2572 | { |
2573 | - Q_ASSERT(the_surface_manager == this); |
2574 | - the_surface_manager = nullptr; |
2575 | + Q_ASSERT(m_instance == this); |
2576 | + m_instance = nullptr; |
2577 | } |
2578 | |
2579 | MirSurface *SurfaceManager::createSurface(const QString& name, |
2580 | Mir::Type type, |
2581 | Mir::State state, |
2582 | - const QUrl& screenshot) |
2583 | + const QUrl& screenshot, |
2584 | + ApplicationInfo *application) |
2585 | { |
2586 | MirSurface* surface = new MirSurface(name, type, state, screenshot); |
2587 | connect(surface, &QObject::destroyed, this, [this](QObject *obj) { |
2588 | @@ -68,7 +69,7 @@ |
2589 | surface->setWidthIncrement(m_newSurfaceWidthIncrement); |
2590 | surface->setHeightIncrement(m_newSurfaceHeightIncrement); |
2591 | |
2592 | - Q_EMIT surfaceCreated(surface); |
2593 | + Q_EMIT surfaceCreated(surface, application); |
2594 | return surface; |
2595 | } |
2596 | |
2597 | |
2598 | === modified file 'tests/mocks/Unity/Application/SurfaceManager.h' |
2599 | --- tests/mocks/Unity/Application/SurfaceManager.h 2016-04-13 18:33:15 +0000 |
2600 | +++ tests/mocks/Unity/Application/SurfaceManager.h 2016-11-09 15:21:35 +0000 |
2601 | @@ -44,7 +44,8 @@ |
2602 | Q_INVOKABLE MirSurface* createSurface(const QString& name, |
2603 | Mir::Type type, |
2604 | Mir::State state, |
2605 | - const QUrl& screenshot); |
2606 | + const QUrl& screenshot, |
2607 | + ApplicationInfo *application); |
2608 | |
2609 | MirSurface* inputMethodSurface() const; |
2610 | |
2611 | @@ -69,7 +70,7 @@ |
2612 | Q_SIGNALS: |
2613 | void inputMethodSurfaceChanged(); |
2614 | void countChanged(); |
2615 | - void surfaceCreated(MirSurface *surface); |
2616 | + void surfaceCreated(MirSurface *surface, ApplicationInfo *application); |
2617 | void surfaceDestroyed(MirSurface*surface); |
2618 | |
2619 | void newSurfaceMinimumWidthChanged(int value); |
2620 | @@ -80,7 +81,7 @@ |
2621 | void newSurfaceHeightIncrementChanged(int value); |
2622 | |
2623 | private: |
2624 | - static SurfaceManager *the_surface_manager; |
2625 | + static SurfaceManager *m_instance; |
2626 | VirtualKeyboard *m_virtualKeyboard; |
2627 | |
2628 | int m_newSurfaceMinimumWidth{0}; |
2629 | |
2630 | === added file 'tests/mocks/Unity/Application/TopLevelWindowModel.cpp' |
2631 | --- tests/mocks/Unity/Application/TopLevelWindowModel.cpp 1970-01-01 00:00:00 +0000 |
2632 | +++ tests/mocks/Unity/Application/TopLevelWindowModel.cpp 2016-11-09 15:21:35 +0000 |
2633 | @@ -0,0 +1,610 @@ |
2634 | +/* |
2635 | + * Copyright (C) 2016 Canonical, Ltd. |
2636 | + * |
2637 | + * This program is free software; you can redistribute it and/or modify |
2638 | + * it under the terms of the GNU General Public License as published by |
2639 | + * the Free Software Foundation; version 3. |
2640 | + * |
2641 | + * This program is distributed in the hope that it will be useful, |
2642 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2643 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2644 | + * GNU General Public License for more details. |
2645 | + * |
2646 | + * You should have received a copy of the GNU General Public License |
2647 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2648 | + */ |
2649 | + |
2650 | +#include "TopLevelWindowModel.h" |
2651 | + |
2652 | +#include "SurfaceManager.h" |
2653 | + |
2654 | +Q_LOGGING_CATEGORY(TOPLEVELWINDOWMODEL, "toplevelwindowmodel", QtWarningMsg) |
2655 | + |
2656 | +#define DEBUG_MSG qCDebug(TOPLEVELWINDOWMODEL).nospace().noquote() << __func__ |
2657 | + |
2658 | +namespace unityapi = unity::shell::application; |
2659 | + |
2660 | +TopLevelWindowModel::TopLevelWindowModel() |
2661 | +{ |
2662 | + DEBUG_MSG; |
2663 | + auto *appManNotifier = ApplicationManagerNotifier::instance(); |
2664 | + |
2665 | + if (appManNotifier->applicationManager()) { |
2666 | + setApplicationManager(appManNotifier->applicationManager()); |
2667 | + } else { |
2668 | + connect(appManNotifier, &ApplicationManagerNotifier::applicationManagerChanged, |
2669 | + this, &TopLevelWindowModel::setApplicationManager); |
2670 | + } |
2671 | +} |
2672 | + |
2673 | +TopLevelWindowModel::~TopLevelWindowModel() |
2674 | +{ |
2675 | + DEBUG_MSG; |
2676 | +} |
2677 | + |
2678 | +unityapi::MirSurfaceInterface* TopLevelWindowModel::inputMethodSurface() const |
2679 | +{ |
2680 | + return m_inputMethodWindow ? m_inputMethodWindow->surface() : nullptr; |
2681 | +} |
2682 | + |
2683 | +void TopLevelWindowModel::connectSurfaceManager() |
2684 | +{ |
2685 | + if (m_connectedSurfaceManager) |
2686 | + return; |
2687 | + |
2688 | + auto surfaceManager = SurfaceManager::instance(); |
2689 | + Q_ASSERT(surfaceManager != nullptr); |
2690 | + |
2691 | + setInputMethodSurface(surfaceManager->inputMethodSurface()); |
2692 | + |
2693 | + connect(surfaceManager, &SurfaceManager::inputMethodSurfaceChanged, |
2694 | + this, [&]() { |
2695 | + setInputMethodSurface(surfaceManager->inputMethodSurface()); |
2696 | + }); |
2697 | + |
2698 | + connect(surfaceManager, &SurfaceManager::surfaceCreated, |
2699 | + this, &TopLevelWindowModel::prependSurface); |
2700 | + |
2701 | + m_connectedSurfaceManager = true; |
2702 | +} |
2703 | + |
2704 | +void TopLevelWindowModel::setApplicationManager(ApplicationManager* value) |
2705 | +{ |
2706 | + if (m_applicationManager == value) { |
2707 | + return; |
2708 | + } |
2709 | + |
2710 | + Q_ASSERT(m_modelState == IdleState); |
2711 | + m_modelState = ResettingState; |
2712 | + |
2713 | + beginResetModel(); |
2714 | + |
2715 | + if (m_applicationManager) { |
2716 | + m_windowModel.clear(); |
2717 | + disconnect(m_applicationManager, 0, this, 0); |
2718 | + } |
2719 | + |
2720 | + m_applicationManager = value; |
2721 | + |
2722 | + if (m_applicationManager) { |
2723 | + // we're in business! |
2724 | + connectSurfaceManager(); |
2725 | + |
2726 | + connect(m_applicationManager, &QAbstractItemModel::rowsInserted, |
2727 | + this, [this](const QModelIndex &/*parent*/, int first, int last) { |
2728 | + for (int i = first; i <= last; ++i) { |
2729 | + auto application = m_applicationManager->get(i); |
2730 | + addApplication(static_cast<ApplicationInfo*>(application)); |
2731 | + } |
2732 | + }); |
2733 | + |
2734 | + connect(m_applicationManager, &QAbstractItemModel::rowsAboutToBeRemoved, |
2735 | + this, [this](const QModelIndex &/*parent*/, int first, int last) { |
2736 | + for (int i = first; i <= last; ++i) { |
2737 | + auto application = m_applicationManager->get(i); |
2738 | + removeApplication(static_cast<ApplicationInfo*>(application)); |
2739 | + } |
2740 | + // fake-miral |
2741 | + // Do it after ApplicationManager has finished changing its model |
2742 | + QMetaObject::invokeMethod(this, "focusTopMostAvailableWindow", Qt::QueuedConnection); |
2743 | + }); |
2744 | + |
2745 | + for (int i = 0; i < m_applicationManager->rowCount(); ++i) { |
2746 | + auto application = m_applicationManager->get(i); |
2747 | + addApplication(static_cast<ApplicationInfo*>(application)); |
2748 | + } |
2749 | + } |
2750 | + |
2751 | + endResetModel(); |
2752 | + m_modelState = IdleState; |
2753 | +} |
2754 | + |
2755 | +void TopLevelWindowModel::focusTopMostAvailableWindow() |
2756 | +{ |
2757 | + DEBUG_MSG << "()"; |
2758 | + setFocusedWindow(findFocusableWindow(0)); |
2759 | +} |
2760 | + |
2761 | +void TopLevelWindowModel::addApplication(ApplicationInfo *application) |
2762 | +{ |
2763 | + DEBUG_MSG << "(" << application->appId() << ")"; |
2764 | + |
2765 | + if (application->state() != unityapi::ApplicationInfoInterface::Stopped && application->surfaceList()->count() == 0) { |
2766 | + prependPlaceholder(application); |
2767 | + } else { |
2768 | + auto *surfaceList = application->surfaceList(); |
2769 | + for (int i = 0; i < surfaceList->count(); ++i) { |
2770 | + prependSurface(static_cast<MirSurface*>(surfaceList->get(i)), application); |
2771 | + } |
2772 | + } |
2773 | +} |
2774 | + |
2775 | +void TopLevelWindowModel::removeApplication(ApplicationInfo *application) |
2776 | +{ |
2777 | + DEBUG_MSG << "(" << application->appId() << ")"; |
2778 | + |
2779 | + Q_ASSERT(m_modelState == IdleState); |
2780 | + |
2781 | + int i = 0; |
2782 | + while (i < m_windowModel.count()) { |
2783 | + if (m_windowModel.at(i).application == application) { |
2784 | + removeAt(i); |
2785 | + } else { |
2786 | + ++i; |
2787 | + } |
2788 | + } |
2789 | + |
2790 | + DEBUG_MSG << " after " << toString(); |
2791 | +} |
2792 | + |
2793 | +void TopLevelWindowModel::prependPlaceholder(ApplicationInfo *application) |
2794 | +{ |
2795 | + DEBUG_MSG << "(" << application->appId() << ")"; |
2796 | + |
2797 | + prependSurfaceHelper(nullptr, application); |
2798 | +} |
2799 | + |
2800 | +void TopLevelWindowModel::prependSurface(MirSurface *surface, ApplicationInfo *application) |
2801 | +{ |
2802 | + Q_ASSERT(surface != nullptr); |
2803 | + |
2804 | + bool filledPlaceholder = false; |
2805 | + for (int i = 0; i < m_windowModel.count() && !filledPlaceholder; ++i) { |
2806 | + ModelEntry &entry = m_windowModel[i]; |
2807 | + if (entry.application == application && entry.window->surface() == nullptr) { |
2808 | + // fake-miral: focus the newly added surface |
2809 | + if (entry.window->focused()) { |
2810 | + surface->setFocused(true); |
2811 | + } |
2812 | + |
2813 | + entry.window->setSurface(surface); |
2814 | + connectSurface(surface); |
2815 | + DEBUG_MSG << " appId=" << application->appId() << " surface=" << surface |
2816 | + << ", filling out placeholder. after: " << toString(); |
2817 | + filledPlaceholder = true; |
2818 | + } |
2819 | + } |
2820 | + |
2821 | + if (!filledPlaceholder) { |
2822 | + DEBUG_MSG << " appId=" << application->appId() << " surface=" << surface << ", adding new row"; |
2823 | + prependSurfaceHelper(surface, application); |
2824 | + } |
2825 | +} |
2826 | + |
2827 | +void TopLevelWindowModel::prependSurfaceHelper(MirSurface *surface, ApplicationInfo *application) |
2828 | +{ |
2829 | + if (m_modelState == IdleState) { |
2830 | + m_modelState = InsertingState; |
2831 | + beginInsertRows(QModelIndex(), 0 /*first*/, 0 /*last*/); |
2832 | + } else { |
2833 | + Q_ASSERT(m_modelState == ResettingState); |
2834 | + // No point in signaling anything if we're resetting the whole model |
2835 | + } |
2836 | + |
2837 | + int id = generateId(); |
2838 | + Window *window = new Window(id); |
2839 | + if (surface) { |
2840 | + window->setSurface(surface); |
2841 | + } |
2842 | + m_windowModel.prepend(ModelEntry(window, application)); |
2843 | + if (surface) { |
2844 | + connectSurface(surface); |
2845 | + } |
2846 | + |
2847 | + connect(window, &WindowInterface::focusRequested, this, [this, window]() { |
2848 | + // fake-miral: just comply |
2849 | + setFocusedWindow(window); |
2850 | + }); |
2851 | + |
2852 | + connect(window, &Window::closeRequested, this, [this, window]() { |
2853 | + onWindowCloseRequested(window); |
2854 | + }); |
2855 | + |
2856 | + connect(window, &Window::stateRequested, this, [this, window](Mir::State requestedState) { |
2857 | + onStateChangeRequested(window, requestedState); |
2858 | + }); |
2859 | + |
2860 | + if (m_modelState == InsertingState) { |
2861 | + endInsertRows(); |
2862 | + Q_EMIT countChanged(); |
2863 | + Q_EMIT listChanged(); |
2864 | + m_modelState = IdleState; |
2865 | + } |
2866 | + |
2867 | + // fake-miral: focus the newly added window |
2868 | + setFocusedWindow(window); |
2869 | + |
2870 | + DEBUG_MSG << " after " << toString(); |
2871 | +} |
2872 | + |
2873 | +void TopLevelWindowModel::onWindowCloseRequested(Window *window) |
2874 | +{ |
2875 | + if (!window->surface()) { |
2876 | + int index = indexOf(window); |
2877 | + Q_ASSERT(index >= 0); |
2878 | + m_windowModel[index].application->close(); |
2879 | + } |
2880 | +} |
2881 | + |
2882 | +void TopLevelWindowModel::connectSurface(MirSurface *surface) |
2883 | +{ |
2884 | + connect(surface, &MirSurfaceInterface::liveChanged, this, [this, surface](bool live){ |
2885 | + if (!live) { |
2886 | + onSurfaceDied(surface); |
2887 | + } |
2888 | + }); |
2889 | + |
2890 | + connect(surface, &QObject::destroyed, this, [this, surface](){ this->onSurfaceDestroyed(surface); }); |
2891 | +} |
2892 | + |
2893 | +void TopLevelWindowModel::onStateChangeRequested(Window *window, Mir::State requestedState) |
2894 | +{ |
2895 | + if (requestedState == window->state()) { |
2896 | + return; |
2897 | + } |
2898 | + |
2899 | + // fake-miral |
2900 | + |
2901 | + window->setState(requestedState); |
2902 | + |
2903 | + if (requestedState == Mir::MinimizedState) { |
2904 | + if (m_focusedWindow && m_focusedWindow == window) { |
2905 | + setFocusedWindow(findFocusableWindow(indexOf(window)+1)); |
2906 | + } |
2907 | + } else if (window->state() == Mir::MinimizedState || window->state() == Mir::HiddenState) { |
2908 | + if (requestedState != Mir::MinimizedState && requestedState != Mir::HiddenState) { |
2909 | + setFocusedWindow(window); |
2910 | + } |
2911 | + } |
2912 | +} |
2913 | + |
2914 | +Window *TopLevelWindowModel::findFocusableWindow(int index) |
2915 | +{ |
2916 | + Q_ASSERT(index >= 0); |
2917 | + |
2918 | + // the simplest thing possible. this is a fake implementation afterall |
2919 | + if (index < m_windowModel.count()) { |
2920 | + auto candidate = m_windowModel[index].window; |
2921 | + if (candidate->state() != Mir::MinimizedState && candidate->state() != Mir::HiddenState) { |
2922 | + return candidate; |
2923 | + } else { |
2924 | + return findFocusableWindow(index + 1); |
2925 | + } |
2926 | + } else { |
2927 | + return nullptr; |
2928 | + } |
2929 | +} |
2930 | + |
2931 | +void TopLevelWindowModel::onSurfaceDied(MirSurfaceInterface *surface) |
2932 | +{ |
2933 | + int i = indexOf(surface); |
2934 | + if (i == -1) { |
2935 | + return; |
2936 | + } |
2937 | + |
2938 | + auto application = m_windowModel[i].application; |
2939 | + |
2940 | + // can't be starting if it already has a surface |
2941 | + Q_ASSERT(application->state() != unityapi::ApplicationInfoInterface::Starting); |
2942 | + |
2943 | + if (application->state() == unityapi::ApplicationInfoInterface::Running) { |
2944 | + m_windowModel[i].removeOnceSurfaceDestroyed = true; |
2945 | + } else { |
2946 | + // assume it got killed by the out-of-memory daemon. |
2947 | + // |
2948 | + // So leave entry in the model and only remove its surface, so shell can display a screenshot |
2949 | + // in its place. |
2950 | + m_windowModel[i].removeOnceSurfaceDestroyed = false; |
2951 | + } |
2952 | +} |
2953 | + |
2954 | +void TopLevelWindowModel::onSurfaceDestroyed(MirSurfaceInterface *surface) |
2955 | +{ |
2956 | + int i = indexOf(surface); |
2957 | + if (i == -1) { |
2958 | + return; |
2959 | + } |
2960 | + |
2961 | + if (m_windowModel[i].removeOnceSurfaceDestroyed) { |
2962 | + removeAt(i); |
2963 | + } else { |
2964 | + m_windowModel[i].window->setSurface(nullptr); |
2965 | + DEBUG_MSG << " Removed surface from entry. After: " << toString(); |
2966 | + } |
2967 | + |
2968 | + disconnect(surface, 0, this, 0); |
2969 | +} |
2970 | + |
2971 | +void TopLevelWindowModel::removeAt(int index) |
2972 | +{ |
2973 | + Q_ASSERT(index >= 0 && index < m_windowModel.count()); |
2974 | + |
2975 | + if (m_modelState == IdleState) { |
2976 | + beginRemoveRows(QModelIndex(), index, index); |
2977 | + m_modelState = RemovingState; |
2978 | + } else { |
2979 | + Q_ASSERT(m_modelState == ResettingState); |
2980 | + // No point in signaling anything if we're resetting the whole model |
2981 | + } |
2982 | + |
2983 | + auto window = m_windowModel[index].window; |
2984 | + if (window == focusedWindow()) { |
2985 | + setFocusedWindow(nullptr); |
2986 | + } |
2987 | + |
2988 | + m_windowModel.removeAt(index); |
2989 | + |
2990 | + delete window; |
2991 | + |
2992 | + if (m_modelState == RemovingState) { |
2993 | + endRemoveRows(); |
2994 | + Q_EMIT countChanged(); |
2995 | + Q_EMIT listChanged(); |
2996 | + m_modelState = IdleState; |
2997 | + } |
2998 | + |
2999 | + DEBUG_MSG << " after " << toString(); |
3000 | +} |
3001 | + |
3002 | +void TopLevelWindowModel::setInputMethodSurface(MirSurface *surface) |
3003 | +{ |
3004 | + if (m_inputMethodWindow) { |
3005 | + qDebug("Multiple Input Method Surfaces created, removing the old one!"); |
3006 | + delete m_inputMethodWindow; |
3007 | + } |
3008 | + m_inputMethodWindow = new Window(generateId()); |
3009 | + m_inputMethodWindow->setSurface(surface); |
3010 | + if (surface) { |
3011 | + connectSurface(surface); |
3012 | + } |
3013 | + Q_EMIT inputMethodSurfaceChanged(m_inputMethodWindow->surface()); |
3014 | +} |
3015 | + |
3016 | +void TopLevelWindowModel::removeInputMethodWindow() |
3017 | +{ |
3018 | + if (m_inputMethodWindow) { |
3019 | + delete m_inputMethodWindow; |
3020 | + m_inputMethodWindow = nullptr; |
3021 | + Q_EMIT inputMethodSurfaceChanged(nullptr); |
3022 | + } |
3023 | +} |
3024 | + |
3025 | +int TopLevelWindowModel::rowCount(const QModelIndex &/*parent*/) const |
3026 | +{ |
3027 | + return m_windowModel.count(); |
3028 | +} |
3029 | + |
3030 | +QVariant TopLevelWindowModel::data(const QModelIndex& index, int role) const |
3031 | +{ |
3032 | + if (index.row() < 0 || index.row() >= m_windowModel.size()) |
3033 | + return QVariant(); |
3034 | + |
3035 | + if (role == WindowRole) { |
3036 | + unityapi::WindowInterface *window = m_windowModel.at(index.row()).window; |
3037 | + return QVariant::fromValue(window); |
3038 | + } else if (role == ApplicationRole) { |
3039 | + return QVariant::fromValue(m_windowModel.at(index.row()).application); |
3040 | + } else { |
3041 | + return QVariant(); |
3042 | + } |
3043 | +} |
3044 | + |
3045 | +int TopLevelWindowModel::generateId() |
3046 | +{ |
3047 | + int id = m_nextId; |
3048 | + m_nextId = nextFreeId(m_nextId + 1); |
3049 | + Q_EMIT nextIdChanged(); |
3050 | + return id; |
3051 | +} |
3052 | + |
3053 | +int TopLevelWindowModel::nextFreeId(int candidateId) |
3054 | +{ |
3055 | + if (candidateId > m_maxId) { |
3056 | + return nextFreeId(1); |
3057 | + } else { |
3058 | + if (indexForId(candidateId) == -1) { |
3059 | + // it's indeed free |
3060 | + return candidateId; |
3061 | + } else { |
3062 | + return nextFreeId(candidateId + 1); |
3063 | + } |
3064 | + } |
3065 | +} |
3066 | + |
3067 | +QString TopLevelWindowModel::toString() |
3068 | +{ |
3069 | + QString str; |
3070 | + for (int i = 0; i < m_windowModel.count(); ++i) { |
3071 | + auto item = m_windowModel.at(i); |
3072 | + |
3073 | + QString itemStr = QString("(index=%1,appId=%2,surface=0x%3,id=%4)") |
3074 | + .arg(i) |
3075 | + .arg(item.application->appId()) |
3076 | + .arg((qintptr)item.window->surface(), 0, 16) |
3077 | + .arg(item.window->id()); |
3078 | + |
3079 | + if (i > 0) { |
3080 | + str.append(","); |
3081 | + } |
3082 | + str.append(itemStr); |
3083 | + } |
3084 | + return str; |
3085 | +} |
3086 | + |
3087 | +int TopLevelWindowModel::indexOf(WindowInterface *window) |
3088 | +{ |
3089 | + for (int i = 0; i < m_windowModel.count(); ++i) { |
3090 | + if (m_windowModel.at(i).window == window) { |
3091 | + return i; |
3092 | + } |
3093 | + } |
3094 | + return -1; |
3095 | +} |
3096 | + |
3097 | +int TopLevelWindowModel::indexOf(MirSurfaceInterface *surface) |
3098 | +{ |
3099 | + for (int i = 0; i < m_windowModel.count(); ++i) { |
3100 | + if (m_windowModel.at(i).window->surface() == surface) { |
3101 | + return i; |
3102 | + } |
3103 | + } |
3104 | + return -1; |
3105 | +} |
3106 | + |
3107 | +int TopLevelWindowModel::indexForId(int id) const |
3108 | +{ |
3109 | + for (int i = 0; i < m_windowModel.count(); ++i) { |
3110 | + if (m_windowModel[i].window->id() == id) { |
3111 | + return i; |
3112 | + } |
3113 | + } |
3114 | + return -1; |
3115 | +} |
3116 | + |
3117 | +unityapi::WindowInterface *TopLevelWindowModel::windowAt(int index) const |
3118 | +{ |
3119 | + if (index >=0 && index < m_windowModel.count()) { |
3120 | + return m_windowModel[index].window; |
3121 | + } else { |
3122 | + return nullptr; |
3123 | + } |
3124 | +} |
3125 | + |
3126 | +unityapi::MirSurfaceInterface *TopLevelWindowModel::surfaceAt(int index) const |
3127 | +{ |
3128 | + auto window = windowAt(index); |
3129 | + return window ? window->surface() : nullptr; |
3130 | +} |
3131 | + |
3132 | +unityapi::ApplicationInfoInterface *TopLevelWindowModel::applicationAt(int index) const |
3133 | +{ |
3134 | + if (index >=0 && index < m_windowModel.count()) { |
3135 | + return m_windowModel[index].application; |
3136 | + } else { |
3137 | + return nullptr; |
3138 | + } |
3139 | +} |
3140 | + |
3141 | +int TopLevelWindowModel::idAt(int index) const |
3142 | +{ |
3143 | + if (index >=0 && index < m_windowModel.count()) { |
3144 | + return m_windowModel[index].window->id(); |
3145 | + } else { |
3146 | + return 0; |
3147 | + } |
3148 | +} |
3149 | + |
3150 | +void TopLevelWindowModel::raiseId(int id) |
3151 | +{ |
3152 | + if (m_modelState == IdleState) { |
3153 | + DEBUG_MSG << "(id=" << id << ") - do it now."; |
3154 | + doRaiseId(id); |
3155 | + } else { |
3156 | + DEBUG_MSG << "(id=" << id << ") - Model busy (modelState=" << m_modelState << "). Try again in the next event loop."; |
3157 | + // The model has just signalled some change. If we have a Repeater responding to this update, it will get nuts |
3158 | + // if we perform yet another model change straight away. |
3159 | + // |
3160 | + // A bad sympton of this problem is a Repeater.itemAt(index) call returning null event though Repeater.count says |
3161 | + // the index is definitely within bounds. |
3162 | + QMetaObject::invokeMethod(this, "raiseId", Qt::QueuedConnection, Q_ARG(int, id)); |
3163 | + } |
3164 | +} |
3165 | + |
3166 | +void TopLevelWindowModel::doRaiseId(int id) |
3167 | +{ |
3168 | + int fromIndex = indexForId(id); |
3169 | + if (fromIndex != -1) { |
3170 | + move(fromIndex, 0); |
3171 | + } |
3172 | +} |
3173 | + |
3174 | +Window *TopLevelWindowModel::findWindowWithSurface(MirSurface *surface) |
3175 | +{ |
3176 | + for (int i = 0; i < m_windowModel.count(); ++i) { |
3177 | + Window *window = m_windowModel[i].window; |
3178 | + if (window->surface() == surface) { |
3179 | + return window; |
3180 | + } |
3181 | + } |
3182 | + return nullptr; |
3183 | +} |
3184 | + |
3185 | +void TopLevelWindowModel::setFocusedWindow(Window *window) |
3186 | +{ |
3187 | + if (window != m_focusedWindow) { |
3188 | + DEBUG_MSG << "(" << (window ? window->toString() : "null") << ")"; |
3189 | + |
3190 | + Window* previousWindow = m_focusedWindow; |
3191 | + |
3192 | + // fake-miral: restore window if needed |
3193 | + if (window && (window->state() == Mir::MinimizedState || window->state() == Mir::HiddenState)) { |
3194 | + window->setState(Mir::RestoredState); |
3195 | + } |
3196 | + |
3197 | + m_focusedWindow = window; |
3198 | + Q_EMIT focusedWindowChanged(m_focusedWindow); |
3199 | + |
3200 | + if (previousWindow) { |
3201 | + // fake-miral |
3202 | + previousWindow->setFocused(false); |
3203 | + } |
3204 | + |
3205 | + if (m_focusedWindow) { |
3206 | + // fake-miral |
3207 | + m_focusedWindow->setFocused(true); |
3208 | + raiseId(m_focusedWindow->id()); |
3209 | + } |
3210 | + } |
3211 | +} |
3212 | + |
3213 | +unityapi::WindowInterface* TopLevelWindowModel::focusedWindow() const |
3214 | +{ |
3215 | + return m_focusedWindow; |
3216 | +} |
3217 | + |
3218 | +void TopLevelWindowModel::move(int from, int to) |
3219 | +{ |
3220 | + if (from == to) return; |
3221 | + DEBUG_MSG << " from=" << from << " to=" << to; |
3222 | + |
3223 | + if (from >= 0 && from < m_windowModel.size() && to >= 0 && to < m_windowModel.size()) { |
3224 | + QModelIndex parent; |
3225 | + /* When moving an item down, the destination index needs to be incremented |
3226 | + by one, as explained in the documentation: |
3227 | + http://qt-project.org/doc/qt-5.0/qtcore/qabstractitemmodel.html#beginMoveRows */ |
3228 | + |
3229 | + Q_ASSERT(m_modelState == IdleState); |
3230 | + m_modelState = MovingState; |
3231 | + |
3232 | + beginMoveRows(parent, from, from, parent, to + (to > from ? 1 : 0)); |
3233 | + ModelEntry entry = m_windowModel.takeAt(from); |
3234 | + m_windowModel.insert(to, entry); |
3235 | + endMoveRows(); |
3236 | + |
3237 | + m_modelState = IdleState; |
3238 | + |
3239 | + DEBUG_MSG << " after " << toString(); |
3240 | + |
3241 | + Q_EMIT listChanged(); |
3242 | + } |
3243 | +} |
3244 | |
3245 | === added file 'tests/mocks/Unity/Application/TopLevelWindowModel.h' |
3246 | --- tests/mocks/Unity/Application/TopLevelWindowModel.h 1970-01-01 00:00:00 +0000 |
3247 | +++ tests/mocks/Unity/Application/TopLevelWindowModel.h 2016-11-09 15:21:35 +0000 |
3248 | @@ -0,0 +1,146 @@ |
3249 | +/* |
3250 | + * Copyright (C) 2016 Canonical, Ltd. |
3251 | + * |
3252 | + * This program is free software; you can redistribute it and/or modify |
3253 | + * it under the terms of the GNU General Public License as published by |
3254 | + * the Free Software Foundation; version 3. |
3255 | + * |
3256 | + * This program is distributed in the hope that it will be useful, |
3257 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3258 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3259 | + * GNU General Public License for more details. |
3260 | + * |
3261 | + * You should have received a copy of the GNU General Public License |
3262 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3263 | + */ |
3264 | + |
3265 | +#pragma once |
3266 | + |
3267 | +#include <QLoggingCategory> |
3268 | + |
3269 | +#include "ApplicationManager.h" |
3270 | + |
3271 | +// unity-api |
3272 | +#include <unity/shell/application/TopLevelWindowModelInterface.h> |
3273 | + |
3274 | +// local |
3275 | +#include "Window.h" |
3276 | + |
3277 | +Q_DECLARE_LOGGING_CATEGORY(TOPLEVELWINDOWMODEL) |
3278 | + |
3279 | +/* |
3280 | + This is a copy of TopLevelWindowModel from qtmir (the real deal) with some small changes. |
3281 | + |
3282 | + Yes, this code duplication sucks |
3283 | + |
3284 | + IDEA: Move as much as possible of the implementation to TopLevelWindowModelInterface.h |
3285 | + in unity-api |
3286 | +*/ |
3287 | +class TopLevelWindowModel : public unity::shell::application::TopLevelWindowModelInterface |
3288 | +{ |
3289 | + Q_OBJECT |
3290 | + |
3291 | + /** |
3292 | + The id to be used on the next entry created |
3293 | + Useful for tests |
3294 | + */ |
3295 | + Q_PROPERTY(int nextId READ nextId NOTIFY nextIdChanged) |
3296 | + |
3297 | +public: |
3298 | + TopLevelWindowModel(); |
3299 | + virtual ~TopLevelWindowModel(); |
3300 | + |
3301 | + // From unity::shell::aplication::TopLevelWindowModelInterface |
3302 | + unity::shell::application::MirSurfaceInterface* inputMethodSurface() const override; |
3303 | + unity::shell::application::WindowInterface* focusedWindow() const override; |
3304 | + |
3305 | + // From QAbstractItemModel |
3306 | + int rowCount(const QModelIndex &parent = QModelIndex()) const override; |
3307 | + QVariant data(const QModelIndex& index, int role) const override; |
3308 | + |
3309 | + // Own API |
3310 | + int nextId() const { return m_nextId; } |
3311 | + |
3312 | +public Q_SLOTS: |
3313 | + // From unity::shell::aplication::TopLevelWindowModelInterface |
3314 | + unity::shell::application::MirSurfaceInterface *surfaceAt(int index) const override; |
3315 | + unity::shell::application::WindowInterface *windowAt(int index) const override; |
3316 | + unity::shell::application::ApplicationInfoInterface *applicationAt(int index) const override; |
3317 | + int idAt(int index) const override; |
3318 | + int indexForId(int id) const override; |
3319 | + void raiseId(int id) override; |
3320 | + |
3321 | +Q_SIGNALS: |
3322 | + // Own API |
3323 | + void nextIdChanged(); |
3324 | + |
3325 | +private Q_SLOTS: |
3326 | + void focusTopMostAvailableWindow(); |
3327 | + |
3328 | +private: |
3329 | + void connectSurfaceManager(); |
3330 | + void setApplicationManager(ApplicationManager*); |
3331 | + void doRaiseId(int id); |
3332 | + int generateId(); |
3333 | + int nextFreeId(int candidateId); |
3334 | + QString toString(); |
3335 | + int indexOf(WindowInterface *window); |
3336 | + int indexOf(MirSurfaceInterface *surface); |
3337 | + |
3338 | + void setInputMethodSurface(MirSurface *surface); |
3339 | + void setFocusedWindow(Window *window); |
3340 | + void removeInputMethodWindow(); |
3341 | + void removeAt(int index); |
3342 | + |
3343 | + void addApplication(ApplicationInfo *application); |
3344 | + void removeApplication(ApplicationInfo *application); |
3345 | + |
3346 | + void prependPlaceholder(ApplicationInfo *application); |
3347 | + void prependSurface(MirSurface *surface, ApplicationInfo *application); |
3348 | + void prependSurfaceHelper(MirSurface *surface, ApplicationInfo *application); |
3349 | + |
3350 | + void connectSurface(MirSurface *surface); |
3351 | + |
3352 | + void onStateChangeRequested(Window *window, Mir::State requestedState); |
3353 | + void onSurfaceDied(MirSurfaceInterface *surface); |
3354 | + void onSurfaceDestroyed(MirSurfaceInterface *surface); |
3355 | + void onWindowCloseRequested(Window *window); |
3356 | + |
3357 | + Window *findWindowWithSurface(MirSurface *surface); |
3358 | + |
3359 | + Window *findFocusableWindow(int index); |
3360 | + |
3361 | + void move(int from, int to); |
3362 | + |
3363 | + struct ModelEntry { |
3364 | + ModelEntry() {} |
3365 | + ModelEntry(Window *window, |
3366 | + ApplicationInfo *application) |
3367 | + : window(window), application(application) {} |
3368 | + Window *window{nullptr}; |
3369 | + ApplicationInfo *application{nullptr}; |
3370 | + bool removeOnceSurfaceDestroyed{false}; |
3371 | + }; |
3372 | + |
3373 | + QVector<ModelEntry> m_windowModel; |
3374 | + Window* m_inputMethodWindow{nullptr}; |
3375 | + Window* m_focusedWindow{nullptr}; |
3376 | + int m_nextId{1}; |
3377 | + // Just something big enough that we don't risk running out of unused id numbers. |
3378 | + // Not sure if QML int type supports something close to std::numeric_limits<int>::max() and |
3379 | + // there's no reason to try out its limits. |
3380 | + static const int m_maxId{1000000}; |
3381 | + |
3382 | + ApplicationManagerInterface* m_applicationManager{nullptr}; |
3383 | + |
3384 | + enum ModelState { |
3385 | + IdleState, |
3386 | + InsertingState, |
3387 | + RemovingState, |
3388 | + MovingState, |
3389 | + ResettingState |
3390 | + }; |
3391 | + ModelState m_modelState{IdleState}; |
3392 | + |
3393 | + bool m_connectedSurfaceManager{false}; |
3394 | +}; |
3395 | |
3396 | === added file 'tests/mocks/Unity/Application/Window.cpp' |
3397 | --- tests/mocks/Unity/Application/Window.cpp 1970-01-01 00:00:00 +0000 |
3398 | +++ tests/mocks/Unity/Application/Window.cpp 2016-11-09 15:21:35 +0000 |
3399 | @@ -0,0 +1,229 @@ |
3400 | +/* |
3401 | + * Copyright (C) 2016 Canonical, Ltd. |
3402 | + * |
3403 | + * This program is free software; you can redistribute it and/or modify |
3404 | + * it under the terms of the GNU General Public License as published by |
3405 | + * the Free Software Foundation; version 3. |
3406 | + * |
3407 | + * This program is distributed in the hope that it will be useful, |
3408 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3409 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3410 | + * GNU General Public License for more details. |
3411 | + * |
3412 | + * You should have received a copy of the GNU General Public License |
3413 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3414 | + */ |
3415 | + |
3416 | +#include "Window.h" |
3417 | +#include "MirSurface.h" |
3418 | + |
3419 | +#include <QQmlEngine> |
3420 | + |
3421 | +#define WINDOW_DEBUG 0 |
3422 | + |
3423 | +#if WINDOW_DEBUG |
3424 | +#include <QDebug> |
3425 | +#define DEBUG_MSG(params) qDebug().nospace() << qPrintable(toString()) << "::" << __func__ << " " << params |
3426 | +#else |
3427 | +#define DEBUG_MSG(params) ((void)0) |
3428 | +#endif |
3429 | + |
3430 | +using namespace unity::shell::application; |
3431 | + |
3432 | +Window::Window(int id) |
3433 | + : WindowInterface(nullptr) |
3434 | + , m_id(id) |
3435 | +{ |
3436 | + DEBUG_MSG(""); |
3437 | + QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); |
3438 | +} |
3439 | + |
3440 | +Window::~Window() |
3441 | +{ |
3442 | + DEBUG_MSG(""); |
3443 | +} |
3444 | + |
3445 | +QPoint Window::position() const |
3446 | +{ |
3447 | + return m_position; |
3448 | +} |
3449 | + |
3450 | +QPoint Window::requestedPosition() const |
3451 | +{ |
3452 | + return m_requestedPosition; |
3453 | +} |
3454 | + |
3455 | +void Window::setRequestedPosition(const QPoint &value) |
3456 | +{ |
3457 | + if (value != m_requestedPosition) { |
3458 | + m_requestedPosition = value; |
3459 | + Q_EMIT requestedPositionChanged(m_requestedPosition); |
3460 | + if (m_surface) { |
3461 | + m_surface->setRequestedPosition(value); |
3462 | + } else { |
3463 | + // fake-miral: always comply |
3464 | + m_position = m_requestedPosition; |
3465 | + Q_EMIT positionChanged(m_position); |
3466 | + } |
3467 | + } |
3468 | +} |
3469 | + |
3470 | +Mir::State Window::state() const |
3471 | +{ |
3472 | + return m_state; |
3473 | +} |
3474 | + |
3475 | +bool Window::focused() const |
3476 | +{ |
3477 | + return m_focused; |
3478 | +} |
3479 | + |
3480 | +bool Window::confinesMousePointer() const |
3481 | +{ |
3482 | + if (m_surface) { |
3483 | + return m_surface->confinesMousePointer(); |
3484 | + } else { |
3485 | + return false; |
3486 | + } |
3487 | +} |
3488 | + |
3489 | +int Window::id() const |
3490 | +{ |
3491 | + return m_id; |
3492 | +} |
3493 | + |
3494 | +MirSurfaceInterface* Window::surface() const |
3495 | +{ |
3496 | + return m_surface; |
3497 | +} |
3498 | + |
3499 | +void Window::requestState(Mir::State state) |
3500 | +{ |
3501 | + Q_EMIT stateRequested(state); |
3502 | +} |
3503 | + |
3504 | +void Window::setState(Mir::State state) |
3505 | +{ |
3506 | + if (m_surface) { |
3507 | + m_surface->setState(state); |
3508 | + } else { |
3509 | + m_state = state; |
3510 | + Q_EMIT stateChanged(m_state); |
3511 | + } |
3512 | +} |
3513 | + |
3514 | +void Window::requestFocus() |
3515 | +{ |
3516 | + if (m_surface) { |
3517 | + m_surface->requestFocus(); |
3518 | + } else { |
3519 | + Q_EMIT focusRequested(); |
3520 | + } |
3521 | +} |
3522 | + |
3523 | +void Window::close() |
3524 | +{ |
3525 | + if (m_surface) { |
3526 | + m_surface->close(); |
3527 | + } else { |
3528 | + Q_EMIT closeRequested(); |
3529 | + } |
3530 | +} |
3531 | + |
3532 | +void Window::setSurface(MirSurface *surface) |
3533 | +{ |
3534 | + if (m_surface) { |
3535 | + disconnect(m_surface, 0, this, 0); |
3536 | + } |
3537 | + |
3538 | + m_surface = surface; |
3539 | + |
3540 | + if (m_surface) { |
3541 | + connect(surface, &MirSurfaceInterface::focusRequested, this, [this]() { |
3542 | + Q_EMIT focusRequested(); |
3543 | + }); |
3544 | + |
3545 | + connect(surface, &MirSurface::closeRequested, this, &Window::closeRequested); |
3546 | + |
3547 | + connect(surface, &MirSurface::stateRequested, this, [this](Mir::State state) { |
3548 | + Q_EMIT stateRequested(state); |
3549 | + }); |
3550 | + |
3551 | + connect(surface, &MirSurfaceInterface::positionChanged, this, [this]() { |
3552 | + updatePosition(); |
3553 | + }); |
3554 | + |
3555 | + connect(surface, &MirSurfaceInterface::stateChanged, this, [this]() { |
3556 | + updateState(); |
3557 | + }); |
3558 | + |
3559 | + connect(surface, &MirSurfaceInterface::focusedChanged, this, [this]() { |
3560 | + updateFocused(); |
3561 | + }); |
3562 | + |
3563 | + // bring it up to speed |
3564 | + m_surface->setRequestedPosition(m_requestedPosition); |
3565 | + m_surface->requestState(m_state); |
3566 | + |
3567 | + // and sync with surface |
3568 | + updatePosition(); |
3569 | + updateState(); |
3570 | + updateFocused(); |
3571 | + } |
3572 | + |
3573 | + Q_EMIT surfaceChanged(surface); |
3574 | +} |
3575 | + |
3576 | +void Window::updatePosition() |
3577 | +{ |
3578 | + if (m_surface->position() != m_position) { |
3579 | + m_position = m_surface->position(); |
3580 | + Q_EMIT positionChanged(m_position); |
3581 | + } |
3582 | +} |
3583 | + |
3584 | +void Window::updateState() |
3585 | +{ |
3586 | + if (m_surface->state() != m_state) { |
3587 | + m_state = m_surface->state(); |
3588 | + Q_EMIT stateChanged(m_state); |
3589 | + } |
3590 | +} |
3591 | + |
3592 | +void Window::updateFocused() |
3593 | +{ |
3594 | + if (m_surface->focused() != m_focused) { |
3595 | + m_focused = m_surface->focused(); |
3596 | + Q_EMIT focusedChanged(m_focused); |
3597 | + } |
3598 | +} |
3599 | + |
3600 | + |
3601 | +void Window::setFocused(bool value) |
3602 | +{ |
3603 | + if (value != m_focused) { |
3604 | + DEBUG_MSG("(" << value << ")"); |
3605 | + m_focused = value; |
3606 | + Q_EMIT focusedChanged(m_focused); |
3607 | + if (m_surface) { |
3608 | + m_surface->setFocused(m_focused); |
3609 | + } |
3610 | + } else { |
3611 | + DEBUG_MSG("(" << value << ") - NOOP"); |
3612 | + } |
3613 | +} |
3614 | + |
3615 | +QString Window::toString() const |
3616 | +{ |
3617 | + if (surface()) { |
3618 | + return QString("Window[0x%1, id=%2, MirSurface[0x%3,\"%4\"]]") |
3619 | + .arg((quintptr)this, 0, 16) |
3620 | + .arg(id()) |
3621 | + .arg((quintptr)surface(), 0, 16) |
3622 | + .arg(surface()->name()); |
3623 | + } else { |
3624 | + return QString("Window[0x%1, id=%2, null]") |
3625 | + .arg((quintptr)this, 0, 16) |
3626 | + .arg(id()); |
3627 | + } |
3628 | +} |
3629 | |
3630 | === added file 'tests/mocks/Unity/Application/Window.h' |
3631 | --- tests/mocks/Unity/Application/Window.h 1970-01-01 00:00:00 +0000 |
3632 | +++ tests/mocks/Unity/Application/Window.h 2016-11-09 15:21:35 +0000 |
3633 | @@ -0,0 +1,69 @@ |
3634 | +/* |
3635 | + * Copyright (C) 2016 Canonical, Ltd. |
3636 | + * |
3637 | + * This program is free software; you can redistribute it and/or modify |
3638 | + * it under the terms of the GNU General Public License as published by |
3639 | + * the Free Software Foundation; version 3. |
3640 | + * |
3641 | + * This program is distributed in the hope that it will be useful, |
3642 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3643 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3644 | + * GNU General Public License for more details. |
3645 | + * |
3646 | + * You should have received a copy of the GNU General Public License |
3647 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3648 | + */ |
3649 | + |
3650 | +#ifndef MOCK_WINDOW_H |
3651 | +#define MOCK_WINDOW_H |
3652 | + |
3653 | +// unity-api |
3654 | +#include <unity/shell/application/WindowInterface.h> |
3655 | + |
3656 | +class MirSurface; |
3657 | + |
3658 | +class Window : public unity::shell::application::WindowInterface |
3659 | +{ |
3660 | + Q_OBJECT |
3661 | + |
3662 | +public: |
3663 | + Window(int id); |
3664 | + virtual ~Window(); |
3665 | + QPoint position() const override; |
3666 | + QPoint requestedPosition() const override; |
3667 | + void setRequestedPosition(const QPoint &) override; |
3668 | + Mir::State state() const override; |
3669 | + bool focused() const override; |
3670 | + bool confinesMousePointer() const override; |
3671 | + int id() const override; |
3672 | + unity::shell::application::MirSurfaceInterface* surface() const override; |
3673 | + |
3674 | + void setSurface(MirSurface *surface); |
3675 | + void setFocused(bool value); |
3676 | + void setState(Mir::State state); |
3677 | + |
3678 | + QString toString() const; |
3679 | + |
3680 | +Q_SIGNALS: |
3681 | + void stateRequested(Mir::State); |
3682 | + void closeRequested(); |
3683 | + |
3684 | +public Q_SLOTS: |
3685 | + void requestState(Mir::State state) override; |
3686 | + void requestFocus() override; |
3687 | + void close() override; |
3688 | + |
3689 | +private: |
3690 | + void updatePosition(); |
3691 | + void updateState(); |
3692 | + void updateFocused(); |
3693 | + |
3694 | + QPoint m_position; |
3695 | + QPoint m_requestedPosition; |
3696 | + bool m_focused{false}; |
3697 | + int m_id; |
3698 | + Mir::State m_state{Mir::RestoredState}; |
3699 | + MirSurface *m_surface{nullptr}; |
3700 | +}; |
3701 | + |
3702 | +#endif // MOCK_WINDOW_H |
3703 | |
3704 | === modified file 'tests/mocks/Unity/Application/plugin.cpp' |
3705 | --- tests/mocks/Unity/Application/plugin.cpp 2016-06-30 13:51:32 +0000 |
3706 | +++ tests/mocks/Unity/Application/plugin.cpp 2016-11-09 15:21:35 +0000 |
3707 | @@ -19,6 +19,8 @@ |
3708 | #include "ApplicationManager.h" |
3709 | #include "MirSurfaceItem.h" |
3710 | #include "SurfaceManager.h" |
3711 | +#include "TopLevelWindowModel.h" |
3712 | +#include "Window.h" |
3713 | |
3714 | // unity-api |
3715 | #include <unity/shell/application/Mir.h> |
3716 | @@ -32,9 +34,6 @@ |
3717 | void createUnityApplicationSharedSingletons() |
3718 | { |
3719 | // they have to be created in a specific order |
3720 | - if (!MirFocusController::instance()) { |
3721 | - new MirFocusController; |
3722 | - } |
3723 | if (!SurfaceManager::instance()) { |
3724 | new SurfaceManager; |
3725 | } |
3726 | @@ -48,16 +47,12 @@ |
3727 | |
3728 | QObject* surfaceManagerSingleton(QQmlEngine*, QJSEngine*) |
3729 | { |
3730 | - createUnityApplicationSharedSingletons(); |
3731 | + if (!SurfaceManager::instance()) { |
3732 | + new SurfaceManager; |
3733 | + } |
3734 | return SurfaceManager::instance(); |
3735 | } |
3736 | |
3737 | -QObject* mirFocusControllerSingleton(QQmlEngine*, QJSEngine*) |
3738 | -{ |
3739 | - createUnityApplicationSharedSingletons(); |
3740 | - return MirFocusController::instance(); |
3741 | -} |
3742 | - |
3743 | } // anonymous namespace |
3744 | |
3745 | void FakeUnityApplicationQmlPlugin::registerTypes(const char *uri) |
3746 | @@ -67,18 +62,19 @@ |
3747 | qRegisterMetaType<unity::shell::application::MirSurfaceListInterface*>("unity::shell::application::MirSurfaceListInterface*"); |
3748 | qRegisterMetaType<Mir::Type>("Mir::Type"); |
3749 | qRegisterMetaType<Mir::State>("Mir::State"); |
3750 | + qRegisterMetaType<unity::shell::application::WindowInterface*>("unity::shell::application::WindowInterface*"); |
3751 | |
3752 | qmlRegisterUncreatableType<unity::shell::application::ApplicationManagerInterface>(uri, 0, 1, "ApplicationManagerInterface", "Abstract interface. Cannot be created in QML"); |
3753 | qmlRegisterUncreatableType<unity::shell::application::ApplicationInfoInterface>(uri, 0, 1, "ApplicationInfoInterface", "Abstract interface. Cannot be created in QML"); |
3754 | qmlRegisterUncreatableType<MirSurface>(uri, 0, 1, "MirSurface", "MirSurface can't be instantiated from QML"); |
3755 | qmlRegisterUncreatableType<unity::shell::application::MirSurfaceInterface>( |
3756 | uri, 0, 1, "MirSurface", "MirSurface can't be instantiated from QML"); |
3757 | - qmlRegisterSingletonType<MirFocusController>(uri, 0, 1, "MirFocusController", mirFocusControllerSingleton); |
3758 | qmlRegisterType<MirSurfaceItem>(uri, 0, 1, "MirSurfaceItem"); |
3759 | qmlRegisterType<ApplicationInfo>(uri, 0, 1, "ApplicationInfo"); |
3760 | |
3761 | qmlRegisterSingletonType<ApplicationManager>(uri, 0, 1, "ApplicationManager", applicationManagerSingleton); |
3762 | qmlRegisterSingletonType<SurfaceManager>(uri, 0, 1, "SurfaceManager", surfaceManagerSingleton); |
3763 | + qmlRegisterType<TopLevelWindowModel>(uri, 0, 1, "TopLevelWindowModel"); |
3764 | |
3765 | qmlRegisterUncreatableType<Mir>(uri, 0, 1, "Mir", "Mir provides enum values, it can't be instantiated"); |
3766 | } |
3767 | |
3768 | === modified file 'tests/qmltests/Stage/tst_DesktopStage.qml' |
3769 | --- tests/qmltests/Stage/tst_DesktopStage.qml 2016-09-27 15:03:00 +0000 |
3770 | +++ tests/qmltests/Stage/tst_DesktopStage.qml 2016-11-09 15:21:35 +0000 |
3771 | @@ -20,7 +20,6 @@ |
3772 | import Ubuntu.Components.ListItems 1.3 |
3773 | import Unity.Application 0.1 |
3774 | import Unity.Test 0.1 |
3775 | -import WindowManager 0.1 |
3776 | import Utils 0.1 |
3777 | |
3778 | import ".." // For EdgeBarrierControls |
3779 | @@ -57,9 +56,8 @@ |
3780 | } |
3781 | } |
3782 | |
3783 | - TopLevelSurfaceList { |
3784 | + TopLevelWindowModel { |
3785 | id: topSurfaceList |
3786 | - applicationsModel: ApplicationManager |
3787 | } |
3788 | |
3789 | Loader { |
3790 | @@ -170,8 +168,9 @@ |
3791 | tryCompare(dashApp, "state", ApplicationInfoInterface.Running); |
3792 | |
3793 | tryCompare(topSurfaceList, "count", 1); |
3794 | - tryCompareFunction(function(){return topSurfaceList.surfaceAt(0) != null;}, true); |
3795 | - compare(MirFocusController.focusedSurface, topSurfaceList.surfaceAt(0)); |
3796 | + tryCompareFunction(function(){return topSurfaceList.windowAt(0) != null;}, true); |
3797 | + topSurfaceList.windowAt(0).requestFocus(); |
3798 | + tryCompare(topSurfaceList, "focusedWindow", topSurfaceList.windowAt(0)); |
3799 | } |
3800 | |
3801 | function cleanup() { |
3802 | @@ -284,13 +283,13 @@ |
3803 | verify(fromAppWindow); |
3804 | tap(fromAppWindow); |
3805 | compare(fromDelegate.surface.activeFocus, true); |
3806 | - compare(MirFocusController.focusedSurface, fromDelegate.surface); |
3807 | + compare(topSurfaceList.focusedWindow, fromDelegate.window); |
3808 | |
3809 | var toAppWindow = findChild(toDelegate, "appWindow"); |
3810 | verify(toAppWindow); |
3811 | tap(toAppWindow); |
3812 | compare(toDelegate.surface.activeFocus, true); |
3813 | - compare(MirFocusController.focusedSurface, toDelegate.surface); |
3814 | + compare(topSurfaceList.focusedWindow, toDelegate.window); |
3815 | } |
3816 | |
3817 | function test_clickingOnWindowChangesFocusedApp_data() { |
3818 | @@ -309,13 +308,13 @@ |
3819 | verify(fromAppWindow); |
3820 | mouseClick(fromAppWindow); |
3821 | compare(fromDelegate.surface.activeFocus, true); |
3822 | - compare(MirFocusController.focusedSurface, fromDelegate.surface); |
3823 | + compare(topSurfaceList.focusedWindow, fromDelegate.window); |
3824 | |
3825 | var toAppWindow = findChild(toDelegate, "appWindow"); |
3826 | verify(toAppWindow); |
3827 | mouseClick(toAppWindow); |
3828 | compare(toDelegate.surface.activeFocus, true); |
3829 | - compare(MirFocusController.focusedSurface, toDelegate.surface); |
3830 | + compare(topSurfaceList.focusedWindow, toDelegate.window); |
3831 | } |
3832 | |
3833 | function test_tappingOnDecorationFocusesApplication_data() { |
3834 | @@ -343,6 +342,13 @@ |
3835 | return findChild(appDelegate, "appWindowDecoration"); |
3836 | } |
3837 | |
3838 | + function maximizeDelegate(appDelegate) { |
3839 | + var maximizeButton = findChild(appDelegate, "maximizeWindowButton"); |
3840 | + verify(maximizeButton); |
3841 | + mouseClick(maximizeButton); |
3842 | + tryCompare(appDelegate, "visuallyMaximized", true); |
3843 | + } |
3844 | + |
3845 | function test_tappingOnDecorationFocusesApplication(data) { |
3846 | var appDelegates = []; |
3847 | for (var i = 0; i < data.apps.length; i++) { |
3848 | @@ -512,11 +518,11 @@ |
3849 | apps.forEach(startApplication); |
3850 | verify(topSurfaceList.count == 3); |
3851 | keyClick(Qt.Key_D, Qt.MetaModifier|Qt.ControlModifier); // Ctrl+Super+D shortcut to minimize all |
3852 | - tryCompare(MirFocusController, "focusedSurface", null); // verify no surface is focused |
3853 | + tryCompare(topSurfaceList, "focusedWindow", null); // verify no window is focused |
3854 | |
3855 | // now try pressing all 4 arrow keys + ctrl + meta |
3856 | keyClick(Qt.Key_Up | Qt.Key_Down | Qt.Key_Left | Qt.Key_Right, Qt.MetaModifier|Qt.ControlModifier); // smash it!!! |
3857 | - tryCompare(MirFocusController, "focusedSurface", null); // verify still no surface is focused |
3858 | + tryCompare(topSurfaceList, "focusedWindow", null); // verify still no window is focused |
3859 | } |
3860 | |
3861 | function test_minimizeApplicationHidesSurface() { |
3862 | @@ -527,9 +533,12 @@ |
3863 | var decoratedWindow = findDecoratedWindow(dashSurfaceId); |
3864 | verify(decoratedWindow); |
3865 | |
3866 | - tryCompare(dashSurface, "visible", true); |
3867 | - decoratedWindow.minimizeClicked(); |
3868 | - tryCompare(dashSurface, "visible", false); |
3869 | + var minimizeButton = findChild(decoratedWindow, "minimizeWindowButton"); |
3870 | + verify(minimizeButton); |
3871 | + |
3872 | + tryCompare(dashSurface, "exposed", true); |
3873 | + mouseClick(minimizeButton); |
3874 | + tryCompare(dashSurface, "exposed", false); |
3875 | } |
3876 | |
3877 | function test_maximizeApplicationHidesSurfacesBehindIt() { |
3878 | @@ -538,16 +547,16 @@ |
3879 | var gmailDelegate = startApplication("gmail-webapp"); |
3880 | |
3881 | // maximize without raising |
3882 | - dialerDelegate.maximize(); |
3883 | + dialerDelegate.requestMaximize(); |
3884 | tryCompare(dialerDelegate, "visuallyMaximized", true); |
3885 | |
3886 | - tryCompare(dashDelegate.surface, "visible", false); |
3887 | - compare(gmailDelegate.surface.visible, true); |
3888 | + tryCompare(dashDelegate.surface, "exposed", false); |
3889 | + compare(gmailDelegate.surface.exposed, true); |
3890 | |
3891 | // restore without raising |
3892 | - dialerDelegate.restoreFromMaximized(); |
3893 | - compare(dashDelegate.surface.visible, true); |
3894 | - compare(gmailDelegate.surface.visible, true); |
3895 | + dialerDelegate.requestRestore(); |
3896 | + compare(dashDelegate.surface.exposed, true); |
3897 | + compare(gmailDelegate.surface.exposed, true); |
3898 | } |
3899 | |
3900 | function test_applicationsBecomeVisibleWhenOccludingAppRemoved() { |
3901 | @@ -580,26 +589,22 @@ |
3902 | tryCompare(dialerDelegate, "visuallyMaximized", true); |
3903 | tryCompare(gmailDelegate, "visuallyMaximized", true); |
3904 | |
3905 | - tryCompare(dashApp.surfaceList.get(0), "visible", false); |
3906 | - tryCompare(dialerApp.surfaceList.get(0), "visible", false); |
3907 | - tryCompare(mapApp.surfaceList.get(0), "visible", false); |
3908 | + tryCompare(dashApp.surfaceList.get(0), "exposed", false); |
3909 | + tryCompare(dialerApp.surfaceList.get(0), "exposed", false); |
3910 | + tryCompare(mapApp.surfaceList.get(0), "exposed", false); |
3911 | |
3912 | ApplicationManager.stopApplication("gmail-webapp"); |
3913 | wait(2000) |
3914 | |
3915 | - tryCompare(mapApp.surfaceList.get(0), "visible", true); |
3916 | - tryCompare(dialerApp.surfaceList.get(0), "visible", true); |
3917 | - tryCompare(dashApp.surfaceList.get(0), "visible", false); // still occluded by maximised dialer |
3918 | + tryCompare(mapApp.surfaceList.get(0), "exposed", true); |
3919 | + tryCompare(dialerApp.surfaceList.get(0), "exposed", true); |
3920 | + tryCompare(dashApp.surfaceList.get(0), "exposed", false); // still occluded by maximised dialer |
3921 | } |
3922 | |
3923 | function test_maximisedAppStaysVisibleWhenAppStarts() { |
3924 | var dashDelegate = startApplication("unity8-dash"); |
3925 | |
3926 | - // maximize |
3927 | - var dashMaximizeButton = findChild(dashDelegate, "maximizeWindowButton"); |
3928 | - verify(dashMaximizeButton); |
3929 | - mouseClick(dashMaximizeButton); |
3930 | - tryCompare(dashDelegate, "visuallyMaximized", true); |
3931 | + maximizeDelegate(dashDelegate); |
3932 | |
3933 | var dialerDelegate = startApplication("dialer-app"); |
3934 | verify(dialerDelegate); |
3935 | @@ -621,25 +626,25 @@ |
3936 | tryCompare(facebookAppDelegate, "visible", true); |
3937 | |
3938 | // Maximize the topmost and make sure the other two are hidden |
3939 | - facebookAppDelegate.maximize(); |
3940 | + maximizeDelegate(facebookAppDelegate); |
3941 | tryCompare(dashAppDelegate, "visible", false); |
3942 | tryCompare(dialerAppDelegate, "visible", false); |
3943 | tryCompare(facebookAppDelegate, "visible", true); |
3944 | |
3945 | // Bring dash to front. make sure dash and the maximized facebook are visible, the restored one behind is hidden |
3946 | - dashAppDelegate.focus = true; |
3947 | + dashAppDelegate.requestFocus(); |
3948 | tryCompare(dashAppDelegate, "visible", true); |
3949 | tryCompare(dialerAppDelegate, "visible", false); |
3950 | tryCompare(facebookAppDelegate, "visible", true); |
3951 | |
3952 | // Now focus the dialer app. all 3 should be visible again |
3953 | - dialerAppDelegate.focus = true; |
3954 | + dialerAppDelegate.requestFocus(); |
3955 | tryCompare(dashAppDelegate, "visible", true); |
3956 | tryCompare(dialerAppDelegate, "visible", true); |
3957 | tryCompare(facebookAppDelegate, "visible", true); |
3958 | |
3959 | // Maximize the dialer app. The other 2 should hide |
3960 | - dialerAppDelegate.maximize(); |
3961 | + maximizeDelegate(dialerAppDelegate); |
3962 | tryCompare(dashAppDelegate, "visible", false); |
3963 | tryCompare(dialerAppDelegate, "visible", true); |
3964 | tryCompare(facebookAppDelegate, "visible", false); |
3965 | @@ -648,7 +653,7 @@ |
3966 | function test_dropShadow() { |
3967 | // start an app, maximize it |
3968 | var facebookAppDelegate = startApplication("facebook-webapp"); |
3969 | - facebookAppDelegate.maximize(); |
3970 | + maximizeDelegate(facebookAppDelegate); |
3971 | |
3972 | // verify the drop shadow is still not visible |
3973 | verify(PanelState.dropShadow == false); |
3974 | |
3975 | === modified file 'tests/qmltests/Stage/tst_PhoneStage.qml' |
3976 | --- tests/qmltests/Stage/tst_PhoneStage.qml 2016-10-08 16:45:37 +0000 |
3977 | +++ tests/qmltests/Stage/tst_PhoneStage.qml 2016-11-09 15:21:35 +0000 |
3978 | @@ -22,7 +22,6 @@ |
3979 | import "../../../qml/Stage" |
3980 | import Ubuntu.Components 1.3 |
3981 | import Unity.Application 0.1 |
3982 | -import WindowManager 0.1 |
3983 | |
3984 | Item { |
3985 | id: root |
3986 | @@ -41,9 +40,8 @@ |
3987 | orientations: Orientations {} |
3988 | applicationManager: ApplicationManager |
3989 | mode: "staged" |
3990 | - topLevelSurfaceList: TopLevelSurfaceList { |
3991 | + topLevelSurfaceList: TopLevelWindowModel { |
3992 | id: topLevelSurfaceList |
3993 | - applicationsModel: ApplicationManager |
3994 | } |
3995 | } |
3996 | |
3997 | @@ -505,7 +503,7 @@ |
3998 | function test_selectSuspendedAppWithoutSurface() { |
3999 | compare(topLevelSurfaceList.applicationAt(0).appId, "unity8-dash"); |
4000 | var dashSurfaceId = topLevelSurfaceList.idAt(0); |
4001 | - var dashSurface = topLevelSurfaceList.surfaceAt(0); |
4002 | + var dashWindow = topLevelSurfaceList.windowAt(0); |
4003 | |
4004 | var webbrowserSurfaceId = topLevelSurfaceList.nextId; |
4005 | var webbrowserApp = ApplicationManager.startApplication("webbrowser-app"); |
4006 | @@ -513,7 +511,7 @@ |
4007 | |
4008 | switchToSurface(dashSurfaceId); |
4009 | |
4010 | - tryCompare(MirFocusController, "focusedSurface", dashSurface); |
4011 | + tryCompare(topLevelSurfaceList, "focusedWindow", dashWindow); |
4012 | tryCompare(webbrowserApp, "state", ApplicationInfoInterface.Suspended); |
4013 | |
4014 | compare(webbrowserApp.surfaceList.count, 1); |
4015 | @@ -549,7 +547,7 @@ |
4016 | { |
4017 | compare(topLevelSurfaceList.applicationAt(0).appId, "unity8-dash"); |
4018 | var dashSurfaceId = topLevelSurfaceList.idAt(0); |
4019 | - var dashSurface = topLevelSurfaceList.surfaceAt(0); |
4020 | + var dashWindow = topLevelSurfaceList.windowAt(0); |
4021 | |
4022 | var webbrowserSurfaceId = topLevelSurfaceList.nextId; |
4023 | var webbrowserApp = ApplicationManager.startApplication("webbrowser-app"); |
4024 | @@ -557,7 +555,7 @@ |
4025 | |
4026 | switchToSurface(dashSurfaceId); |
4027 | |
4028 | - tryCompare(MirFocusController, "focusedSurface", dashSurface); |
4029 | + tryCompare(topLevelSurfaceList, "focusedWindow", dashWindow); |
4030 | tryCompare(webbrowserApp, "state", ApplicationInfoInterface.Suspended); |
4031 | |
4032 | compare(webbrowserApp.surfaceList.count, 1); |
4033 | |
4034 | === modified file 'tests/qmltests/Stage/tst_TabletStage.qml' |
4035 | --- tests/qmltests/Stage/tst_TabletStage.qml 2016-10-08 16:45:37 +0000 |
4036 | +++ tests/qmltests/Stage/tst_TabletStage.qml 2016-11-09 15:21:35 +0000 |
4037 | @@ -21,7 +21,6 @@ |
4038 | import Unity.Application 0.1 |
4039 | import Unity.Test 0.1 |
4040 | import Utils 0.1 |
4041 | -import WindowManager 0.1 |
4042 | |
4043 | import ".." |
4044 | import "../../../qml/Stage" |
4045 | @@ -50,9 +49,8 @@ |
4046 | focus: true |
4047 | mode: "stagedWithSideStage" |
4048 | applicationManager: ApplicationManager |
4049 | - topLevelSurfaceList: TopLevelSurfaceList { |
4050 | + topLevelSurfaceList: TopLevelWindowModel { |
4051 | id: topLevelSurfaceList |
4052 | - applicationsModel: ApplicationManager |
4053 | } |
4054 | } |
4055 | |
4056 | @@ -628,7 +626,7 @@ |
4057 | function test_selectSuspendedAppWithoutSurface() { |
4058 | compare(topSurfaceList.applicationAt(0).appId, "unity8-dash"); |
4059 | var dashSurfaceId = topSurfaceList.idAt(0); |
4060 | - var dashSurface = topSurfaceList.surfaceAt(0); |
4061 | + var dashWindow = topSurfaceList.windowAt(0); |
4062 | |
4063 | var webbrowserSurfaceId = topSurfaceList.nextId; |
4064 | webbrowserCheckBox.checked = true; |
4065 | @@ -637,7 +635,7 @@ |
4066 | |
4067 | switchToSurface(dashSurfaceId); |
4068 | |
4069 | - tryCompare(MirFocusController, "focusedSurface", dashSurface); |
4070 | + tryCompare(topLevelSurfaceList, "focusedWindow", dashWindow); |
4071 | tryCompare(webbrowserApp, "state", ApplicationInfoInterface.Suspended); |
4072 | |
4073 | compare(webbrowserApp.surfaceList.count, 1); |
4074 | |
4075 | === modified file 'tests/qmltests/tst_Shell.qml' |
4076 | --- tests/qmltests/tst_Shell.qml 2016-10-03 11:15:27 +0000 |
4077 | +++ tests/qmltests/tst_Shell.qml 2016-11-09 15:21:35 +0000 |
4078 | @@ -52,6 +52,15 @@ |
4079 | } |
4080 | |
4081 | property var shell: shellLoader.item ? shellLoader.item : null |
4082 | + onShellChanged: { |
4083 | + if (shell) { |
4084 | + topLevelSurfaceList = testCase.findInvisibleChild(shell, "topLevelSurfaceList"); |
4085 | + } else { |
4086 | + topLevelSurfaceList = null; |
4087 | + } |
4088 | + } |
4089 | + |
4090 | + property var topLevelSurfaceList: null |
4091 | |
4092 | Item { |
4093 | id: shellContainer |
4094 | @@ -318,21 +327,21 @@ |
4095 | id: fullscreeAppCheck |
4096 | |
4097 | onTriggered: { |
4098 | - if (!MirFocusController.focusedSurface) return; |
4099 | - if (MirFocusController.focusedSurface.state == Mir.FullscreenState) { |
4100 | - MirFocusController.focusedSurface.state = Mir.RestoredState; |
4101 | + if (!topLevelSurfaceList.focusedSurface) return; |
4102 | + if (topLevelSurfaceList.focusedSurface.state == Mir.FullscreenState) { |
4103 | + topLevelSurfaceList.focusedSurface.requestState(Mir.RestoredState); |
4104 | } else { |
4105 | - MirFocusController.focusedSurface.state = Mir.FullscreenState; |
4106 | + topLevelSurfaceList.focusedSurface.requestState(Mir.FullscreenState); |
4107 | } |
4108 | } |
4109 | |
4110 | Binding { |
4111 | target: fullscreeAppCheck |
4112 | - when: MirFocusController.focusedSurface |
4113 | + when: topLevelSurfaceList && topLevelSurfaceList.focusedSurface |
4114 | property: "checked" |
4115 | value: { |
4116 | - if (!MirFocusController.focusedSurface) return false; |
4117 | - return MirFocusController.focusedSurface.state === Mir.FullscreenState |
4118 | + if (!topLevelSurfaceList || !topLevelSurfaceList.focusedSurface) return false; |
4119 | + return topLevelSurfaceList.focusedSurface.state === Mir.FullscreenState |
4120 | } |
4121 | } |
4122 | } |
4123 | @@ -346,21 +355,21 @@ |
4124 | id: chromeAppCheck |
4125 | |
4126 | onTriggered: { |
4127 | - if (!MirFocusController.focusedSurface) return; |
4128 | - if (MirFocusController.focusedSurface.shellChrome == Mir.LowChrome) { |
4129 | - MirFocusController.focusedSurface.setShellChrome(Mir.NormalChrome); |
4130 | + if (!topLevelSurfaceList.focusedSurface) return; |
4131 | + if (topLevelSurfaceList.focusedSurface.shellChrome == Mir.LowChrome) { |
4132 | + topLevelSurfaceList.focusedSurface.setShellChrome(Mir.NormalChrome); |
4133 | } else { |
4134 | - MirFocusController.focusedSurface.setShellChrome(Mir.LowChrome); |
4135 | + topLevelSurfaceList.focusedSurface.setShellChrome(Mir.LowChrome); |
4136 | } |
4137 | } |
4138 | |
4139 | Binding { |
4140 | target: chromeAppCheck |
4141 | - when: MirFocusController.focusedSurface !== null |
4142 | + when: topLevelSurfaceList && topLevelSurfaceList.focusedSurface !== null |
4143 | property: "checked" |
4144 | value: { |
4145 | - if (!MirFocusController.focusedSurface) return false; |
4146 | - MirFocusController.focusedSurface.shellChrome === Mir.LowChrome |
4147 | + if (!topLevelSurfaceList || !topLevelSurfaceList.focusedSurface) return false; |
4148 | + topLevelSurfaceList.focusedSurface.shellChrome === Mir.LowChrome |
4149 | } |
4150 | } |
4151 | } |
4152 | @@ -950,21 +959,21 @@ |
4153 | loadShell("phone"); |
4154 | swipeAwayGreeter(); |
4155 | var item = findChild(shell, "inputMethod"); |
4156 | - var surface = SurfaceManager.inputMethodSurface; |
4157 | - |
4158 | - surface.setState(Mir.MinimizedState); |
4159 | - tryCompare(item, "visible", false); |
4160 | - |
4161 | - surface.setState(Mir.RestoredState); |
4162 | - tryCompare(item, "visible", true); |
4163 | - |
4164 | - surface.setState(Mir.MinimizedState); |
4165 | - tryCompare(item, "visible", false); |
4166 | - |
4167 | - surface.setState(Mir.MaximizedState); |
4168 | - tryCompare(item, "visible", true); |
4169 | - |
4170 | - surface.setState(Mir.MinimizedState); |
4171 | + var surface = topLevelSurfaceList.inputMethodSurface; |
4172 | + |
4173 | + surface.requestState(Mir.MinimizedState); |
4174 | + tryCompare(item, "visible", false); |
4175 | + |
4176 | + surface.requestState(Mir.RestoredState); |
4177 | + tryCompare(item, "visible", true); |
4178 | + |
4179 | + surface.requestState(Mir.MinimizedState); |
4180 | + tryCompare(item, "visible", false); |
4181 | + |
4182 | + surface.requestState(Mir.MaximizedState); |
4183 | + tryCompare(item, "visible", true); |
4184 | + |
4185 | + surface.requestState(Mir.MinimizedState); |
4186 | tryCompare(item, "visible", false); |
4187 | } |
4188 | |
4189 | @@ -2397,7 +2406,7 @@ |
4190 | |
4191 | compare(launcher.lockedVisible, true); |
4192 | |
4193 | - app.surfaceList.get(0).state = Mir.FullscreenState; |
4194 | + app.surfaceList.get(0).requestState(Mir.FullscreenState); |
4195 | |
4196 | tryCompare(launcher, "lockedVisible", false); |
4197 | } |
4198 | @@ -2584,7 +2593,7 @@ |
4199 | verify(promptSurface); |
4200 | tryCompare(appSurface, "keymap", promptSurface.keymap); |
4201 | // ... and that the controller's surface keymap is also the same |
4202 | - tryCompare(MirFocusController.focusedSurface, "keymap", "sk"); |
4203 | + tryCompare(topLevelSurfaceList.focusedSurface, "keymap", "sk"); |
4204 | app.promptSurfaceList.get(0).close(); |
4205 | |
4206 | // switch to next keymap, should go to "cz+qwerty" |
4207 | @@ -2702,7 +2711,6 @@ |
4208 | return [ |
4209 | {tag: "no need to displace", windowHeight: units.gu(10), windowY: units.gu(5), targetDisplacement: units.gu(5), oskEnabled: true}, |
4210 | {tag: "displace to top", windowHeight: units.gu(50), windowY: units.gu(10), targetDisplacement: PanelState.panelHeight, oskEnabled: true}, |
4211 | - {tag: "displace to top", windowHeight: units.gu(50), windowY: units.gu(10), targetDisplacement: PanelState.panelHeight, oskEnabled: true}, |
4212 | {tag: "osk not on this screen", windowHeight: units.gu(40), windowY: units.gu(10), targetDisplacement: units.gu(10), oskEnabled: false}, |
4213 | ] |
4214 | } |
4215 | @@ -2714,24 +2722,24 @@ |
4216 | swipeAwayGreeter(); |
4217 | shell.oskEnabled = data.oskEnabled; |
4218 | |
4219 | - var oldOSKState = SurfaceManager.inputMethodSurface.state; |
4220 | - SurfaceManager.inputMethodSurface.state = Mir.RestoredState; |
4221 | + var oldOSKState = topLevelSurfaceList.inputMethodSurface.state; |
4222 | + topLevelSurfaceList.inputMethodSurface.requestState(Mir.RestoredState); |
4223 | var appRepeater = findChild(shell, "appRepeater"); |
4224 | var dashAppDelegate = appRepeater.itemAt(0); |
4225 | verify(dashAppDelegate); |
4226 | dashAppDelegate.requestedHeight = data.windowHeight; |
4227 | dashAppDelegate.requestedY = data.windowY; |
4228 | - SurfaceManager.inputMethodSurface.setInputBounds(Qt.rect(0, 0, 0, 0)); |
4229 | + topLevelSurfaceList.inputMethodSurface.setInputBounds(Qt.rect(0, 0, 0, 0)); |
4230 | var initialY = dashAppDelegate.y; |
4231 | print("intial", initialY, "panel", PanelState.panelHeight); |
4232 | verify(initialY > PanelState.panelHeight); |
4233 | |
4234 | - SurfaceManager.inputMethodSurface.setInputBounds(Qt.rect(0, root.height / 2, root.width, root.height / 2)); |
4235 | + topLevelSurfaceList.inputMethodSurface.setInputBounds(Qt.rect(0, root.height / 2, root.width, root.height / 2)); |
4236 | tryCompare(dashAppDelegate, "y", data.targetDisplacement); |
4237 | |
4238 | - SurfaceManager.inputMethodSurface.setInputBounds(Qt.rect(0, 0, 0, 0)); |
4239 | + topLevelSurfaceList.inputMethodSurface.setInputBounds(Qt.rect(0, 0, 0, 0)); |
4240 | tryCompare(dashAppDelegate, "y", initialY); |
4241 | - SurfaceManager.inputMethodSurface.state = oldOSKState; |
4242 | + topLevelSurfaceList.inputMethodSurface.requestState(oldOSKState); |
4243 | } |
4244 | |
4245 | function test_cursorHidingWithFullscreenApp() { |