Merge lp:~dandrader/qtmir/miral-surfacemanager into lp:~unity-team/qtmir/miral-qt-integration
- miral-surfacemanager
- Merge into miral-qt-integration
Proposed by
Daniel d'Andrada
Status: | Merged |
---|---|
Approved by: | Gerry Boland |
Approved revision: | 579 |
Merged at revision: | 581 |
Proposed branch: | lp:~dandrader/qtmir/miral-surfacemanager |
Merge into: | lp:~unity-team/qtmir/miral-qt-integration |
Diff against target: |
1582 lines (+261/-1156) 13 files modified
src/modules/Unity/Application/CMakeLists.txt (+2/-4) src/modules/Unity/Application/application.h (+1/-2) src/modules/Unity/Application/application_manager.cpp (+11/-0) src/modules/Unity/Application/application_manager.h (+6/-5) src/modules/Unity/Application/applicationmanagerinterface.h (+0/-35) src/modules/Unity/Application/mirsurfaceinterface.h (+0/-1) src/modules/Unity/Application/plugin.cpp (+3/-4) src/modules/Unity/Application/surfacemanager.cpp (+166/-0) src/modules/Unity/Application/surfacemanager.h (+72/-0) src/modules/Unity/Application/toplevelwindowmodel.cpp (+0/-691) src/modules/Unity/Application/toplevelwindowmodel.h (+0/-161) src/modules/Unity/Application/window.cpp (+0/-186) src/modules/Unity/Application/window.h (+0/-67) |
To merge this branch: | bzr merge lp:~dandrader/qtmir/miral-surfacemanager |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gerry Boland (community) | Approve | ||
Review via email: mp+310909@code.launchpad.net |
Commit message
Move TopLevelWindowModel out of qtmir. Export a SurfaceManager instead
Description of the change
Dramatically improves the interface between qtmir and unity8
Needs:
https:/
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/modules/Unity/Application/CMakeLists.txt' |
2 | --- src/modules/Unity/Application/CMakeLists.txt 2016-11-03 20:17:46 +0000 |
3 | +++ src/modules/Unity/Application/CMakeLists.txt 2016-11-15 17:55:38 +0000 |
4 | @@ -45,14 +45,13 @@ |
5 | session.cpp |
6 | sessionmanager.cpp |
7 | sharedwakelock.cpp |
8 | + surfacemanager.cpp |
9 | upstart/applicationinfo.cpp |
10 | upstart/taskcontroller.cpp |
11 | timer.cpp |
12 | timesource.cpp |
13 | - toplevelwindowmodel.cpp |
14 | tracepoints.c |
15 | settings.cpp |
16 | - window.cpp |
17 | windowmodel.cpp |
18 | # We need to run moc on these headers |
19 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h |
20 | @@ -61,8 +60,7 @@ |
21 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h |
22 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceItemInterface.h |
23 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceListInterface.h |
24 | - ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/TopLevelWindowModelInterface.h |
25 | - ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/WindowInterface.h |
26 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/SurfaceManagerInterface.h |
27 | # Feed the automoc monster |
28 | session_interface.h |
29 | applicationinfo.h |
30 | |
31 | === modified file 'src/modules/Unity/Application/application.h' |
32 | --- src/modules/Unity/Application/application.h 2016-11-03 20:17:46 +0000 |
33 | +++ src/modules/Unity/Application/application.h 2016-11-15 17:55:38 +0000 |
34 | @@ -103,6 +103,7 @@ |
35 | unity::shell::application::MirSurfaceListInterface* surfaceList() const override; |
36 | unity::shell::application::MirSurfaceListInterface* promptSurfaceList() const override; |
37 | int surfaceCount() const override { return surfaceList()->count(); } |
38 | + void close() override; |
39 | |
40 | ProcessState processState() const { return m_processState; } |
41 | void setProcessState(ProcessState value); |
42 | @@ -119,8 +120,6 @@ |
43 | |
44 | pid_t pid() const; |
45 | |
46 | - void close(); |
47 | - |
48 | // internal as in "not exposed in unity-api", so qtmir-internal. |
49 | InternalState internalState() const { return m_state; } |
50 | |
51 | |
52 | === modified file 'src/modules/Unity/Application/application_manager.cpp' |
53 | --- src/modules/Unity/Application/application_manager.cpp 2016-11-03 20:17:46 +0000 |
54 | +++ src/modules/Unity/Application/application_manager.cpp 2016-11-15 17:55:38 +0000 |
55 | @@ -577,6 +577,17 @@ |
56 | authorized = true; |
57 | } |
58 | |
59 | + |
60 | +unityapi::ApplicationInfoInterface *ApplicationManager::findApplicationWithSurface(unityapi::MirSurfaceInterface* surface) |
61 | +{ |
62 | + if (!surface) |
63 | + return nullptr; |
64 | + |
65 | + auto qtmirSurface = static_cast<qtmir::MirSurfaceInterface*>(surface); |
66 | + |
67 | + return findApplicationWithPid(miral::pid_of(qtmirSurface->session()->session())); |
68 | +} |
69 | + |
70 | Application* ApplicationManager::findApplicationWithSession(const std::shared_ptr<ms::Session> &session) |
71 | { |
72 | if (!session) |
73 | |
74 | === modified file 'src/modules/Unity/Application/application_manager.h' |
75 | --- src/modules/Unity/Application/application_manager.h 2016-11-03 20:17:46 +0000 |
76 | +++ src/modules/Unity/Application/application_manager.h 2016-11-15 17:55:38 +0000 |
77 | @@ -26,9 +26,11 @@ |
78 | |
79 | // local |
80 | #include "application.h" |
81 | -#include "applicationmanagerinterface.h" |
82 | #include "taskcontroller.h" |
83 | |
84 | +// Unity API |
85 | +#include <unity/shell/application/ApplicationManagerInterface.h> |
86 | + |
87 | namespace mir { |
88 | namespace scene { |
89 | class Session; |
90 | @@ -53,7 +55,7 @@ |
91 | class SharedWakelock; |
92 | class SettingsInterface; |
93 | |
94 | -class ApplicationManager : public ApplicationManagerInterface |
95 | +class ApplicationManager : public unity::shell::application::ApplicationManagerInterface |
96 | { |
97 | Q_OBJECT |
98 | |
99 | @@ -81,13 +83,11 @@ |
100 | QString focusedApplicationId() const override; |
101 | Q_INVOKABLE qtmir::Application* get(int index) const override; |
102 | Q_INVOKABLE qtmir::Application* findApplication(const QString &appId) const override; |
103 | + unity::shell::application::ApplicationInfoInterface *findApplicationWithSurface(unity::shell::application::MirSurfaceInterface* surface) override; |
104 | Q_INVOKABLE bool requestFocusApplication(const QString &appId) override; |
105 | Q_INVOKABLE qtmir::Application* startApplication(const QString &appId, const QStringList &arguments = QStringList()) override; |
106 | Q_INVOKABLE bool stopApplication(const QString &appId) override; |
107 | |
108 | - // qtmir::ApplicationManagerInterface |
109 | - Application* findApplicationWithSession(const std::shared_ptr<mir::scene::Session> &session) override; |
110 | - |
111 | // QAbstractListModel |
112 | int rowCount(const QModelIndex & parent = QModelIndex()) const override; |
113 | QVariant data(const QModelIndex & index, int role) const override; |
114 | @@ -119,6 +119,7 @@ |
115 | void onApplicationClosing(Application *application); |
116 | |
117 | private: |
118 | + Application* findApplicationWithSession(const std::shared_ptr<mir::scene::Session> &session); |
119 | void setFocused(Application *application); |
120 | void add(Application *application); |
121 | void remove(Application* application); |
122 | |
123 | === removed file 'src/modules/Unity/Application/applicationmanagerinterface.h' |
124 | --- src/modules/Unity/Application/applicationmanagerinterface.h 2016-11-03 20:17:46 +0000 |
125 | +++ src/modules/Unity/Application/applicationmanagerinterface.h 1970-01-01 00:00:00 +0000 |
126 | @@ -1,35 +0,0 @@ |
127 | -/* |
128 | - * Copyright (C) 2016 Canonical, Ltd. |
129 | - * |
130 | - * This program is free software: you can redistribute it and/or modify it under |
131 | - * the terms of the GNU Lesser General Public License version 3, as published by |
132 | - * the Free Software Foundation. |
133 | - * |
134 | - * This program is distributed in the hope that it will be useful, but WITHOUT |
135 | - * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
136 | - * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
137 | - * Lesser General Public License for more details. |
138 | - * |
139 | - * You should have received a copy of the GNU Lesser General Public License |
140 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
141 | - */ |
142 | - |
143 | -#ifndef QTMIR_APPLICATION_MANAGER_INTERFACE_H |
144 | -#define QTMIR_APPLICATION_MANAGER_INTERFACE_H |
145 | - |
146 | -// Unity API |
147 | -#include <unity/shell/application/ApplicationManagerInterface.h> |
148 | - |
149 | -namespace qtmir { |
150 | - |
151 | -class ApplicationManagerInterface : public unity::shell::application::ApplicationManagerInterface |
152 | -{ |
153 | -public: |
154 | - ApplicationManagerInterface(QObject *parent) : unity::shell::application::ApplicationManagerInterface(parent) {} |
155 | - |
156 | - virtual Application* findApplicationWithSession(const std::shared_ptr<mir::scene::Session> &session) = 0; |
157 | -}; |
158 | - |
159 | -} // namespace qtmir |
160 | - |
161 | -#endif // QTMIR_APPLICATION_MANAGER_INTERFACE_H |
162 | |
163 | === modified file 'src/modules/Unity/Application/mirsurfaceinterface.h' |
164 | --- src/modules/Unity/Application/mirsurfaceinterface.h 2016-11-03 20:17:46 +0000 |
165 | +++ src/modules/Unity/Application/mirsurfaceinterface.h 2016-11-15 17:55:38 +0000 |
166 | @@ -116,7 +116,6 @@ |
167 | void ready(); |
168 | void cursorChanged(const QCursor &cursor); |
169 | void raiseRequested(); |
170 | - void closeRequested(); |
171 | void framesPosted(); |
172 | void isBeingDisplayedChanged(); |
173 | void frameDropped(); |
174 | |
175 | === modified file 'src/modules/Unity/Application/plugin.cpp' |
176 | --- src/modules/Unity/Application/plugin.cpp 2016-11-03 20:17:46 +0000 |
177 | +++ src/modules/Unity/Application/plugin.cpp 2016-11-15 17:55:38 +0000 |
178 | @@ -23,9 +23,8 @@ |
179 | #include "mirsurfaceinterface.h" |
180 | #include "mirsurfaceitem.h" |
181 | #include "mirsurfacelistmodel.h" |
182 | -#include "toplevelwindowmodel.h" |
183 | -#include "window.h" |
184 | #include "windowmodel.h" |
185 | +#include "surfacemanager.h" |
186 | |
187 | // platforms/mirserver |
188 | #include <mirsingleton.h> |
189 | @@ -65,8 +64,8 @@ |
190 | qRegisterMetaType<qtmir::Application*>("Application*"); |
191 | qRegisterMetaType<unity::shell::application::MirSurfaceInterface*>("MirSurfaceInterface*"); |
192 | qRegisterMetaType<unity::shell::application::MirSurfaceListInterface*>("unity::shell::application::MirSurfaceListInterface*"); |
193 | + qRegisterMetaType<unity::shell::application::SurfaceManagerInterface*>("unity::shell::application::SurfaceManagerInterface*"); |
194 | qRegisterMetaType<MirSurfaceAttrib>("MirSurfaceAttrib"); |
195 | - qRegisterMetaType<unity::shell::application::WindowInterface*>("unity::shell::application::WindowInterface*"); |
196 | |
197 | qmlRegisterUncreatableType<unity::shell::application::ApplicationManagerInterface>( |
198 | uri, 0, 1, "ApplicationManagerInterface", "Abstract interface. Cannot be created in QML"); |
199 | @@ -80,9 +79,9 @@ |
200 | uri, 0, 1, "MirSurface", "MirSurface can't be instantiated from QML"); |
201 | qmlRegisterType<qtmir::MirSurfaceItem>(uri, 0, 1, "MirSurfaceItem"); |
202 | qmlRegisterSingletonType<qtmir::Mir>(uri, 0, 1, "Mir", mirSingleton); |
203 | + qmlRegisterType<qtmir::SurfaceManager>(uri, 0, 1, "SurfaceManager"); |
204 | |
205 | qmlRegisterType<qtmir::WindowModel>(uri, 0, 1, "WindowModel"); |
206 | - qmlRegisterType<qtmir::TopLevelWindowModel>(uri, 0, 1, "TopLevelWindowModel"); |
207 | } |
208 | |
209 | virtual void initializeEngine(QQmlEngine *engine, const char *uri) |
210 | |
211 | === added file 'src/modules/Unity/Application/surfacemanager.cpp' |
212 | --- src/modules/Unity/Application/surfacemanager.cpp 1970-01-01 00:00:00 +0000 |
213 | +++ src/modules/Unity/Application/surfacemanager.cpp 2016-11-15 17:55:38 +0000 |
214 | @@ -0,0 +1,166 @@ |
215 | +/* |
216 | + * Copyright (C) 2016 Canonical, Ltd. |
217 | + * |
218 | + * This program is free software: you can redistribute it and/or modify it under |
219 | + * the terms of the GNU Lesser General Public License version 3, as published by |
220 | + * the Free Software Foundation. |
221 | + * |
222 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
223 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
224 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
225 | + * Lesser General Public License for more details. |
226 | + * |
227 | + * You should have received a copy of the GNU Lesser General Public License |
228 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
229 | + */ |
230 | + |
231 | +#include "surfacemanager.h" |
232 | + |
233 | +#include "mirsurface.h" |
234 | +#include "sessionmanager.h" |
235 | + |
236 | +// mirserver |
237 | +#include "nativeinterface.h" |
238 | + |
239 | +// Qt |
240 | +#include <QGuiApplication> |
241 | + |
242 | +Q_LOGGING_CATEGORY(QTMIR_SURFACEMANAGER, "qtmir.surfacemanager", QtDebugMsg) |
243 | + |
244 | +#define DEBUG_MSG qCDebug(QTMIR_SURFACEMANAGER).nospace().noquote() << __func__ |
245 | + |
246 | +using namespace qtmir; |
247 | +namespace unityapi = unity::shell::application; |
248 | + |
249 | +SurfaceManager::SurfaceManager(QObject *) |
250 | +{ |
251 | + DEBUG_MSG << "()"; |
252 | + |
253 | + auto nativeInterface = dynamic_cast<NativeInterface*>(QGuiApplication::platformNativeInterface()); |
254 | + |
255 | + if (!nativeInterface) { |
256 | + qFatal("ERROR: Unity.Application QML plugin requires use of the 'mirserver' QPA plugin"); |
257 | + } |
258 | + |
259 | + m_windowController = static_cast<WindowControllerInterface*>(nativeInterface->nativeResourceForIntegration("WindowController")); |
260 | + |
261 | + auto windowModel = static_cast<WindowModelNotifier*>(nativeInterface->nativeResourceForIntegration("WindowModelNotifier")); |
262 | + connectToWindowModelNotifier(windowModel); |
263 | + |
264 | + m_sessionManager = SessionManager::singleton(); |
265 | +} |
266 | + |
267 | +void SurfaceManager::connectToWindowModelNotifier(WindowModelNotifier *notifier) |
268 | +{ |
269 | + connect(notifier, &WindowModelNotifier::windowAdded, this, &SurfaceManager::onWindowAdded, Qt::QueuedConnection); |
270 | + connect(notifier, &WindowModelNotifier::windowRemoved, this, &SurfaceManager::onWindowRemoved, Qt::QueuedConnection); |
271 | + connect(notifier, &WindowModelNotifier::windowReady, this, &SurfaceManager::onWindowReady, Qt::QueuedConnection); |
272 | + connect(notifier, &WindowModelNotifier::windowMoved, this, &SurfaceManager::onWindowMoved, Qt::QueuedConnection); |
273 | + connect(notifier, &WindowModelNotifier::windowStateChanged, this, &SurfaceManager::onWindowStateChanged, Qt::QueuedConnection); |
274 | + connect(notifier, &WindowModelNotifier::windowFocusChanged, this, &SurfaceManager::onWindowFocusChanged, Qt::QueuedConnection); |
275 | + connect(notifier, &WindowModelNotifier::windowsRaised, this, &SurfaceManager::onWindowsRaised, Qt::QueuedConnection); |
276 | + connect(notifier, &WindowModelNotifier::modificationsStarted, this, &SurfaceManager::modificationsStarted, Qt::QueuedConnection); |
277 | + connect(notifier, &WindowModelNotifier::modificationsEnded, this, &SurfaceManager::modificationsEnded, Qt::QueuedConnection); |
278 | +} |
279 | + |
280 | +void SurfaceManager::rememberMirSurface(MirSurface *surface) |
281 | +{ |
282 | + m_allSurfaces.append(surface); |
283 | +} |
284 | + |
285 | +void SurfaceManager::forgetMirSurface(const miral::Window &window) |
286 | +{ |
287 | + for (int i = 0; i < m_allSurfaces.count(); ++i) { |
288 | + if (m_allSurfaces[i]->window() == window) { |
289 | + m_allSurfaces.removeAt(i); |
290 | + return; |
291 | + } |
292 | + } |
293 | +} |
294 | +void SurfaceManager::onWindowAdded(const NewWindow &window) |
295 | +{ |
296 | + auto mirSession = window.windowInfo.window().application(); |
297 | + SessionInterface* session = m_sessionManager->findSession(mirSession.get()); |
298 | + |
299 | + auto surface = new MirSurface(window, m_windowController, session); |
300 | + rememberMirSurface(surface); |
301 | + |
302 | + if (session) |
303 | + session->registerSurface(surface); |
304 | + |
305 | + Q_EMIT surfaceCreated(surface); |
306 | +} |
307 | + |
308 | +void SurfaceManager::onWindowRemoved(const miral::WindowInfo &windowInfo) |
309 | +{ |
310 | + MirSurface *surface = find(windowInfo); |
311 | + forgetMirSurface(windowInfo.window()); |
312 | + surface->setLive(false); |
313 | +} |
314 | + |
315 | +MirSurface *SurfaceManager::find(const miral::WindowInfo &needle) const |
316 | +{ |
317 | + return find(needle.window()); |
318 | +} |
319 | + |
320 | +MirSurface *SurfaceManager::find(const miral::Window &window) const |
321 | +{ |
322 | + Q_FOREACH(const auto surface, m_allSurfaces) { |
323 | + if (surface->window() == window) { |
324 | + return surface; |
325 | + } |
326 | + } |
327 | + return nullptr; |
328 | +} |
329 | + |
330 | +void SurfaceManager::onWindowReady(const miral::WindowInfo &windowInfo) |
331 | +{ |
332 | + if (auto mirSurface = find(windowInfo)) { |
333 | + mirSurface->setReady(); |
334 | + } |
335 | +} |
336 | + |
337 | +void SurfaceManager::onWindowMoved(const miral::WindowInfo &windowInfo, const QPoint topLeft) |
338 | +{ |
339 | + if (auto mirSurface = find(windowInfo)) { |
340 | + mirSurface->setPosition(topLeft); |
341 | + } |
342 | +} |
343 | + |
344 | +void SurfaceManager::onWindowFocusChanged(const miral::WindowInfo &windowInfo, bool focused) |
345 | +{ |
346 | + if (auto mirSurface = find(windowInfo)) { |
347 | + mirSurface->setFocused(focused); |
348 | + } |
349 | +} |
350 | + |
351 | +void SurfaceManager::onWindowStateChanged(const miral::WindowInfo &windowInfo, Mir::State state) |
352 | +{ |
353 | + if (auto mirSurface = find(windowInfo)) { |
354 | + mirSurface->updateState(state); |
355 | + } |
356 | +} |
357 | + |
358 | +void SurfaceManager::onWindowsRaised(const std::vector<miral::Window> &windows) |
359 | +{ |
360 | + // sad inefficiency when crossing API boundaries (from miral to qt) |
361 | + const int raiseCount = windows.size(); |
362 | + QVector<unityapi::MirSurfaceInterface*> surfaces(raiseCount); |
363 | + for (int i = 0; i < raiseCount; i++) { |
364 | + auto mirSurface = find(windows[i]); |
365 | + surfaces.append(mirSurface); |
366 | + } |
367 | + Q_EMIT surfacesRaised(surfaces); |
368 | +} |
369 | + |
370 | +void SurfaceManager::raise(unityapi::MirSurfaceInterface *surface) |
371 | +{ |
372 | + auto qtmirSurface = static_cast<qtmir::MirSurface*>(surface); |
373 | + m_windowController->raise(qtmirSurface->window()); |
374 | +} |
375 | + |
376 | +void SurfaceManager::activate(unityapi::MirSurfaceInterface *surface) |
377 | +{ |
378 | + auto qtmirSurface = static_cast<qtmir::MirSurface*>(surface); |
379 | + m_windowController->activate(qtmirSurface ? qtmirSurface->window() : miral::Window()); |
380 | +} |
381 | |
382 | === added file 'src/modules/Unity/Application/surfacemanager.h' |
383 | --- src/modules/Unity/Application/surfacemanager.h 1970-01-01 00:00:00 +0000 |
384 | +++ src/modules/Unity/Application/surfacemanager.h 2016-11-15 17:55:38 +0000 |
385 | @@ -0,0 +1,72 @@ |
386 | +/* |
387 | + * Copyright (C) 2016 Canonical, Ltd. |
388 | + * |
389 | + * This program is free software: you can redistribute it and/or modify it under |
390 | + * the terms of the GNU Lesser General Public License version 3, as published by |
391 | + * the Free Software Foundation. |
392 | + * |
393 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
394 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
395 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
396 | + * Lesser General Public License for more details. |
397 | + * |
398 | + * You should have received a copy of the GNU Lesser General Public License |
399 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
400 | + */ |
401 | + |
402 | +#ifndef QTMIR_SURFACEMANAGER_H |
403 | +#define QTMIR_SURFACEMANAGER_H |
404 | + |
405 | +// common |
406 | +#include "windowmodelnotifier.h" |
407 | + |
408 | +// Unity API |
409 | +#include <unity/shell/application/SurfaceManagerInterface.h> |
410 | + |
411 | +#include <QVector> |
412 | +#include <QLoggingCategory> |
413 | + |
414 | +Q_DECLARE_LOGGING_CATEGORY(QTMIR_SURFACEMANAGER) |
415 | + |
416 | +namespace qtmir { |
417 | + |
418 | +class MirSurface; |
419 | +class SessionManager; |
420 | +class WindowControllerInterface; |
421 | + |
422 | +class SurfaceManager : public unity::shell::application::SurfaceManagerInterface |
423 | +{ |
424 | + Q_OBJECT |
425 | + |
426 | +public: |
427 | + explicit SurfaceManager(QObject *parent = 0); |
428 | + virtual ~SurfaceManager() {} |
429 | + |
430 | + void raise(unity::shell::application::MirSurfaceInterface *surface) override; |
431 | + void activate(unity::shell::application::MirSurfaceInterface *surface) override; |
432 | + |
433 | +private Q_SLOTS: |
434 | + void onWindowAdded(const qtmir::NewWindow &windowInfo); |
435 | + void onWindowRemoved(const miral::WindowInfo &windowInfo); |
436 | + void onWindowReady(const miral::WindowInfo &windowInfo); |
437 | + void onWindowMoved(const miral::WindowInfo &windowInfo, const QPoint topLeft); |
438 | + void onWindowStateChanged(const miral::WindowInfo &windowInfo, Mir::State state); |
439 | + void onWindowFocusChanged(const miral::WindowInfo &windowInfo, bool focused); |
440 | + void onWindowsRaised(const std::vector<miral::Window> &windows); |
441 | + |
442 | +private: |
443 | + void connectToWindowModelNotifier(WindowModelNotifier *notifier); |
444 | + void rememberMirSurface(MirSurface *surface); |
445 | + void forgetMirSurface(const miral::Window &window); |
446 | + MirSurface* find(const miral::WindowInfo &needle) const; |
447 | + MirSurface* find(const miral::Window &needle) const; |
448 | + |
449 | + QVector<MirSurface*> m_allSurfaces; |
450 | + |
451 | + WindowControllerInterface *m_windowController; |
452 | + SessionManager* m_sessionManager; |
453 | +}; |
454 | + |
455 | +} // namespace qtmir |
456 | + |
457 | +#endif // QTMIR_SURFACEMANAGER_H |
458 | |
459 | === removed file 'src/modules/Unity/Application/toplevelwindowmodel.cpp' |
460 | --- src/modules/Unity/Application/toplevelwindowmodel.cpp 2016-11-09 14:18:17 +0000 |
461 | +++ src/modules/Unity/Application/toplevelwindowmodel.cpp 1970-01-01 00:00:00 +0000 |
462 | @@ -1,691 +0,0 @@ |
463 | -/* |
464 | - * Copyright (C) 2016 Canonical, Ltd. |
465 | - * |
466 | - * This program is free software: you can redistribute it and/or modify it under |
467 | - * the terms of the GNU Lesser General Public License version 3, as published by |
468 | - * the Free Software Foundation. |
469 | - * |
470 | - * This program is distributed in the hope that it will be useful, but WITHOUT |
471 | - * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
472 | - * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
473 | - * Lesser General Public License for more details. |
474 | - * |
475 | - * You should have received a copy of the GNU Lesser General Public License |
476 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
477 | - */ |
478 | - |
479 | -#include "toplevelwindowmodel.h" |
480 | - |
481 | -#include "application.h" |
482 | -#include "application_manager.h" |
483 | -#include "mirsurface.h" |
484 | -#include "sessionmanager.h" |
485 | - |
486 | -// mirserver |
487 | -#include "nativeinterface.h" |
488 | - |
489 | -// Qt |
490 | -#include <QGuiApplication> |
491 | -#include <QDebug> |
492 | - |
493 | -Q_LOGGING_CATEGORY(QTMIR_TOPLEVELWINDOWMODEL, "qtmir.toplevelwindowmodel", QtDebugMsg) |
494 | - |
495 | -#define DEBUG_MSG qCDebug(QTMIR_TOPLEVELWINDOWMODEL).nospace().noquote() << __func__ |
496 | - |
497 | -using namespace qtmir; |
498 | -namespace unityapi = unity::shell::application; |
499 | - |
500 | -TopLevelWindowModel::TopLevelWindowModel() |
501 | -{ |
502 | - auto nativeInterface = dynamic_cast<NativeInterface*>(QGuiApplication::platformNativeInterface()); |
503 | - |
504 | - if (!nativeInterface) { |
505 | - qFatal("ERROR: Unity.Application QML plugin requires use of the 'mirserver' QPA plugin"); |
506 | - } |
507 | - |
508 | - m_windowController = static_cast<WindowControllerInterface*>(nativeInterface->nativeResourceForIntegration("WindowController")); |
509 | - |
510 | - auto windowModel = static_cast<WindowModelNotifier*>(nativeInterface->nativeResourceForIntegration("WindowModelNotifier")); |
511 | - connectToWindowModelNotifier(windowModel); |
512 | - |
513 | - setApplicationManager(ApplicationManager::singleton()); |
514 | - |
515 | - m_sessionManager = SessionManager::singleton(); |
516 | -} |
517 | - |
518 | -TopLevelWindowModel::TopLevelWindowModel(WindowModelNotifier *notifier, |
519 | - WindowControllerInterface *controller) |
520 | - : m_windowController(controller) |
521 | -{ |
522 | - connectToWindowModelNotifier(notifier); |
523 | -} |
524 | - |
525 | -void TopLevelWindowModel::setApplicationManager(ApplicationManagerInterface* value) |
526 | -{ |
527 | - if (m_applicationManager == value) { |
528 | - return; |
529 | - } |
530 | - |
531 | - Q_ASSERT(m_modelState == IdleState); |
532 | - m_modelState = ResettingState; |
533 | - |
534 | - beginResetModel(); |
535 | - |
536 | - if (m_applicationManager) { |
537 | - m_windowModel.clear(); |
538 | - disconnect(m_applicationManager, 0, this, 0); |
539 | - } |
540 | - |
541 | - m_applicationManager = value; |
542 | - |
543 | - if (m_applicationManager) { |
544 | - connect(m_applicationManager, &QAbstractItemModel::rowsInserted, |
545 | - this, [this](const QModelIndex &/*parent*/, int first, int last) { |
546 | - for (int i = first; i <= last; ++i) { |
547 | - auto application = m_applicationManager->get(i); |
548 | - addApplication(static_cast<Application*>(application)); |
549 | - } |
550 | - }); |
551 | - |
552 | - connect(m_applicationManager, &QAbstractItemModel::rowsAboutToBeRemoved, |
553 | - this, [this](const QModelIndex &/*parent*/, int first, int last) { |
554 | - for (int i = first; i <= last; ++i) { |
555 | - auto application = m_applicationManager->get(i); |
556 | - removeApplication(static_cast<Application*>(application)); |
557 | - } |
558 | - }); |
559 | - |
560 | - for (int i = 0; i < m_applicationManager->rowCount(); ++i) { |
561 | - auto application = m_applicationManager->get(i); |
562 | - addApplication(static_cast<Application*>(application)); |
563 | - } |
564 | - } |
565 | - |
566 | - endResetModel(); |
567 | - m_modelState = IdleState; |
568 | -} |
569 | - |
570 | -void TopLevelWindowModel::addApplication(Application *application) |
571 | -{ |
572 | - DEBUG_MSG << "(" << application->appId() << ")"; |
573 | - |
574 | - if (application->state() != unityapi::ApplicationInfoInterface::Stopped && application->surfaceList()->count() == 0) { |
575 | - prependPlaceholder(application); |
576 | - } |
577 | -} |
578 | - |
579 | -void TopLevelWindowModel::removeApplication(Application *application) |
580 | -{ |
581 | - DEBUG_MSG << "(" << application->appId() << ")"; |
582 | - |
583 | - Q_ASSERT(m_modelState == IdleState); |
584 | - |
585 | - int i = 0; |
586 | - while (i < m_windowModel.count()) { |
587 | - if (m_windowModel.at(i).application == application) { |
588 | - removeAt(i); |
589 | - } else { |
590 | - ++i; |
591 | - } |
592 | - } |
593 | -} |
594 | - |
595 | -void TopLevelWindowModel::prependPlaceholder(Application *application) |
596 | -{ |
597 | - DEBUG_MSG << "(" << application->appId() << ")"; |
598 | - |
599 | - prependSurfaceHelper(nullptr, application); |
600 | -} |
601 | - |
602 | -void TopLevelWindowModel::prependSurface(MirSurface *surface, Application *application) |
603 | -{ |
604 | - Q_ASSERT(surface != nullptr); |
605 | - |
606 | - bool filledPlaceholder = false; |
607 | - for (int i = 0; i < m_windowModel.count() && !filledPlaceholder; ++i) { |
608 | - ModelEntry &entry = m_windowModel[i]; |
609 | - if (entry.application == application && entry.window->surface() == nullptr) { |
610 | - entry.window->setSurface(surface); |
611 | - connectSurface(surface); |
612 | - DEBUG_MSG << " appId=" << application->appId() << " surface=" << surface |
613 | - << ", filling out placeholder. after: " << toString(); |
614 | - filledPlaceholder = true; |
615 | - } |
616 | - } |
617 | - |
618 | - if (!filledPlaceholder) { |
619 | - DEBUG_MSG << " appId=" << application->appId() << " surface=" << surface << ", adding new row"; |
620 | - prependSurfaceHelper(surface, application); |
621 | - } |
622 | -} |
623 | - |
624 | -void TopLevelWindowModel::prependSurfaceHelper(MirSurface *surface, Application *application) |
625 | -{ |
626 | - if (m_modelState == IdleState) { |
627 | - m_modelState = InsertingState; |
628 | - beginInsertRows(QModelIndex(), 0 /*first*/, 0 /*last*/); |
629 | - } else { |
630 | - Q_ASSERT(m_modelState == ResettingState); |
631 | - // No point in signaling anything if we're resetting the whole model |
632 | - } |
633 | - |
634 | - int id = generateId(); |
635 | - Window *window = new Window(id); |
636 | - if (surface) { |
637 | - window->setSurface(surface); |
638 | - } |
639 | - m_windowModel.prepend(ModelEntry(window, application)); |
640 | - if (surface) { |
641 | - connectSurface(surface); |
642 | - } |
643 | - |
644 | - connectWindow(window); |
645 | - |
646 | - if (m_modelState == InsertingState) { |
647 | - endInsertRows(); |
648 | - Q_EMIT countChanged(); |
649 | - Q_EMIT listChanged(); |
650 | - m_modelState = IdleState; |
651 | - } |
652 | - |
653 | - if (!surface) { |
654 | - // focus the newly added window. miral can't help with that as it doesn't know about it. |
655 | - window->setFocused(true); |
656 | - if (m_focusedWindow && m_focusedWindow->surface()) { |
657 | - m_windowController->activate(miral::Window()); |
658 | - } |
659 | - } |
660 | - |
661 | - DEBUG_MSG << " after " << toString(); |
662 | -} |
663 | - |
664 | -void TopLevelWindowModel::connectWindow(Window *window) |
665 | -{ |
666 | - connect(window, &unityapi::WindowInterface::focusRequested, this, [this, window]() { |
667 | - if (!window->surface()) { |
668 | - // miral doesn't know about this window, so we have to do it ourselves |
669 | - window->setFocused(true); |
670 | - raiseId(window->id()); |
671 | - Window *previousWindow = m_focusedWindow; |
672 | - setFocusedWindow(window); |
673 | - if (previousWindow && previousWindow->surface() && previousWindow->surface()->focused()) { |
674 | - m_windowController->activate(miral::Window()); |
675 | - } |
676 | - } |
677 | - }); |
678 | - |
679 | - connect(window, &unityapi::WindowInterface::focusedChanged, this, [this, window](bool focused) { |
680 | - if (window->surface()) { |
681 | - // Condense changes to the focused window |
682 | - // eg: Do focusedWindow=A to focusedWindow=B instead of |
683 | - // focusedWindow=A to focusedWindow=null to focusedWindow=B |
684 | - m_focusedWindowChanged = true; |
685 | - if (focused) { |
686 | - Q_ASSERT(m_newlyFocusedWindow == nullptr); |
687 | - m_newlyFocusedWindow = window; |
688 | - } |
689 | - } |
690 | - }); |
691 | - |
692 | - connect(window, &Window::closeRequested, this, [this, window]() { |
693 | - if (!window->surface()) { |
694 | - int index = indexForId(window->id()); |
695 | - Q_ASSERT(index >= 0); |
696 | - m_windowModel[index].application->close(); |
697 | - } |
698 | - }); |
699 | -} |
700 | - |
701 | -void TopLevelWindowModel::connectSurface(MirSurfaceInterface *surface) |
702 | -{ |
703 | - connect(surface, &MirSurfaceInterface::liveChanged, this, [this, surface](bool live){ |
704 | - if (!live) { |
705 | - onSurfaceDied(surface); |
706 | - } |
707 | - }); |
708 | - connect(surface, &QObject::destroyed, this, [this, surface](){ this->onSurfaceDestroyed(surface); }); |
709 | -} |
710 | - |
711 | -void TopLevelWindowModel::onSurfaceDied(MirSurfaceInterface *surface) |
712 | -{ |
713 | - int i = indexOf(surface); |
714 | - if (i == -1) { |
715 | - return; |
716 | - } |
717 | - |
718 | - auto application = m_windowModel[i].application; |
719 | - |
720 | - // can't be starting if it already has a surface |
721 | - Q_ASSERT(application->state() != unityapi::ApplicationInfoInterface::Starting); |
722 | - |
723 | - if (application->state() == unityapi::ApplicationInfoInterface::Running) { |
724 | - m_windowModel[i].removeOnceSurfaceDestroyed = true; |
725 | - } else { |
726 | - // assume it got killed by the out-of-memory daemon. |
727 | - // |
728 | - // So leave entry in the model and only remove its surface, so shell can display a screenshot |
729 | - // in its place. |
730 | - m_windowModel[i].removeOnceSurfaceDestroyed = false; |
731 | - } |
732 | -} |
733 | - |
734 | -void TopLevelWindowModel::onSurfaceDestroyed(MirSurfaceInterface *surface) |
735 | -{ |
736 | - int i = indexOf(surface); |
737 | - if (i == -1) { |
738 | - return; |
739 | - } |
740 | - |
741 | - if (m_windowModel[i].removeOnceSurfaceDestroyed) { |
742 | - removeAt(i); |
743 | - } else { |
744 | - auto window = m_windowModel[i].window; |
745 | - window->setSurface(nullptr); |
746 | - window->setFocused(false); |
747 | - DEBUG_MSG << " Removed surface from entry. After: " << toString(); |
748 | - } |
749 | -} |
750 | - |
751 | -void TopLevelWindowModel::connectToWindowModelNotifier(WindowModelNotifier *notifier) |
752 | -{ |
753 | - connect(notifier, &WindowModelNotifier::windowAdded, this, &TopLevelWindowModel::onWindowAdded, Qt::QueuedConnection); |
754 | - connect(notifier, &WindowModelNotifier::windowRemoved, this, &TopLevelWindowModel::onWindowRemoved, Qt::QueuedConnection); |
755 | - connect(notifier, &WindowModelNotifier::windowReady, this, &TopLevelWindowModel::onWindowReady, Qt::QueuedConnection); |
756 | - connect(notifier, &WindowModelNotifier::windowMoved, this, &TopLevelWindowModel::onWindowMoved, Qt::QueuedConnection); |
757 | - connect(notifier, &WindowModelNotifier::windowStateChanged, this, &TopLevelWindowModel::onWindowStateChanged, Qt::QueuedConnection); |
758 | - connect(notifier, &WindowModelNotifier::windowFocusChanged, this, &TopLevelWindowModel::onWindowFocusChanged, Qt::QueuedConnection); |
759 | - connect(notifier, &WindowModelNotifier::windowsRaised, this, &TopLevelWindowModel::onWindowsRaised, Qt::QueuedConnection); |
760 | - connect(notifier, &WindowModelNotifier::modificationsStarted, this, &TopLevelWindowModel::onModificationsStarted, Qt::QueuedConnection); |
761 | - connect(notifier, &WindowModelNotifier::modificationsEnded, this, &TopLevelWindowModel::onModificationsEnded, Qt::QueuedConnection); |
762 | -} |
763 | - |
764 | -void TopLevelWindowModel::onWindowAdded(const NewWindow &window) |
765 | -{ |
766 | - auto mirSession = window.windowInfo.window().application(); |
767 | - SessionInterface* session = m_sessionManager->findSession(mirSession.get()); |
768 | - |
769 | - auto surface = new MirSurface(window, m_windowController, session); |
770 | - rememberMirSurface(surface); |
771 | - |
772 | - if (session) |
773 | - session->registerSurface(surface); |
774 | - |
775 | - if (window.windowInfo.type() == mir_surface_type_inputmethod) { |
776 | - int id = generateId(); |
777 | - Window *qmlWindow = new Window(id); |
778 | - connectWindow(qmlWindow); |
779 | - qmlWindow->setSurface(surface); |
780 | - setInputMethodWindow(qmlWindow); |
781 | - } else { |
782 | - Application *application = m_applicationManager->findApplicationWithSession(mirSession); |
783 | - if (application) { |
784 | - prependSurface(surface, application); |
785 | - } else { |
786 | - // Must be a prompt session. No need to do anything about it here as a prompt surface is not top-level. |
787 | - // It will show up in the qtmir::Application::promptSurfaceList of some application. |
788 | - } |
789 | - } |
790 | - // TODO: handle surfaces that are neither top-level windows nor input method. eg: child dialogs, popups, menus |
791 | -} |
792 | - |
793 | -void TopLevelWindowModel::onWindowRemoved(const miral::WindowInfo &windowInfo) |
794 | -{ |
795 | - forgetMirSurface(windowInfo.window()); |
796 | - |
797 | - if (windowInfo.type() == mir_surface_type_inputmethod) { |
798 | - removeInputMethodWindow(); |
799 | - return; |
800 | - } |
801 | - |
802 | - const int index = findIndexOf(windowInfo.window()); |
803 | - if (index >= 0) { |
804 | - auto surface = static_cast<MirSurface*>(m_windowModel[index].window->surface()); |
805 | - surface->setLive(false); |
806 | - } |
807 | -} |
808 | - |
809 | -void TopLevelWindowModel::rememberMirSurface(MirSurface *surface) |
810 | -{ |
811 | - m_allSurfaces.append(surface); |
812 | -} |
813 | - |
814 | -void TopLevelWindowModel::forgetMirSurface(const miral::Window &window) |
815 | -{ |
816 | - for (int i = 0; i < m_allSurfaces.count(); ++i) { |
817 | - if (m_allSurfaces[i]->window() == window) { |
818 | - m_allSurfaces.removeAt(i); |
819 | - return; |
820 | - } |
821 | - } |
822 | -} |
823 | - |
824 | -void TopLevelWindowModel::removeAt(int index) |
825 | -{ |
826 | - if (m_modelState == IdleState) { |
827 | - beginRemoveRows(QModelIndex(), index, index); |
828 | - m_modelState = RemovingState; |
829 | - } else { |
830 | - Q_ASSERT(m_modelState == ResettingState); |
831 | - // No point in signaling anything if we're resetting the whole model |
832 | - } |
833 | - |
834 | - auto window = m_windowModel[index].window; |
835 | - |
836 | - window->setSurface(nullptr); |
837 | - window->setFocused(false); |
838 | - |
839 | - m_windowModel.removeAt(index); |
840 | - |
841 | - if (m_modelState == RemovingState) { |
842 | - endRemoveRows(); |
843 | - Q_EMIT countChanged(); |
844 | - Q_EMIT listChanged(); |
845 | - m_modelState = IdleState; |
846 | - } |
847 | - |
848 | - disconnect(window, 0, this, 0); |
849 | - if (m_focusedWindow == window) { |
850 | - setFocusedWindow(nullptr); |
851 | - } |
852 | - delete window; |
853 | - |
854 | - DEBUG_MSG << " after " << toString(); |
855 | -} |
856 | - |
857 | -void TopLevelWindowModel::onWindowReady(const miral::WindowInfo &windowInfo) |
858 | -{ |
859 | - if (auto mirSurface = find(windowInfo)) { |
860 | - mirSurface->setReady(); |
861 | - } |
862 | -} |
863 | - |
864 | -void TopLevelWindowModel::onWindowMoved(const miral::WindowInfo &windowInfo, const QPoint topLeft) |
865 | -{ |
866 | - if (auto mirSurface = find(windowInfo)) { |
867 | - mirSurface->setPosition(topLeft); |
868 | - } |
869 | -} |
870 | - |
871 | -void TopLevelWindowModel::onWindowFocusChanged(const miral::WindowInfo &windowInfo, bool focused) |
872 | -{ |
873 | - if (auto mirSurface = find(windowInfo)) { |
874 | - mirSurface->setFocused(focused); |
875 | - } |
876 | -} |
877 | - |
878 | -void TopLevelWindowModel::onWindowStateChanged(const miral::WindowInfo &windowInfo, Mir::State state) |
879 | -{ |
880 | - if (auto mirSurface = find(windowInfo)) { |
881 | - mirSurface->updateState(state); |
882 | - } |
883 | -} |
884 | - |
885 | -void TopLevelWindowModel::setInputMethodWindow(Window *window) |
886 | -{ |
887 | - if (m_inputMethodWindow) { |
888 | - qWarning("Multiple Input Method Surfaces created, removing the old one!"); |
889 | - delete m_inputMethodWindow; |
890 | - } |
891 | - m_inputMethodWindow = window; |
892 | - Q_EMIT inputMethodSurfaceChanged(m_inputMethodWindow->surface()); |
893 | -} |
894 | - |
895 | -void TopLevelWindowModel::removeInputMethodWindow() |
896 | -{ |
897 | - if (m_inputMethodWindow) { |
898 | - delete m_inputMethodWindow; |
899 | - m_inputMethodWindow = nullptr; |
900 | - Q_EMIT inputMethodSurfaceChanged(nullptr); |
901 | - } |
902 | -} |
903 | - |
904 | -void TopLevelWindowModel::onWindowsRaised(const std::vector<miral::Window> &windows) |
905 | -{ |
906 | - const int raiseCount = windows.size(); |
907 | - for (int i = 0; i < raiseCount; i++) { |
908 | - int fromIndex = findIndexOf(windows[i]); |
909 | - if (fromIndex != -1) { |
910 | - move(fromIndex, 0); |
911 | - } |
912 | - } |
913 | -} |
914 | - |
915 | -int TopLevelWindowModel::rowCount(const QModelIndex &/*parent*/) const |
916 | -{ |
917 | - return m_windowModel.count(); |
918 | -} |
919 | - |
920 | -QVariant TopLevelWindowModel::data(const QModelIndex& index, int role) const |
921 | -{ |
922 | - if (index.row() < 0 || index.row() >= m_windowModel.size()) |
923 | - return QVariant(); |
924 | - |
925 | - if (role == WindowRole) { |
926 | - unityapi::WindowInterface *window = m_windowModel.at(index.row()).window; |
927 | - return QVariant::fromValue(window); |
928 | - } else if (role == ApplicationRole) { |
929 | - return QVariant::fromValue(m_windowModel.at(index.row()).application); |
930 | - } else { |
931 | - return QVariant(); |
932 | - } |
933 | -} |
934 | - |
935 | -MirSurface *TopLevelWindowModel::find(const miral::WindowInfo &needle) const |
936 | -{ |
937 | - auto window = needle.window(); |
938 | - Q_FOREACH(const auto surface, m_allSurfaces) { |
939 | - if (surface->window() == window) { |
940 | - return surface; |
941 | - } |
942 | - } |
943 | - return nullptr; |
944 | -} |
945 | - |
946 | -int TopLevelWindowModel::findIndexOf(const miral::Window &needle) const |
947 | -{ |
948 | - for (int i=0; i<m_windowModel.count(); i++) { |
949 | - auto surface = static_cast<MirSurface*>(m_windowModel[i].window->surface()); |
950 | - if (surface && surface->window() == needle) { |
951 | - return i; |
952 | - } |
953 | - } |
954 | - return -1; |
955 | -} |
956 | - |
957 | -int TopLevelWindowModel::generateId() |
958 | -{ |
959 | - int id = m_nextId; |
960 | - m_nextId = nextFreeId(m_nextId + 1); |
961 | - return id; |
962 | -} |
963 | - |
964 | -int TopLevelWindowModel::nextFreeId(int candidateId) |
965 | -{ |
966 | - if (candidateId > m_maxId) { |
967 | - return nextFreeId(1); |
968 | - } else { |
969 | - if (indexForId(candidateId) == -1) { |
970 | - // it's indeed free |
971 | - return candidateId; |
972 | - } else { |
973 | - return nextFreeId(candidateId + 1); |
974 | - } |
975 | - } |
976 | -} |
977 | - |
978 | -QString TopLevelWindowModel::toString() |
979 | -{ |
980 | - QString str; |
981 | - for (int i = 0; i < m_windowModel.count(); ++i) { |
982 | - auto item = m_windowModel.at(i); |
983 | - |
984 | - QString itemStr = QString("(index=%1,appId=%2,surface=0x%3,id=%4)") |
985 | - .arg(i) |
986 | - .arg(item.application->appId()) |
987 | - .arg((qintptr)item.window->surface(), 0, 16) |
988 | - .arg(item.window->id()); |
989 | - |
990 | - if (i > 0) { |
991 | - str.append(","); |
992 | - } |
993 | - str.append(itemStr); |
994 | - } |
995 | - return str; |
996 | -} |
997 | - |
998 | -int TopLevelWindowModel::indexOf(MirSurfaceInterface *surface) |
999 | -{ |
1000 | - for (int i = 0; i < m_windowModel.count(); ++i) { |
1001 | - if (m_windowModel.at(i).window->surface() == surface) { |
1002 | - return i; |
1003 | - } |
1004 | - } |
1005 | - return -1; |
1006 | -} |
1007 | - |
1008 | -int TopLevelWindowModel::indexForId(int id) const |
1009 | -{ |
1010 | - for (int i = 0; i < m_windowModel.count(); ++i) { |
1011 | - if (m_windowModel[i].window->id() == id) { |
1012 | - return i; |
1013 | - } |
1014 | - } |
1015 | - return -1; |
1016 | -} |
1017 | - |
1018 | -unityapi::WindowInterface *TopLevelWindowModel::windowAt(int index) const |
1019 | -{ |
1020 | - if (index >=0 && index < m_windowModel.count()) { |
1021 | - return m_windowModel[index].window; |
1022 | - } else { |
1023 | - return nullptr; |
1024 | - } |
1025 | -} |
1026 | - |
1027 | -unityapi::MirSurfaceInterface *TopLevelWindowModel::surfaceAt(int index) const |
1028 | -{ |
1029 | - if (index >=0 && index < m_windowModel.count()) { |
1030 | - return m_windowModel[index].window->surface(); |
1031 | - } else { |
1032 | - return nullptr; |
1033 | - } |
1034 | -} |
1035 | - |
1036 | -unityapi::ApplicationInfoInterface *TopLevelWindowModel::applicationAt(int index) const |
1037 | -{ |
1038 | - if (index >=0 && index < m_windowModel.count()) { |
1039 | - return m_windowModel[index].application; |
1040 | - } else { |
1041 | - return nullptr; |
1042 | - } |
1043 | -} |
1044 | - |
1045 | -int TopLevelWindowModel::idAt(int index) const |
1046 | -{ |
1047 | - if (index >=0 && index < m_windowModel.count()) { |
1048 | - return m_windowModel[index].window->id(); |
1049 | - } else { |
1050 | - return 0; |
1051 | - } |
1052 | -} |
1053 | - |
1054 | -void TopLevelWindowModel::raiseId(int id) |
1055 | -{ |
1056 | - if (m_modelState == IdleState) { |
1057 | - DEBUG_MSG << "(id=" << id << ") - do it now."; |
1058 | - doRaiseId(id); |
1059 | - } else { |
1060 | - DEBUG_MSG << "(id=" << id << ") - Model busy (modelState=" << m_modelState << "). Try again in the next event loop."; |
1061 | - // The model has just signalled some change. If we have a Repeater responding to this update, it will get nuts |
1062 | - // if we perform yet another model change straight away. |
1063 | - // |
1064 | - // A bad sympton of this problem is a Repeater.itemAt(index) call returning null event though Repeater.count says |
1065 | - // the index is definitely within bounds. |
1066 | - QMetaObject::invokeMethod(this, "raiseId", Qt::QueuedConnection, Q_ARG(int, id)); |
1067 | - } |
1068 | -} |
1069 | - |
1070 | -void TopLevelWindowModel::doRaiseId(int id) |
1071 | -{ |
1072 | - int fromIndex = indexForId(id); |
1073 | - if (fromIndex != -1) { |
1074 | - auto surface = static_cast<MirSurface*>(m_windowModel[fromIndex].window->surface()); |
1075 | - if (surface) { |
1076 | - m_windowController->raise(surface->window()); |
1077 | - } else { |
1078 | - // move it ourselves. Since there's no mir::scene::Surface/miral::Window, there's nothing |
1079 | - // miral can do about it. |
1080 | - move(fromIndex, 0); |
1081 | - } |
1082 | - } |
1083 | -} |
1084 | - |
1085 | -void TopLevelWindowModel::setFocusedWindow(Window *window) |
1086 | -{ |
1087 | - if (window != m_focusedWindow) { |
1088 | - DEBUG_MSG << "(" << window << ")"; |
1089 | - |
1090 | - Window* previousWindow = m_focusedWindow; |
1091 | - |
1092 | - m_focusedWindow = window; |
1093 | - Q_EMIT focusedWindowChanged(m_focusedWindow); |
1094 | - |
1095 | - if (previousWindow && previousWindow->focused() && !previousWindow->surface()) { |
1096 | - // do it ourselves. miral doesn't know about this window |
1097 | - previousWindow->setFocused(false); |
1098 | - } |
1099 | - } |
1100 | -} |
1101 | - |
1102 | -unityapi::MirSurfaceInterface* TopLevelWindowModel::inputMethodSurface() const |
1103 | -{ |
1104 | - return m_inputMethodWindow ? m_inputMethodWindow->surface() : nullptr; |
1105 | -} |
1106 | - |
1107 | -unityapi::WindowInterface* TopLevelWindowModel::focusedWindow() const |
1108 | -{ |
1109 | - return m_focusedWindow; |
1110 | -} |
1111 | - |
1112 | -void TopLevelWindowModel::move(int from, int to) |
1113 | -{ |
1114 | - if (from == to) return; |
1115 | - DEBUG_MSG << " from=" << from << " to=" << to; |
1116 | - |
1117 | - if (from >= 0 && from < m_windowModel.size() && to >= 0 && to < m_windowModel.size()) { |
1118 | - QModelIndex parent; |
1119 | - /* When moving an item down, the destination index needs to be incremented |
1120 | - by one, as explained in the documentation: |
1121 | - http://qt-project.org/doc/qt-5.0/qtcore/qabstractitemmodel.html#beginMoveRows */ |
1122 | - |
1123 | - Q_ASSERT(m_modelState == IdleState); |
1124 | - m_modelState = MovingState; |
1125 | - |
1126 | - beginMoveRows(parent, from, from, parent, to + (to > from ? 1 : 0)); |
1127 | -#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0) |
1128 | - const auto &window = m_windowModel.takeAt(from); |
1129 | - m_windowModel.insert(to, window); |
1130 | -#else |
1131 | - m_windowModel.move(from, to); |
1132 | -#endif |
1133 | - endMoveRows(); |
1134 | - |
1135 | - Q_EMIT listChanged(); |
1136 | - m_modelState = IdleState; |
1137 | - |
1138 | - DEBUG_MSG << " after " << toString(); |
1139 | - } |
1140 | -} |
1141 | -void TopLevelWindowModel::onModificationsStarted() |
1142 | -{ |
1143 | -} |
1144 | - |
1145 | -void TopLevelWindowModel::onModificationsEnded() |
1146 | -{ |
1147 | - if (m_focusedWindowChanged) { |
1148 | - setFocusedWindow(m_newlyFocusedWindow); |
1149 | - } |
1150 | - // reset |
1151 | - m_focusedWindowChanged = false; |
1152 | - m_newlyFocusedWindow = nullptr; |
1153 | -} |
1154 | |
1155 | === removed file 'src/modules/Unity/Application/toplevelwindowmodel.h' |
1156 | --- src/modules/Unity/Application/toplevelwindowmodel.h 2016-11-04 11:06:15 +0000 |
1157 | +++ src/modules/Unity/Application/toplevelwindowmodel.h 1970-01-01 00:00:00 +0000 |
1158 | @@ -1,161 +0,0 @@ |
1159 | -/* |
1160 | - * Copyright (C) 2016 Canonical, Ltd. |
1161 | - * |
1162 | - * This program is free software: you can redistribute it and/or modify it under |
1163 | - * the terms of the GNU Lesser General Public License version 3, as published by |
1164 | - * the Free Software Foundation. |
1165 | - * |
1166 | - * This program is distributed in the hope that it will be useful, but WITHOUT |
1167 | - * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
1168 | - * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1169 | - * Lesser General Public License for more details. |
1170 | - * |
1171 | - * You should have received a copy of the GNU Lesser General Public License |
1172 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1173 | - */ |
1174 | - |
1175 | -#ifndef TOPLEVELWINDOWMODEL_H |
1176 | -#define TOPLEVELWINDOWMODEL_H |
1177 | - |
1178 | -#include <QLoggingCategory> |
1179 | - |
1180 | -#include "mirsurface.h" |
1181 | -#include "window.h" |
1182 | -#include "windowmodelnotifier.h" |
1183 | - |
1184 | -// Unity API |
1185 | -#include <unity/shell/application/TopLevelWindowModelInterface.h> |
1186 | - |
1187 | -Q_DECLARE_LOGGING_CATEGORY(QTMIR_TOPLEVELWINDOWMODEL) |
1188 | - |
1189 | -namespace unity { |
1190 | - namespace shell { |
1191 | - namespace application { |
1192 | - class ApplicationInfoInterface; |
1193 | - class ApplicationManagerInterface; |
1194 | - class MirSurfaceInterface; |
1195 | - } |
1196 | - } |
1197 | -} |
1198 | - |
1199 | -namespace qtmir { |
1200 | - |
1201 | -class Application; |
1202 | -class ApplicationManagerInterface; |
1203 | -class SessionManager; |
1204 | -class WindowControllerInterface; |
1205 | - |
1206 | -class TopLevelWindowModel : public unity::shell::application::TopLevelWindowModelInterface |
1207 | -{ |
1208 | - Q_OBJECT |
1209 | - |
1210 | -public: |
1211 | - TopLevelWindowModel(); |
1212 | - explicit TopLevelWindowModel(WindowModelNotifier *notifier, |
1213 | - WindowControllerInterface *controller); // For testing |
1214 | - |
1215 | - // From unity::shell::application::TopLevelWindowModelInterface |
1216 | - unity::shell::application::MirSurfaceInterface* inputMethodSurface() const override; |
1217 | - unity::shell::application::WindowInterface* focusedWindow() const override; |
1218 | - |
1219 | - // From QAbstractItemModel |
1220 | - int rowCount(const QModelIndex &parent = QModelIndex()) const override; |
1221 | - QVariant data(const QModelIndex& index, int role) const override; |
1222 | - |
1223 | - // Own API |
1224 | - void setApplicationManager(ApplicationManagerInterface*); |
1225 | - |
1226 | -public Q_SLOTS: |
1227 | - // From unity::shell::application::TopLevelWindowModelInterface |
1228 | - unity::shell::application::MirSurfaceInterface *surfaceAt(int index) const override; |
1229 | - unity::shell::application::WindowInterface *windowAt(int index) const override; |
1230 | - unity::shell::application::ApplicationInfoInterface *applicationAt(int index) const override; |
1231 | - int idAt(int index) const override; |
1232 | - int indexForId(int id) const override; |
1233 | - void raiseId(int id) override; |
1234 | - |
1235 | -private Q_SLOTS: |
1236 | - void onWindowAdded(const qtmir::NewWindow &windowInfo); |
1237 | - void onWindowRemoved(const miral::WindowInfo &windowInfo); |
1238 | - void onWindowReady(const miral::WindowInfo &windowInfo); |
1239 | - void onWindowMoved(const miral::WindowInfo &windowInfo, const QPoint topLeft); |
1240 | - void onWindowStateChanged(const miral::WindowInfo &windowInfo, Mir::State state); |
1241 | - void onWindowFocusChanged(const miral::WindowInfo &windowInfo, bool focused); |
1242 | - void onWindowsRaised(const std::vector<miral::Window> &windows); |
1243 | - void onModificationsStarted(); |
1244 | - void onModificationsEnded(); |
1245 | - |
1246 | -private: |
1247 | - void doRaiseId(int id); |
1248 | - int generateId(); |
1249 | - int nextFreeId(int candidateId); |
1250 | - void connectToWindowModelNotifier(WindowModelNotifier *notifier); |
1251 | - QString toString(); |
1252 | - int indexOf(MirSurfaceInterface *surface); |
1253 | - |
1254 | - void setInputMethodWindow(Window *window); |
1255 | - void setFocusedWindow(Window *window); |
1256 | - void removeInputMethodWindow(); |
1257 | - MirSurface* find(const miral::WindowInfo &needle) const; |
1258 | - int findIndexOf(const miral::Window &needle) const; |
1259 | - void removeAt(int index); |
1260 | - |
1261 | - void addApplication(Application *application); |
1262 | - void removeApplication(Application *application); |
1263 | - |
1264 | - void prependPlaceholder(Application *application); |
1265 | - void prependSurface(MirSurface *surface, Application *application); |
1266 | - void prependSurfaceHelper(MirSurface *surface, Application *application); |
1267 | - |
1268 | - void connectWindow(Window *window); |
1269 | - void connectSurface(MirSurfaceInterface *surface); |
1270 | - |
1271 | - void onSurfaceDied(MirSurfaceInterface *surface); |
1272 | - void onSurfaceDestroyed(MirSurfaceInterface *surface); |
1273 | - |
1274 | - void move(int from, int to); |
1275 | - |
1276 | - void rememberMirSurface(MirSurface *surface); |
1277 | - void forgetMirSurface(const miral::Window &window); |
1278 | - |
1279 | - struct ModelEntry { |
1280 | - ModelEntry() {} |
1281 | - ModelEntry(Window *window, |
1282 | - Application *application) |
1283 | - : window(window), application(application) {} |
1284 | - Window *window{nullptr}; |
1285 | - Application *application{nullptr}; |
1286 | - bool removeOnceSurfaceDestroyed{false}; |
1287 | - }; |
1288 | - |
1289 | - QVector<ModelEntry> m_windowModel; |
1290 | - WindowControllerInterface *m_windowController; |
1291 | - SessionManager* m_sessionManager; |
1292 | - Window* m_inputMethodWindow{nullptr}; |
1293 | - Window* m_focusedWindow{nullptr}; |
1294 | - QVector<MirSurface*> m_allSurfaces; |
1295 | - |
1296 | - int m_nextId{1}; |
1297 | - // Just something big enough that we don't risk running out of unused id numbers. |
1298 | - // Not sure if QML int type supports something close to std::numeric_limits<int>::max() and |
1299 | - // there's no reason to try out its limits. |
1300 | - static const int m_maxId{1000000}; |
1301 | - |
1302 | - ApplicationManagerInterface* m_applicationManager{nullptr}; |
1303 | - |
1304 | - enum ModelState { |
1305 | - IdleState, |
1306 | - InsertingState, |
1307 | - RemovingState, |
1308 | - MovingState, |
1309 | - ResettingState |
1310 | - }; |
1311 | - ModelState m_modelState{IdleState}; |
1312 | - |
1313 | - // Valid between modificationsStarted and modificationsEnded |
1314 | - bool m_focusedWindowChanged{false}; |
1315 | - Window *m_newlyFocusedWindow{nullptr}; |
1316 | -}; |
1317 | - |
1318 | -} // namespace qtmir |
1319 | -#endif // TOPLEVELWINDOWMODEL_H |
1320 | |
1321 | === removed file 'src/modules/Unity/Application/window.cpp' |
1322 | --- src/modules/Unity/Application/window.cpp 2016-11-07 11:44:55 +0000 |
1323 | +++ src/modules/Unity/Application/window.cpp 1970-01-01 00:00:00 +0000 |
1324 | @@ -1,186 +0,0 @@ |
1325 | -/* |
1326 | - * Copyright (C) 2016 Canonical, Ltd. |
1327 | - * |
1328 | - * This program is free software; you can redistribute it and/or modify |
1329 | - * it under the terms of the GNU General Public License as published by |
1330 | - * the Free Software Foundation; version 3. |
1331 | - * |
1332 | - * This program is distributed in the hope that it will be useful, |
1333 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1334 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1335 | - * GNU General Public License for more details. |
1336 | - * |
1337 | - * You should have received a copy of the GNU General Public License |
1338 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1339 | - */ |
1340 | - |
1341 | -#include "window.h" |
1342 | -#include "mirsurface.h" |
1343 | - |
1344 | -#include <QQmlEngine> |
1345 | - |
1346 | -namespace unityapi = unity::shell::application; |
1347 | -using namespace qtmir; |
1348 | - |
1349 | -Window::Window(int id) |
1350 | - : WindowInterface(nullptr) |
1351 | - , m_id(id) |
1352 | -{ |
1353 | - QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); |
1354 | -} |
1355 | - |
1356 | -QPoint Window::position() const |
1357 | -{ |
1358 | - return m_position; |
1359 | -} |
1360 | - |
1361 | -QPoint Window::requestedPosition() const |
1362 | -{ |
1363 | - return m_requestedPosition; |
1364 | -} |
1365 | - |
1366 | -void Window::setRequestedPosition(const QPoint &value) |
1367 | -{ |
1368 | - if (value != m_requestedPosition) { |
1369 | - m_requestedPosition = value; |
1370 | - Q_EMIT requestedPositionChanged(m_requestedPosition); |
1371 | - if (m_surface) { |
1372 | - m_surface->setRequestedPosition(value); |
1373 | - } else { |
1374 | - // fake-miral: always comply |
1375 | - m_position = m_requestedPosition; |
1376 | - Q_EMIT positionChanged(m_position); |
1377 | - } |
1378 | - } |
1379 | -} |
1380 | - |
1381 | -Mir::State Window::state() const |
1382 | -{ |
1383 | - return m_state; |
1384 | -} |
1385 | - |
1386 | -bool Window::focused() const |
1387 | -{ |
1388 | - return m_focused; |
1389 | -} |
1390 | - |
1391 | -bool Window::confinesMousePointer() const |
1392 | -{ |
1393 | - if (m_surface) { |
1394 | - return m_surface->confinesMousePointer(); |
1395 | - } else { |
1396 | - return false; |
1397 | - } |
1398 | -} |
1399 | - |
1400 | -int Window::id() const |
1401 | -{ |
1402 | - return m_id; |
1403 | -} |
1404 | - |
1405 | -unityapi::MirSurfaceInterface* Window::surface() const |
1406 | -{ |
1407 | - return m_surface; |
1408 | -} |
1409 | - |
1410 | -void Window::requestState(Mir::State state) |
1411 | -{ |
1412 | - if (m_surface) { |
1413 | - m_surface->requestState(state); |
1414 | - } else if (m_state != state) { |
1415 | - m_state = state; |
1416 | - Q_EMIT stateChanged(m_state); |
1417 | - } |
1418 | -} |
1419 | - |
1420 | -void Window::requestFocus() |
1421 | -{ |
1422 | - if (m_surface) { |
1423 | - m_surface->requestFocus(); |
1424 | - } else { |
1425 | - Q_EMIT focusRequested(); |
1426 | - } |
1427 | -} |
1428 | - |
1429 | -void Window::close() |
1430 | -{ |
1431 | - if (m_surface) { |
1432 | - m_surface->close(); |
1433 | - } else { |
1434 | - Q_EMIT closeRequested(); |
1435 | - } |
1436 | -} |
1437 | - |
1438 | -void Window::setSurface(MirSurface *surface) |
1439 | -{ |
1440 | - if (m_surface) { |
1441 | - disconnect(m_surface, 0, this, 0); |
1442 | - } |
1443 | - |
1444 | - m_surface = surface; |
1445 | - |
1446 | - if (m_surface) { |
1447 | - connect(surface, &MirSurfaceInterface::focusRequested, this, [this]() { |
1448 | - Q_EMIT focusRequested(); |
1449 | - }); |
1450 | - |
1451 | - connect(surface, &MirSurfaceInterface::closeRequested, this, &Window::closeRequested); |
1452 | - |
1453 | - connect(surface, &MirSurfaceInterface::positionChanged, this, [this]() { |
1454 | - updatePosition(); |
1455 | - }); |
1456 | - |
1457 | - connect(surface, &MirSurfaceInterface::stateChanged, this, [this]() { |
1458 | - updateState(); |
1459 | - }); |
1460 | - |
1461 | - connect(surface, &MirSurfaceInterface::focusedChanged, this, [this]() { |
1462 | - updateFocused(); |
1463 | - }); |
1464 | - |
1465 | - // bring it up to speed |
1466 | - m_surface->setRequestedPosition(m_requestedPosition); |
1467 | - m_surface->requestState(m_state); |
1468 | - |
1469 | - // and sync with surface |
1470 | - updatePosition(); |
1471 | - updateState(); |
1472 | - updateFocused(); |
1473 | - } |
1474 | - |
1475 | - Q_EMIT surfaceChanged(surface); |
1476 | -} |
1477 | - |
1478 | -void Window::updatePosition() |
1479 | -{ |
1480 | - if (m_surface->position() != m_position) { |
1481 | - m_position = m_surface->position(); |
1482 | - Q_EMIT positionChanged(m_position); |
1483 | - } |
1484 | -} |
1485 | - |
1486 | -void Window::updateState() |
1487 | -{ |
1488 | - if (m_surface->state() != m_state) { |
1489 | - m_state = m_surface->state(); |
1490 | - Q_EMIT stateChanged(m_state); |
1491 | - } |
1492 | -} |
1493 | - |
1494 | -void Window::updateFocused() |
1495 | -{ |
1496 | - if (m_surface->focused() != m_focused) { |
1497 | - m_focused = m_surface->focused(); |
1498 | - Q_EMIT focusedChanged(m_focused); |
1499 | - } |
1500 | -} |
1501 | - |
1502 | -void Window::setFocused(bool value) |
1503 | -{ |
1504 | - if (value != m_focused) { |
1505 | - m_focused = value; |
1506 | - Q_EMIT focusedChanged(m_focused); |
1507 | - // when we have a surface we get focus changes from updateFocused() instead |
1508 | - Q_ASSERT(!m_surface); |
1509 | - } |
1510 | -} |
1511 | |
1512 | === removed file 'src/modules/Unity/Application/window.h' |
1513 | --- src/modules/Unity/Application/window.h 2016-11-03 20:17:46 +0000 |
1514 | +++ src/modules/Unity/Application/window.h 1970-01-01 00:00:00 +0000 |
1515 | @@ -1,67 +0,0 @@ |
1516 | -/* |
1517 | - * Copyright (C) 2016 Canonical, Ltd. |
1518 | - * |
1519 | - * This program is free software; you can redistribute it and/or modify |
1520 | - * it under the terms of the GNU General Public License as published by |
1521 | - * the Free Software Foundation; version 3. |
1522 | - * |
1523 | - * This program is distributed in the hope that it will be useful, |
1524 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1525 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1526 | - * GNU General Public License for more details. |
1527 | - * |
1528 | - * You should have received a copy of the GNU General Public License |
1529 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1530 | - */ |
1531 | - |
1532 | -#ifndef QTMIR_WINDOW_H |
1533 | -#define QTMIR_WINDOW_H |
1534 | - |
1535 | -// unity-api |
1536 | -#include <unity/shell/application/WindowInterface.h> |
1537 | - |
1538 | -namespace qtmir { |
1539 | - |
1540 | -class MirSurface; |
1541 | - |
1542 | -class Window : public unity::shell::application::WindowInterface |
1543 | -{ |
1544 | - Q_OBJECT |
1545 | - |
1546 | -public: |
1547 | - Window(int id); |
1548 | - QPoint position() const override; |
1549 | - QPoint requestedPosition() const override; |
1550 | - void setRequestedPosition(const QPoint &) override; |
1551 | - Mir::State state() const override; |
1552 | - bool focused() const override; |
1553 | - bool confinesMousePointer() const override; |
1554 | - int id() const override; |
1555 | - unity::shell::application::MirSurfaceInterface* surface() const override; |
1556 | - |
1557 | - void setSurface(MirSurface *surface); |
1558 | - void setFocused(bool value); |
1559 | - |
1560 | -public Q_SLOTS: |
1561 | - void requestState(Mir::State state) override; |
1562 | - void requestFocus() override; |
1563 | - void close() override; |
1564 | - |
1565 | -Q_SIGNALS: |
1566 | - void closeRequested(); |
1567 | - |
1568 | -private: |
1569 | - void updatePosition(); |
1570 | - void updateState(); |
1571 | - void updateFocused(); |
1572 | - |
1573 | - QPoint m_position; |
1574 | - QPoint m_requestedPosition; |
1575 | - bool m_focused{false}; |
1576 | - int m_id; |
1577 | - Mir::State m_state{Mir::RestoredState}; |
1578 | - MirSurface *m_surface{nullptr}; |
1579 | -}; |
1580 | - |
1581 | -} // namespace qtmir { |
1582 | -#endif // QTMIR_WINDOW_H |
Smaller API is cleaner.