Merge lp:~dandrader/qtmir/miral-surfacemanager into lp:~unity-team/qtmir/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
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://code.launchpad.net/~dandrader/unity-api/miral-surfacemanager/+merge/310910

To post a comment you must log in.
Revision history for this message
Gerry Boland (gerboland) wrote :

Smaller API is cleaner.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/modules/Unity/Application/CMakeLists.txt'
--- src/modules/Unity/Application/CMakeLists.txt 2016-11-03 20:17:46 +0000
+++ src/modules/Unity/Application/CMakeLists.txt 2016-11-15 17:55:38 +0000
@@ -45,14 +45,13 @@
45 session.cpp45 session.cpp
46 sessionmanager.cpp46 sessionmanager.cpp
47 sharedwakelock.cpp47 sharedwakelock.cpp
48 surfacemanager.cpp
48 upstart/applicationinfo.cpp49 upstart/applicationinfo.cpp
49 upstart/taskcontroller.cpp50 upstart/taskcontroller.cpp
50 timer.cpp51 timer.cpp
51 timesource.cpp52 timesource.cpp
52 toplevelwindowmodel.cpp
53 tracepoints.c53 tracepoints.c
54 settings.cpp54 settings.cpp
55 window.cpp
56 windowmodel.cpp55 windowmodel.cpp
57# We need to run moc on these headers56# We need to run moc on these headers
58 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h57 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
@@ -61,8 +60,7 @@
61 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h60 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
62 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceItemInterface.h61 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceItemInterface.h
63 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceListInterface.h62 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceListInterface.h
64 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/TopLevelWindowModelInterface.h63 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/SurfaceManagerInterface.h
65 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/WindowInterface.h
66# Feed the automoc monster64# Feed the automoc monster
67 session_interface.h65 session_interface.h
68 applicationinfo.h66 applicationinfo.h
6967
=== modified file 'src/modules/Unity/Application/application.h'
--- src/modules/Unity/Application/application.h 2016-11-03 20:17:46 +0000
+++ src/modules/Unity/Application/application.h 2016-11-15 17:55:38 +0000
@@ -103,6 +103,7 @@
103 unity::shell::application::MirSurfaceListInterface* surfaceList() const override;103 unity::shell::application::MirSurfaceListInterface* surfaceList() const override;
104 unity::shell::application::MirSurfaceListInterface* promptSurfaceList() const override;104 unity::shell::application::MirSurfaceListInterface* promptSurfaceList() const override;
105 int surfaceCount() const override { return surfaceList()->count(); }105 int surfaceCount() const override { return surfaceList()->count(); }
106 void close() override;
106107
107 ProcessState processState() const { return m_processState; }108 ProcessState processState() const { return m_processState; }
108 void setProcessState(ProcessState value);109 void setProcessState(ProcessState value);
@@ -119,8 +120,6 @@
119120
120 pid_t pid() const;121 pid_t pid() const;
121122
122 void close();
123
124 // internal as in "not exposed in unity-api", so qtmir-internal.123 // internal as in "not exposed in unity-api", so qtmir-internal.
125 InternalState internalState() const { return m_state; }124 InternalState internalState() const { return m_state; }
126125
127126
=== modified file 'src/modules/Unity/Application/application_manager.cpp'
--- src/modules/Unity/Application/application_manager.cpp 2016-11-03 20:17:46 +0000
+++ src/modules/Unity/Application/application_manager.cpp 2016-11-15 17:55:38 +0000
@@ -577,6 +577,17 @@
577 authorized = true;577 authorized = true;
578}578}
579579
580
581unityapi::ApplicationInfoInterface *ApplicationManager::findApplicationWithSurface(unityapi::MirSurfaceInterface* surface)
582{
583 if (!surface)
584 return nullptr;
585
586 auto qtmirSurface = static_cast<qtmir::MirSurfaceInterface*>(surface);
587
588 return findApplicationWithPid(miral::pid_of(qtmirSurface->session()->session()));
589}
590
580Application* ApplicationManager::findApplicationWithSession(const std::shared_ptr<ms::Session> &session)591Application* ApplicationManager::findApplicationWithSession(const std::shared_ptr<ms::Session> &session)
581{592{
582 if (!session)593 if (!session)
583594
=== modified file 'src/modules/Unity/Application/application_manager.h'
--- src/modules/Unity/Application/application_manager.h 2016-11-03 20:17:46 +0000
+++ src/modules/Unity/Application/application_manager.h 2016-11-15 17:55:38 +0000
@@ -26,9 +26,11 @@
2626
27// local27// local
28#include "application.h"28#include "application.h"
29#include "applicationmanagerinterface.h"
30#include "taskcontroller.h"29#include "taskcontroller.h"
3130
31// Unity API
32#include <unity/shell/application/ApplicationManagerInterface.h>
33
32namespace mir {34namespace mir {
33 namespace scene {35 namespace scene {
34 class Session;36 class Session;
@@ -53,7 +55,7 @@
53class SharedWakelock;55class SharedWakelock;
54class SettingsInterface;56class SettingsInterface;
5557
56class ApplicationManager : public ApplicationManagerInterface58class ApplicationManager : public unity::shell::application::ApplicationManagerInterface
57{59{
58 Q_OBJECT60 Q_OBJECT
5961
@@ -81,13 +83,11 @@
81 QString focusedApplicationId() const override;83 QString focusedApplicationId() const override;
82 Q_INVOKABLE qtmir::Application* get(int index) const override;84 Q_INVOKABLE qtmir::Application* get(int index) const override;
83 Q_INVOKABLE qtmir::Application* findApplication(const QString &appId) const override;85 Q_INVOKABLE qtmir::Application* findApplication(const QString &appId) const override;
86 unity::shell::application::ApplicationInfoInterface *findApplicationWithSurface(unity::shell::application::MirSurfaceInterface* surface) override;
84 Q_INVOKABLE bool requestFocusApplication(const QString &appId) override;87 Q_INVOKABLE bool requestFocusApplication(const QString &appId) override;
85 Q_INVOKABLE qtmir::Application* startApplication(const QString &appId, const QStringList &arguments = QStringList()) override;88 Q_INVOKABLE qtmir::Application* startApplication(const QString &appId, const QStringList &arguments = QStringList()) override;
86 Q_INVOKABLE bool stopApplication(const QString &appId) override;89 Q_INVOKABLE bool stopApplication(const QString &appId) override;
8790
88 // qtmir::ApplicationManagerInterface
89 Application* findApplicationWithSession(const std::shared_ptr<mir::scene::Session> &session) override;
90
91 // QAbstractListModel91 // QAbstractListModel
92 int rowCount(const QModelIndex & parent = QModelIndex()) const override;92 int rowCount(const QModelIndex & parent = QModelIndex()) const override;
93 QVariant data(const QModelIndex & index, int role) const override;93 QVariant data(const QModelIndex & index, int role) const override;
@@ -119,6 +119,7 @@
119 void onApplicationClosing(Application *application);119 void onApplicationClosing(Application *application);
120120
121private:121private:
122 Application* findApplicationWithSession(const std::shared_ptr<mir::scene::Session> &session);
122 void setFocused(Application *application);123 void setFocused(Application *application);
123 void add(Application *application);124 void add(Application *application);
124 void remove(Application* application);125 void remove(Application* application);
125126
=== removed file 'src/modules/Unity/Application/applicationmanagerinterface.h'
--- src/modules/Unity/Application/applicationmanagerinterface.h 2016-11-03 20:17:46 +0000
+++ src/modules/Unity/Application/applicationmanagerinterface.h 1970-01-01 00:00:00 +0000
@@ -1,35 +0,0 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef QTMIR_APPLICATION_MANAGER_INTERFACE_H
18#define QTMIR_APPLICATION_MANAGER_INTERFACE_H
19
20// Unity API
21#include <unity/shell/application/ApplicationManagerInterface.h>
22
23namespace qtmir {
24
25class ApplicationManagerInterface : public unity::shell::application::ApplicationManagerInterface
26{
27public:
28 ApplicationManagerInterface(QObject *parent) : unity::shell::application::ApplicationManagerInterface(parent) {}
29
30 virtual Application* findApplicationWithSession(const std::shared_ptr<mir::scene::Session> &session) = 0;
31};
32
33} // namespace qtmir
34
35#endif // QTMIR_APPLICATION_MANAGER_INTERFACE_H
360
=== modified file 'src/modules/Unity/Application/mirsurfaceinterface.h'
--- src/modules/Unity/Application/mirsurfaceinterface.h 2016-11-03 20:17:46 +0000
+++ src/modules/Unity/Application/mirsurfaceinterface.h 2016-11-15 17:55:38 +0000
@@ -116,7 +116,6 @@
116 void ready();116 void ready();
117 void cursorChanged(const QCursor &cursor);117 void cursorChanged(const QCursor &cursor);
118 void raiseRequested();118 void raiseRequested();
119 void closeRequested();
120 void framesPosted();119 void framesPosted();
121 void isBeingDisplayedChanged();120 void isBeingDisplayedChanged();
122 void frameDropped();121 void frameDropped();
123122
=== modified file 'src/modules/Unity/Application/plugin.cpp'
--- src/modules/Unity/Application/plugin.cpp 2016-11-03 20:17:46 +0000
+++ src/modules/Unity/Application/plugin.cpp 2016-11-15 17:55:38 +0000
@@ -23,9 +23,8 @@
23#include "mirsurfaceinterface.h"23#include "mirsurfaceinterface.h"
24#include "mirsurfaceitem.h"24#include "mirsurfaceitem.h"
25#include "mirsurfacelistmodel.h"25#include "mirsurfacelistmodel.h"
26#include "toplevelwindowmodel.h"
27#include "window.h"
28#include "windowmodel.h"26#include "windowmodel.h"
27#include "surfacemanager.h"
2928
30// platforms/mirserver29// platforms/mirserver
31#include <mirsingleton.h>30#include <mirsingleton.h>
@@ -65,8 +64,8 @@
65 qRegisterMetaType<qtmir::Application*>("Application*");64 qRegisterMetaType<qtmir::Application*>("Application*");
66 qRegisterMetaType<unity::shell::application::MirSurfaceInterface*>("MirSurfaceInterface*");65 qRegisterMetaType<unity::shell::application::MirSurfaceInterface*>("MirSurfaceInterface*");
67 qRegisterMetaType<unity::shell::application::MirSurfaceListInterface*>("unity::shell::application::MirSurfaceListInterface*");66 qRegisterMetaType<unity::shell::application::MirSurfaceListInterface*>("unity::shell::application::MirSurfaceListInterface*");
67 qRegisterMetaType<unity::shell::application::SurfaceManagerInterface*>("unity::shell::application::SurfaceManagerInterface*");
68 qRegisterMetaType<MirSurfaceAttrib>("MirSurfaceAttrib");68 qRegisterMetaType<MirSurfaceAttrib>("MirSurfaceAttrib");
69 qRegisterMetaType<unity::shell::application::WindowInterface*>("unity::shell::application::WindowInterface*");
7069
71 qmlRegisterUncreatableType<unity::shell::application::ApplicationManagerInterface>(70 qmlRegisterUncreatableType<unity::shell::application::ApplicationManagerInterface>(
72 uri, 0, 1, "ApplicationManagerInterface", "Abstract interface. Cannot be created in QML");71 uri, 0, 1, "ApplicationManagerInterface", "Abstract interface. Cannot be created in QML");
@@ -80,9 +79,9 @@
80 uri, 0, 1, "MirSurface", "MirSurface can't be instantiated from QML");79 uri, 0, 1, "MirSurface", "MirSurface can't be instantiated from QML");
81 qmlRegisterType<qtmir::MirSurfaceItem>(uri, 0, 1, "MirSurfaceItem");80 qmlRegisterType<qtmir::MirSurfaceItem>(uri, 0, 1, "MirSurfaceItem");
82 qmlRegisterSingletonType<qtmir::Mir>(uri, 0, 1, "Mir", mirSingleton);81 qmlRegisterSingletonType<qtmir::Mir>(uri, 0, 1, "Mir", mirSingleton);
82 qmlRegisterType<qtmir::SurfaceManager>(uri, 0, 1, "SurfaceManager");
8383
84 qmlRegisterType<qtmir::WindowModel>(uri, 0, 1, "WindowModel");84 qmlRegisterType<qtmir::WindowModel>(uri, 0, 1, "WindowModel");
85 qmlRegisterType<qtmir::TopLevelWindowModel>(uri, 0, 1, "TopLevelWindowModel");
86 }85 }
8786
88 virtual void initializeEngine(QQmlEngine *engine, const char *uri)87 virtual void initializeEngine(QQmlEngine *engine, const char *uri)
8988
=== added file 'src/modules/Unity/Application/surfacemanager.cpp'
--- src/modules/Unity/Application/surfacemanager.cpp 1970-01-01 00:00:00 +0000
+++ src/modules/Unity/Application/surfacemanager.cpp 2016-11-15 17:55:38 +0000
@@ -0,0 +1,166 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "surfacemanager.h"
18
19#include "mirsurface.h"
20#include "sessionmanager.h"
21
22// mirserver
23#include "nativeinterface.h"
24
25// Qt
26#include <QGuiApplication>
27
28Q_LOGGING_CATEGORY(QTMIR_SURFACEMANAGER, "qtmir.surfacemanager", QtDebugMsg)
29
30#define DEBUG_MSG qCDebug(QTMIR_SURFACEMANAGER).nospace().noquote() << __func__
31
32using namespace qtmir;
33namespace unityapi = unity::shell::application;
34
35SurfaceManager::SurfaceManager(QObject *)
36{
37 DEBUG_MSG << "()";
38
39 auto nativeInterface = dynamic_cast<NativeInterface*>(QGuiApplication::platformNativeInterface());
40
41 if (!nativeInterface) {
42 qFatal("ERROR: Unity.Application QML plugin requires use of the 'mirserver' QPA plugin");
43 }
44
45 m_windowController = static_cast<WindowControllerInterface*>(nativeInterface->nativeResourceForIntegration("WindowController"));
46
47 auto windowModel = static_cast<WindowModelNotifier*>(nativeInterface->nativeResourceForIntegration("WindowModelNotifier"));
48 connectToWindowModelNotifier(windowModel);
49
50 m_sessionManager = SessionManager::singleton();
51}
52
53void SurfaceManager::connectToWindowModelNotifier(WindowModelNotifier *notifier)
54{
55 connect(notifier, &WindowModelNotifier::windowAdded, this, &SurfaceManager::onWindowAdded, Qt::QueuedConnection);
56 connect(notifier, &WindowModelNotifier::windowRemoved, this, &SurfaceManager::onWindowRemoved, Qt::QueuedConnection);
57 connect(notifier, &WindowModelNotifier::windowReady, this, &SurfaceManager::onWindowReady, Qt::QueuedConnection);
58 connect(notifier, &WindowModelNotifier::windowMoved, this, &SurfaceManager::onWindowMoved, Qt::QueuedConnection);
59 connect(notifier, &WindowModelNotifier::windowStateChanged, this, &SurfaceManager::onWindowStateChanged, Qt::QueuedConnection);
60 connect(notifier, &WindowModelNotifier::windowFocusChanged, this, &SurfaceManager::onWindowFocusChanged, Qt::QueuedConnection);
61 connect(notifier, &WindowModelNotifier::windowsRaised, this, &SurfaceManager::onWindowsRaised, Qt::QueuedConnection);
62 connect(notifier, &WindowModelNotifier::modificationsStarted, this, &SurfaceManager::modificationsStarted, Qt::QueuedConnection);
63 connect(notifier, &WindowModelNotifier::modificationsEnded, this, &SurfaceManager::modificationsEnded, Qt::QueuedConnection);
64}
65
66void SurfaceManager::rememberMirSurface(MirSurface *surface)
67{
68 m_allSurfaces.append(surface);
69}
70
71void SurfaceManager::forgetMirSurface(const miral::Window &window)
72{
73 for (int i = 0; i < m_allSurfaces.count(); ++i) {
74 if (m_allSurfaces[i]->window() == window) {
75 m_allSurfaces.removeAt(i);
76 return;
77 }
78 }
79}
80void SurfaceManager::onWindowAdded(const NewWindow &window)
81{
82 auto mirSession = window.windowInfo.window().application();
83 SessionInterface* session = m_sessionManager->findSession(mirSession.get());
84
85 auto surface = new MirSurface(window, m_windowController, session);
86 rememberMirSurface(surface);
87
88 if (session)
89 session->registerSurface(surface);
90
91 Q_EMIT surfaceCreated(surface);
92}
93
94void SurfaceManager::onWindowRemoved(const miral::WindowInfo &windowInfo)
95{
96 MirSurface *surface = find(windowInfo);
97 forgetMirSurface(windowInfo.window());
98 surface->setLive(false);
99}
100
101MirSurface *SurfaceManager::find(const miral::WindowInfo &needle) const
102{
103 return find(needle.window());
104}
105
106MirSurface *SurfaceManager::find(const miral::Window &window) const
107{
108 Q_FOREACH(const auto surface, m_allSurfaces) {
109 if (surface->window() == window) {
110 return surface;
111 }
112 }
113 return nullptr;
114}
115
116void SurfaceManager::onWindowReady(const miral::WindowInfo &windowInfo)
117{
118 if (auto mirSurface = find(windowInfo)) {
119 mirSurface->setReady();
120 }
121}
122
123void SurfaceManager::onWindowMoved(const miral::WindowInfo &windowInfo, const QPoint topLeft)
124{
125 if (auto mirSurface = find(windowInfo)) {
126 mirSurface->setPosition(topLeft);
127 }
128}
129
130void SurfaceManager::onWindowFocusChanged(const miral::WindowInfo &windowInfo, bool focused)
131{
132 if (auto mirSurface = find(windowInfo)) {
133 mirSurface->setFocused(focused);
134 }
135}
136
137void SurfaceManager::onWindowStateChanged(const miral::WindowInfo &windowInfo, Mir::State state)
138{
139 if (auto mirSurface = find(windowInfo)) {
140 mirSurface->updateState(state);
141 }
142}
143
144void SurfaceManager::onWindowsRaised(const std::vector<miral::Window> &windows)
145{
146 // sad inefficiency when crossing API boundaries (from miral to qt)
147 const int raiseCount = windows.size();
148 QVector<unityapi::MirSurfaceInterface*> surfaces(raiseCount);
149 for (int i = 0; i < raiseCount; i++) {
150 auto mirSurface = find(windows[i]);
151 surfaces.append(mirSurface);
152 }
153 Q_EMIT surfacesRaised(surfaces);
154}
155
156void SurfaceManager::raise(unityapi::MirSurfaceInterface *surface)
157{
158 auto qtmirSurface = static_cast<qtmir::MirSurface*>(surface);
159 m_windowController->raise(qtmirSurface->window());
160}
161
162void SurfaceManager::activate(unityapi::MirSurfaceInterface *surface)
163{
164 auto qtmirSurface = static_cast<qtmir::MirSurface*>(surface);
165 m_windowController->activate(qtmirSurface ? qtmirSurface->window() : miral::Window());
166}
0167
=== added file 'src/modules/Unity/Application/surfacemanager.h'
--- src/modules/Unity/Application/surfacemanager.h 1970-01-01 00:00:00 +0000
+++ src/modules/Unity/Application/surfacemanager.h 2016-11-15 17:55:38 +0000
@@ -0,0 +1,72 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef QTMIR_SURFACEMANAGER_H
18#define QTMIR_SURFACEMANAGER_H
19
20// common
21#include "windowmodelnotifier.h"
22
23// Unity API
24#include <unity/shell/application/SurfaceManagerInterface.h>
25
26#include <QVector>
27#include <QLoggingCategory>
28
29Q_DECLARE_LOGGING_CATEGORY(QTMIR_SURFACEMANAGER)
30
31namespace qtmir {
32
33class MirSurface;
34class SessionManager;
35class WindowControllerInterface;
36
37class SurfaceManager : public unity::shell::application::SurfaceManagerInterface
38{
39 Q_OBJECT
40
41public:
42 explicit SurfaceManager(QObject *parent = 0);
43 virtual ~SurfaceManager() {}
44
45 void raise(unity::shell::application::MirSurfaceInterface *surface) override;
46 void activate(unity::shell::application::MirSurfaceInterface *surface) override;
47
48private Q_SLOTS:
49 void onWindowAdded(const qtmir::NewWindow &windowInfo);
50 void onWindowRemoved(const miral::WindowInfo &windowInfo);
51 void onWindowReady(const miral::WindowInfo &windowInfo);
52 void onWindowMoved(const miral::WindowInfo &windowInfo, const QPoint topLeft);
53 void onWindowStateChanged(const miral::WindowInfo &windowInfo, Mir::State state);
54 void onWindowFocusChanged(const miral::WindowInfo &windowInfo, bool focused);
55 void onWindowsRaised(const std::vector<miral::Window> &windows);
56
57private:
58 void connectToWindowModelNotifier(WindowModelNotifier *notifier);
59 void rememberMirSurface(MirSurface *surface);
60 void forgetMirSurface(const miral::Window &window);
61 MirSurface* find(const miral::WindowInfo &needle) const;
62 MirSurface* find(const miral::Window &needle) const;
63
64 QVector<MirSurface*> m_allSurfaces;
65
66 WindowControllerInterface *m_windowController;
67 SessionManager* m_sessionManager;
68};
69
70} // namespace qtmir
71
72#endif // QTMIR_SURFACEMANAGER_H
073
=== removed file 'src/modules/Unity/Application/toplevelwindowmodel.cpp'
--- src/modules/Unity/Application/toplevelwindowmodel.cpp 2016-11-09 14:18:17 +0000
+++ src/modules/Unity/Application/toplevelwindowmodel.cpp 1970-01-01 00:00:00 +0000
@@ -1,691 +0,0 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "toplevelwindowmodel.h"
18
19#include "application.h"
20#include "application_manager.h"
21#include "mirsurface.h"
22#include "sessionmanager.h"
23
24// mirserver
25#include "nativeinterface.h"
26
27// Qt
28#include <QGuiApplication>
29#include <QDebug>
30
31Q_LOGGING_CATEGORY(QTMIR_TOPLEVELWINDOWMODEL, "qtmir.toplevelwindowmodel", QtDebugMsg)
32
33#define DEBUG_MSG qCDebug(QTMIR_TOPLEVELWINDOWMODEL).nospace().noquote() << __func__
34
35using namespace qtmir;
36namespace unityapi = unity::shell::application;
37
38TopLevelWindowModel::TopLevelWindowModel()
39{
40 auto nativeInterface = dynamic_cast<NativeInterface*>(QGuiApplication::platformNativeInterface());
41
42 if (!nativeInterface) {
43 qFatal("ERROR: Unity.Application QML plugin requires use of the 'mirserver' QPA plugin");
44 }
45
46 m_windowController = static_cast<WindowControllerInterface*>(nativeInterface->nativeResourceForIntegration("WindowController"));
47
48 auto windowModel = static_cast<WindowModelNotifier*>(nativeInterface->nativeResourceForIntegration("WindowModelNotifier"));
49 connectToWindowModelNotifier(windowModel);
50
51 setApplicationManager(ApplicationManager::singleton());
52
53 m_sessionManager = SessionManager::singleton();
54}
55
56TopLevelWindowModel::TopLevelWindowModel(WindowModelNotifier *notifier,
57 WindowControllerInterface *controller)
58 : m_windowController(controller)
59{
60 connectToWindowModelNotifier(notifier);
61}
62
63void TopLevelWindowModel::setApplicationManager(ApplicationManagerInterface* value)
64{
65 if (m_applicationManager == value) {
66 return;
67 }
68
69 Q_ASSERT(m_modelState == IdleState);
70 m_modelState = ResettingState;
71
72 beginResetModel();
73
74 if (m_applicationManager) {
75 m_windowModel.clear();
76 disconnect(m_applicationManager, 0, this, 0);
77 }
78
79 m_applicationManager = value;
80
81 if (m_applicationManager) {
82 connect(m_applicationManager, &QAbstractItemModel::rowsInserted,
83 this, [this](const QModelIndex &/*parent*/, int first, int last) {
84 for (int i = first; i <= last; ++i) {
85 auto application = m_applicationManager->get(i);
86 addApplication(static_cast<Application*>(application));
87 }
88 });
89
90 connect(m_applicationManager, &QAbstractItemModel::rowsAboutToBeRemoved,
91 this, [this](const QModelIndex &/*parent*/, int first, int last) {
92 for (int i = first; i <= last; ++i) {
93 auto application = m_applicationManager->get(i);
94 removeApplication(static_cast<Application*>(application));
95 }
96 });
97
98 for (int i = 0; i < m_applicationManager->rowCount(); ++i) {
99 auto application = m_applicationManager->get(i);
100 addApplication(static_cast<Application*>(application));
101 }
102 }
103
104 endResetModel();
105 m_modelState = IdleState;
106}
107
108void TopLevelWindowModel::addApplication(Application *application)
109{
110 DEBUG_MSG << "(" << application->appId() << ")";
111
112 if (application->state() != unityapi::ApplicationInfoInterface::Stopped && application->surfaceList()->count() == 0) {
113 prependPlaceholder(application);
114 }
115}
116
117void TopLevelWindowModel::removeApplication(Application *application)
118{
119 DEBUG_MSG << "(" << application->appId() << ")";
120
121 Q_ASSERT(m_modelState == IdleState);
122
123 int i = 0;
124 while (i < m_windowModel.count()) {
125 if (m_windowModel.at(i).application == application) {
126 removeAt(i);
127 } else {
128 ++i;
129 }
130 }
131}
132
133void TopLevelWindowModel::prependPlaceholder(Application *application)
134{
135 DEBUG_MSG << "(" << application->appId() << ")";
136
137 prependSurfaceHelper(nullptr, application);
138}
139
140void TopLevelWindowModel::prependSurface(MirSurface *surface, Application *application)
141{
142 Q_ASSERT(surface != nullptr);
143
144 bool filledPlaceholder = false;
145 for (int i = 0; i < m_windowModel.count() && !filledPlaceholder; ++i) {
146 ModelEntry &entry = m_windowModel[i];
147 if (entry.application == application && entry.window->surface() == nullptr) {
148 entry.window->setSurface(surface);
149 connectSurface(surface);
150 DEBUG_MSG << " appId=" << application->appId() << " surface=" << surface
151 << ", filling out placeholder. after: " << toString();
152 filledPlaceholder = true;
153 }
154 }
155
156 if (!filledPlaceholder) {
157 DEBUG_MSG << " appId=" << application->appId() << " surface=" << surface << ", adding new row";
158 prependSurfaceHelper(surface, application);
159 }
160}
161
162void TopLevelWindowModel::prependSurfaceHelper(MirSurface *surface, Application *application)
163{
164 if (m_modelState == IdleState) {
165 m_modelState = InsertingState;
166 beginInsertRows(QModelIndex(), 0 /*first*/, 0 /*last*/);
167 } else {
168 Q_ASSERT(m_modelState == ResettingState);
169 // No point in signaling anything if we're resetting the whole model
170 }
171
172 int id = generateId();
173 Window *window = new Window(id);
174 if (surface) {
175 window->setSurface(surface);
176 }
177 m_windowModel.prepend(ModelEntry(window, application));
178 if (surface) {
179 connectSurface(surface);
180 }
181
182 connectWindow(window);
183
184 if (m_modelState == InsertingState) {
185 endInsertRows();
186 Q_EMIT countChanged();
187 Q_EMIT listChanged();
188 m_modelState = IdleState;
189 }
190
191 if (!surface) {
192 // focus the newly added window. miral can't help with that as it doesn't know about it.
193 window->setFocused(true);
194 if (m_focusedWindow && m_focusedWindow->surface()) {
195 m_windowController->activate(miral::Window());
196 }
197 }
198
199 DEBUG_MSG << " after " << toString();
200}
201
202void TopLevelWindowModel::connectWindow(Window *window)
203{
204 connect(window, &unityapi::WindowInterface::focusRequested, this, [this, window]() {
205 if (!window->surface()) {
206 // miral doesn't know about this window, so we have to do it ourselves
207 window->setFocused(true);
208 raiseId(window->id());
209 Window *previousWindow = m_focusedWindow;
210 setFocusedWindow(window);
211 if (previousWindow && previousWindow->surface() && previousWindow->surface()->focused()) {
212 m_windowController->activate(miral::Window());
213 }
214 }
215 });
216
217 connect(window, &unityapi::WindowInterface::focusedChanged, this, [this, window](bool focused) {
218 if (window->surface()) {
219 // Condense changes to the focused window
220 // eg: Do focusedWindow=A to focusedWindow=B instead of
221 // focusedWindow=A to focusedWindow=null to focusedWindow=B
222 m_focusedWindowChanged = true;
223 if (focused) {
224 Q_ASSERT(m_newlyFocusedWindow == nullptr);
225 m_newlyFocusedWindow = window;
226 }
227 }
228 });
229
230 connect(window, &Window::closeRequested, this, [this, window]() {
231 if (!window->surface()) {
232 int index = indexForId(window->id());
233 Q_ASSERT(index >= 0);
234 m_windowModel[index].application->close();
235 }
236 });
237}
238
239void TopLevelWindowModel::connectSurface(MirSurfaceInterface *surface)
240{
241 connect(surface, &MirSurfaceInterface::liveChanged, this, [this, surface](bool live){
242 if (!live) {
243 onSurfaceDied(surface);
244 }
245 });
246 connect(surface, &QObject::destroyed, this, [this, surface](){ this->onSurfaceDestroyed(surface); });
247}
248
249void TopLevelWindowModel::onSurfaceDied(MirSurfaceInterface *surface)
250{
251 int i = indexOf(surface);
252 if (i == -1) {
253 return;
254 }
255
256 auto application = m_windowModel[i].application;
257
258 // can't be starting if it already has a surface
259 Q_ASSERT(application->state() != unityapi::ApplicationInfoInterface::Starting);
260
261 if (application->state() == unityapi::ApplicationInfoInterface::Running) {
262 m_windowModel[i].removeOnceSurfaceDestroyed = true;
263 } else {
264 // assume it got killed by the out-of-memory daemon.
265 //
266 // So leave entry in the model and only remove its surface, so shell can display a screenshot
267 // in its place.
268 m_windowModel[i].removeOnceSurfaceDestroyed = false;
269 }
270}
271
272void TopLevelWindowModel::onSurfaceDestroyed(MirSurfaceInterface *surface)
273{
274 int i = indexOf(surface);
275 if (i == -1) {
276 return;
277 }
278
279 if (m_windowModel[i].removeOnceSurfaceDestroyed) {
280 removeAt(i);
281 } else {
282 auto window = m_windowModel[i].window;
283 window->setSurface(nullptr);
284 window->setFocused(false);
285 DEBUG_MSG << " Removed surface from entry. After: " << toString();
286 }
287}
288
289void TopLevelWindowModel::connectToWindowModelNotifier(WindowModelNotifier *notifier)
290{
291 connect(notifier, &WindowModelNotifier::windowAdded, this, &TopLevelWindowModel::onWindowAdded, Qt::QueuedConnection);
292 connect(notifier, &WindowModelNotifier::windowRemoved, this, &TopLevelWindowModel::onWindowRemoved, Qt::QueuedConnection);
293 connect(notifier, &WindowModelNotifier::windowReady, this, &TopLevelWindowModel::onWindowReady, Qt::QueuedConnection);
294 connect(notifier, &WindowModelNotifier::windowMoved, this, &TopLevelWindowModel::onWindowMoved, Qt::QueuedConnection);
295 connect(notifier, &WindowModelNotifier::windowStateChanged, this, &TopLevelWindowModel::onWindowStateChanged, Qt::QueuedConnection);
296 connect(notifier, &WindowModelNotifier::windowFocusChanged, this, &TopLevelWindowModel::onWindowFocusChanged, Qt::QueuedConnection);
297 connect(notifier, &WindowModelNotifier::windowsRaised, this, &TopLevelWindowModel::onWindowsRaised, Qt::QueuedConnection);
298 connect(notifier, &WindowModelNotifier::modificationsStarted, this, &TopLevelWindowModel::onModificationsStarted, Qt::QueuedConnection);
299 connect(notifier, &WindowModelNotifier::modificationsEnded, this, &TopLevelWindowModel::onModificationsEnded, Qt::QueuedConnection);
300}
301
302void TopLevelWindowModel::onWindowAdded(const NewWindow &window)
303{
304 auto mirSession = window.windowInfo.window().application();
305 SessionInterface* session = m_sessionManager->findSession(mirSession.get());
306
307 auto surface = new MirSurface(window, m_windowController, session);
308 rememberMirSurface(surface);
309
310 if (session)
311 session->registerSurface(surface);
312
313 if (window.windowInfo.type() == mir_surface_type_inputmethod) {
314 int id = generateId();
315 Window *qmlWindow = new Window(id);
316 connectWindow(qmlWindow);
317 qmlWindow->setSurface(surface);
318 setInputMethodWindow(qmlWindow);
319 } else {
320 Application *application = m_applicationManager->findApplicationWithSession(mirSession);
321 if (application) {
322 prependSurface(surface, application);
323 } else {
324 // Must be a prompt session. No need to do anything about it here as a prompt surface is not top-level.
325 // It will show up in the qtmir::Application::promptSurfaceList of some application.
326 }
327 }
328 // TODO: handle surfaces that are neither top-level windows nor input method. eg: child dialogs, popups, menus
329}
330
331void TopLevelWindowModel::onWindowRemoved(const miral::WindowInfo &windowInfo)
332{
333 forgetMirSurface(windowInfo.window());
334
335 if (windowInfo.type() == mir_surface_type_inputmethod) {
336 removeInputMethodWindow();
337 return;
338 }
339
340 const int index = findIndexOf(windowInfo.window());
341 if (index >= 0) {
342 auto surface = static_cast<MirSurface*>(m_windowModel[index].window->surface());
343 surface->setLive(false);
344 }
345}
346
347void TopLevelWindowModel::rememberMirSurface(MirSurface *surface)
348{
349 m_allSurfaces.append(surface);
350}
351
352void TopLevelWindowModel::forgetMirSurface(const miral::Window &window)
353{
354 for (int i = 0; i < m_allSurfaces.count(); ++i) {
355 if (m_allSurfaces[i]->window() == window) {
356 m_allSurfaces.removeAt(i);
357 return;
358 }
359 }
360}
361
362void TopLevelWindowModel::removeAt(int index)
363{
364 if (m_modelState == IdleState) {
365 beginRemoveRows(QModelIndex(), index, index);
366 m_modelState = RemovingState;
367 } else {
368 Q_ASSERT(m_modelState == ResettingState);
369 // No point in signaling anything if we're resetting the whole model
370 }
371
372 auto window = m_windowModel[index].window;
373
374 window->setSurface(nullptr);
375 window->setFocused(false);
376
377 m_windowModel.removeAt(index);
378
379 if (m_modelState == RemovingState) {
380 endRemoveRows();
381 Q_EMIT countChanged();
382 Q_EMIT listChanged();
383 m_modelState = IdleState;
384 }
385
386 disconnect(window, 0, this, 0);
387 if (m_focusedWindow == window) {
388 setFocusedWindow(nullptr);
389 }
390 delete window;
391
392 DEBUG_MSG << " after " << toString();
393}
394
395void TopLevelWindowModel::onWindowReady(const miral::WindowInfo &windowInfo)
396{
397 if (auto mirSurface = find(windowInfo)) {
398 mirSurface->setReady();
399 }
400}
401
402void TopLevelWindowModel::onWindowMoved(const miral::WindowInfo &windowInfo, const QPoint topLeft)
403{
404 if (auto mirSurface = find(windowInfo)) {
405 mirSurface->setPosition(topLeft);
406 }
407}
408
409void TopLevelWindowModel::onWindowFocusChanged(const miral::WindowInfo &windowInfo, bool focused)
410{
411 if (auto mirSurface = find(windowInfo)) {
412 mirSurface->setFocused(focused);
413 }
414}
415
416void TopLevelWindowModel::onWindowStateChanged(const miral::WindowInfo &windowInfo, Mir::State state)
417{
418 if (auto mirSurface = find(windowInfo)) {
419 mirSurface->updateState(state);
420 }
421}
422
423void TopLevelWindowModel::setInputMethodWindow(Window *window)
424{
425 if (m_inputMethodWindow) {
426 qWarning("Multiple Input Method Surfaces created, removing the old one!");
427 delete m_inputMethodWindow;
428 }
429 m_inputMethodWindow = window;
430 Q_EMIT inputMethodSurfaceChanged(m_inputMethodWindow->surface());
431}
432
433void TopLevelWindowModel::removeInputMethodWindow()
434{
435 if (m_inputMethodWindow) {
436 delete m_inputMethodWindow;
437 m_inputMethodWindow = nullptr;
438 Q_EMIT inputMethodSurfaceChanged(nullptr);
439 }
440}
441
442void TopLevelWindowModel::onWindowsRaised(const std::vector<miral::Window> &windows)
443{
444 const int raiseCount = windows.size();
445 for (int i = 0; i < raiseCount; i++) {
446 int fromIndex = findIndexOf(windows[i]);
447 if (fromIndex != -1) {
448 move(fromIndex, 0);
449 }
450 }
451}
452
453int TopLevelWindowModel::rowCount(const QModelIndex &/*parent*/) const
454{
455 return m_windowModel.count();
456}
457
458QVariant TopLevelWindowModel::data(const QModelIndex& index, int role) const
459{
460 if (index.row() < 0 || index.row() >= m_windowModel.size())
461 return QVariant();
462
463 if (role == WindowRole) {
464 unityapi::WindowInterface *window = m_windowModel.at(index.row()).window;
465 return QVariant::fromValue(window);
466 } else if (role == ApplicationRole) {
467 return QVariant::fromValue(m_windowModel.at(index.row()).application);
468 } else {
469 return QVariant();
470 }
471}
472
473MirSurface *TopLevelWindowModel::find(const miral::WindowInfo &needle) const
474{
475 auto window = needle.window();
476 Q_FOREACH(const auto surface, m_allSurfaces) {
477 if (surface->window() == window) {
478 return surface;
479 }
480 }
481 return nullptr;
482}
483
484int TopLevelWindowModel::findIndexOf(const miral::Window &needle) const
485{
486 for (int i=0; i<m_windowModel.count(); i++) {
487 auto surface = static_cast<MirSurface*>(m_windowModel[i].window->surface());
488 if (surface && surface->window() == needle) {
489 return i;
490 }
491 }
492 return -1;
493}
494
495int TopLevelWindowModel::generateId()
496{
497 int id = m_nextId;
498 m_nextId = nextFreeId(m_nextId + 1);
499 return id;
500}
501
502int TopLevelWindowModel::nextFreeId(int candidateId)
503{
504 if (candidateId > m_maxId) {
505 return nextFreeId(1);
506 } else {
507 if (indexForId(candidateId) == -1) {
508 // it's indeed free
509 return candidateId;
510 } else {
511 return nextFreeId(candidateId + 1);
512 }
513 }
514}
515
516QString TopLevelWindowModel::toString()
517{
518 QString str;
519 for (int i = 0; i < m_windowModel.count(); ++i) {
520 auto item = m_windowModel.at(i);
521
522 QString itemStr = QString("(index=%1,appId=%2,surface=0x%3,id=%4)")
523 .arg(i)
524 .arg(item.application->appId())
525 .arg((qintptr)item.window->surface(), 0, 16)
526 .arg(item.window->id());
527
528 if (i > 0) {
529 str.append(",");
530 }
531 str.append(itemStr);
532 }
533 return str;
534}
535
536int TopLevelWindowModel::indexOf(MirSurfaceInterface *surface)
537{
538 for (int i = 0; i < m_windowModel.count(); ++i) {
539 if (m_windowModel.at(i).window->surface() == surface) {
540 return i;
541 }
542 }
543 return -1;
544}
545
546int TopLevelWindowModel::indexForId(int id) const
547{
548 for (int i = 0; i < m_windowModel.count(); ++i) {
549 if (m_windowModel[i].window->id() == id) {
550 return i;
551 }
552 }
553 return -1;
554}
555
556unityapi::WindowInterface *TopLevelWindowModel::windowAt(int index) const
557{
558 if (index >=0 && index < m_windowModel.count()) {
559 return m_windowModel[index].window;
560 } else {
561 return nullptr;
562 }
563}
564
565unityapi::MirSurfaceInterface *TopLevelWindowModel::surfaceAt(int index) const
566{
567 if (index >=0 && index < m_windowModel.count()) {
568 return m_windowModel[index].window->surface();
569 } else {
570 return nullptr;
571 }
572}
573
574unityapi::ApplicationInfoInterface *TopLevelWindowModel::applicationAt(int index) const
575{
576 if (index >=0 && index < m_windowModel.count()) {
577 return m_windowModel[index].application;
578 } else {
579 return nullptr;
580 }
581}
582
583int TopLevelWindowModel::idAt(int index) const
584{
585 if (index >=0 && index < m_windowModel.count()) {
586 return m_windowModel[index].window->id();
587 } else {
588 return 0;
589 }
590}
591
592void TopLevelWindowModel::raiseId(int id)
593{
594 if (m_modelState == IdleState) {
595 DEBUG_MSG << "(id=" << id << ") - do it now.";
596 doRaiseId(id);
597 } else {
598 DEBUG_MSG << "(id=" << id << ") - Model busy (modelState=" << m_modelState << "). Try again in the next event loop.";
599 // The model has just signalled some change. If we have a Repeater responding to this update, it will get nuts
600 // if we perform yet another model change straight away.
601 //
602 // A bad sympton of this problem is a Repeater.itemAt(index) call returning null event though Repeater.count says
603 // the index is definitely within bounds.
604 QMetaObject::invokeMethod(this, "raiseId", Qt::QueuedConnection, Q_ARG(int, id));
605 }
606}
607
608void TopLevelWindowModel::doRaiseId(int id)
609{
610 int fromIndex = indexForId(id);
611 if (fromIndex != -1) {
612 auto surface = static_cast<MirSurface*>(m_windowModel[fromIndex].window->surface());
613 if (surface) {
614 m_windowController->raise(surface->window());
615 } else {
616 // move it ourselves. Since there's no mir::scene::Surface/miral::Window, there's nothing
617 // miral can do about it.
618 move(fromIndex, 0);
619 }
620 }
621}
622
623void TopLevelWindowModel::setFocusedWindow(Window *window)
624{
625 if (window != m_focusedWindow) {
626 DEBUG_MSG << "(" << window << ")";
627
628 Window* previousWindow = m_focusedWindow;
629
630 m_focusedWindow = window;
631 Q_EMIT focusedWindowChanged(m_focusedWindow);
632
633 if (previousWindow && previousWindow->focused() && !previousWindow->surface()) {
634 // do it ourselves. miral doesn't know about this window
635 previousWindow->setFocused(false);
636 }
637 }
638}
639
640unityapi::MirSurfaceInterface* TopLevelWindowModel::inputMethodSurface() const
641{
642 return m_inputMethodWindow ? m_inputMethodWindow->surface() : nullptr;
643}
644
645unityapi::WindowInterface* TopLevelWindowModel::focusedWindow() const
646{
647 return m_focusedWindow;
648}
649
650void TopLevelWindowModel::move(int from, int to)
651{
652 if (from == to) return;
653 DEBUG_MSG << " from=" << from << " to=" << to;
654
655 if (from >= 0 && from < m_windowModel.size() && to >= 0 && to < m_windowModel.size()) {
656 QModelIndex parent;
657 /* When moving an item down, the destination index needs to be incremented
658 by one, as explained in the documentation:
659 http://qt-project.org/doc/qt-5.0/qtcore/qabstractitemmodel.html#beginMoveRows */
660
661 Q_ASSERT(m_modelState == IdleState);
662 m_modelState = MovingState;
663
664 beginMoveRows(parent, from, from, parent, to + (to > from ? 1 : 0));
665#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
666 const auto &window = m_windowModel.takeAt(from);
667 m_windowModel.insert(to, window);
668#else
669 m_windowModel.move(from, to);
670#endif
671 endMoveRows();
672
673 Q_EMIT listChanged();
674 m_modelState = IdleState;
675
676 DEBUG_MSG << " after " << toString();
677 }
678}
679void TopLevelWindowModel::onModificationsStarted()
680{
681}
682
683void TopLevelWindowModel::onModificationsEnded()
684{
685 if (m_focusedWindowChanged) {
686 setFocusedWindow(m_newlyFocusedWindow);
687 }
688 // reset
689 m_focusedWindowChanged = false;
690 m_newlyFocusedWindow = nullptr;
691}
6920
=== removed file 'src/modules/Unity/Application/toplevelwindowmodel.h'
--- src/modules/Unity/Application/toplevelwindowmodel.h 2016-11-04 11:06:15 +0000
+++ src/modules/Unity/Application/toplevelwindowmodel.h 1970-01-01 00:00:00 +0000
@@ -1,161 +0,0 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef TOPLEVELWINDOWMODEL_H
18#define TOPLEVELWINDOWMODEL_H
19
20#include <QLoggingCategory>
21
22#include "mirsurface.h"
23#include "window.h"
24#include "windowmodelnotifier.h"
25
26// Unity API
27#include <unity/shell/application/TopLevelWindowModelInterface.h>
28
29Q_DECLARE_LOGGING_CATEGORY(QTMIR_TOPLEVELWINDOWMODEL)
30
31namespace unity {
32 namespace shell {
33 namespace application {
34 class ApplicationInfoInterface;
35 class ApplicationManagerInterface;
36 class MirSurfaceInterface;
37 }
38 }
39}
40
41namespace qtmir {
42
43class Application;
44class ApplicationManagerInterface;
45class SessionManager;
46class WindowControllerInterface;
47
48class TopLevelWindowModel : public unity::shell::application::TopLevelWindowModelInterface
49{
50 Q_OBJECT
51
52public:
53 TopLevelWindowModel();
54 explicit TopLevelWindowModel(WindowModelNotifier *notifier,
55 WindowControllerInterface *controller); // For testing
56
57 // From unity::shell::application::TopLevelWindowModelInterface
58 unity::shell::application::MirSurfaceInterface* inputMethodSurface() const override;
59 unity::shell::application::WindowInterface* focusedWindow() const override;
60
61 // From QAbstractItemModel
62 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
63 QVariant data(const QModelIndex& index, int role) const override;
64
65 // Own API
66 void setApplicationManager(ApplicationManagerInterface*);
67
68public Q_SLOTS:
69 // From unity::shell::application::TopLevelWindowModelInterface
70 unity::shell::application::MirSurfaceInterface *surfaceAt(int index) const override;
71 unity::shell::application::WindowInterface *windowAt(int index) const override;
72 unity::shell::application::ApplicationInfoInterface *applicationAt(int index) const override;
73 int idAt(int index) const override;
74 int indexForId(int id) const override;
75 void raiseId(int id) override;
76
77private Q_SLOTS:
78 void onWindowAdded(const qtmir::NewWindow &windowInfo);
79 void onWindowRemoved(const miral::WindowInfo &windowInfo);
80 void onWindowReady(const miral::WindowInfo &windowInfo);
81 void onWindowMoved(const miral::WindowInfo &windowInfo, const QPoint topLeft);
82 void onWindowStateChanged(const miral::WindowInfo &windowInfo, Mir::State state);
83 void onWindowFocusChanged(const miral::WindowInfo &windowInfo, bool focused);
84 void onWindowsRaised(const std::vector<miral::Window> &windows);
85 void onModificationsStarted();
86 void onModificationsEnded();
87
88private:
89 void doRaiseId(int id);
90 int generateId();
91 int nextFreeId(int candidateId);
92 void connectToWindowModelNotifier(WindowModelNotifier *notifier);
93 QString toString();
94 int indexOf(MirSurfaceInterface *surface);
95
96 void setInputMethodWindow(Window *window);
97 void setFocusedWindow(Window *window);
98 void removeInputMethodWindow();
99 MirSurface* find(const miral::WindowInfo &needle) const;
100 int findIndexOf(const miral::Window &needle) const;
101 void removeAt(int index);
102
103 void addApplication(Application *application);
104 void removeApplication(Application *application);
105
106 void prependPlaceholder(Application *application);
107 void prependSurface(MirSurface *surface, Application *application);
108 void prependSurfaceHelper(MirSurface *surface, Application *application);
109
110 void connectWindow(Window *window);
111 void connectSurface(MirSurfaceInterface *surface);
112
113 void onSurfaceDied(MirSurfaceInterface *surface);
114 void onSurfaceDestroyed(MirSurfaceInterface *surface);
115
116 void move(int from, int to);
117
118 void rememberMirSurface(MirSurface *surface);
119 void forgetMirSurface(const miral::Window &window);
120
121 struct ModelEntry {
122 ModelEntry() {}
123 ModelEntry(Window *window,
124 Application *application)
125 : window(window), application(application) {}
126 Window *window{nullptr};
127 Application *application{nullptr};
128 bool removeOnceSurfaceDestroyed{false};
129 };
130
131 QVector<ModelEntry> m_windowModel;
132 WindowControllerInterface *m_windowController;
133 SessionManager* m_sessionManager;
134 Window* m_inputMethodWindow{nullptr};
135 Window* m_focusedWindow{nullptr};
136 QVector<MirSurface*> m_allSurfaces;
137
138 int m_nextId{1};
139 // Just something big enough that we don't risk running out of unused id numbers.
140 // Not sure if QML int type supports something close to std::numeric_limits<int>::max() and
141 // there's no reason to try out its limits.
142 static const int m_maxId{1000000};
143
144 ApplicationManagerInterface* m_applicationManager{nullptr};
145
146 enum ModelState {
147 IdleState,
148 InsertingState,
149 RemovingState,
150 MovingState,
151 ResettingState
152 };
153 ModelState m_modelState{IdleState};
154
155 // Valid between modificationsStarted and modificationsEnded
156 bool m_focusedWindowChanged{false};
157 Window *m_newlyFocusedWindow{nullptr};
158};
159
160} // namespace qtmir
161#endif // TOPLEVELWINDOWMODEL_H
1620
=== removed file 'src/modules/Unity/Application/window.cpp'
--- src/modules/Unity/Application/window.cpp 2016-11-07 11:44:55 +0000
+++ src/modules/Unity/Application/window.cpp 1970-01-01 00:00:00 +0000
@@ -1,186 +0,0 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "window.h"
18#include "mirsurface.h"
19
20#include <QQmlEngine>
21
22namespace unityapi = unity::shell::application;
23using namespace qtmir;
24
25Window::Window(int id)
26 : WindowInterface(nullptr)
27 , m_id(id)
28{
29 QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
30}
31
32QPoint Window::position() const
33{
34 return m_position;
35}
36
37QPoint Window::requestedPosition() const
38{
39 return m_requestedPosition;
40}
41
42void Window::setRequestedPosition(const QPoint &value)
43{
44 if (value != m_requestedPosition) {
45 m_requestedPosition = value;
46 Q_EMIT requestedPositionChanged(m_requestedPosition);
47 if (m_surface) {
48 m_surface->setRequestedPosition(value);
49 } else {
50 // fake-miral: always comply
51 m_position = m_requestedPosition;
52 Q_EMIT positionChanged(m_position);
53 }
54 }
55}
56
57Mir::State Window::state() const
58{
59 return m_state;
60}
61
62bool Window::focused() const
63{
64 return m_focused;
65}
66
67bool Window::confinesMousePointer() const
68{
69 if (m_surface) {
70 return m_surface->confinesMousePointer();
71 } else {
72 return false;
73 }
74}
75
76int Window::id() const
77{
78 return m_id;
79}
80
81unityapi::MirSurfaceInterface* Window::surface() const
82{
83 return m_surface;
84}
85
86void Window::requestState(Mir::State state)
87{
88 if (m_surface) {
89 m_surface->requestState(state);
90 } else if (m_state != state) {
91 m_state = state;
92 Q_EMIT stateChanged(m_state);
93 }
94}
95
96void Window::requestFocus()
97{
98 if (m_surface) {
99 m_surface->requestFocus();
100 } else {
101 Q_EMIT focusRequested();
102 }
103}
104
105void Window::close()
106{
107 if (m_surface) {
108 m_surface->close();
109 } else {
110 Q_EMIT closeRequested();
111 }
112}
113
114void Window::setSurface(MirSurface *surface)
115{
116 if (m_surface) {
117 disconnect(m_surface, 0, this, 0);
118 }
119
120 m_surface = surface;
121
122 if (m_surface) {
123 connect(surface, &MirSurfaceInterface::focusRequested, this, [this]() {
124 Q_EMIT focusRequested();
125 });
126
127 connect(surface, &MirSurfaceInterface::closeRequested, this, &Window::closeRequested);
128
129 connect(surface, &MirSurfaceInterface::positionChanged, this, [this]() {
130 updatePosition();
131 });
132
133 connect(surface, &MirSurfaceInterface::stateChanged, this, [this]() {
134 updateState();
135 });
136
137 connect(surface, &MirSurfaceInterface::focusedChanged, this, [this]() {
138 updateFocused();
139 });
140
141 // bring it up to speed
142 m_surface->setRequestedPosition(m_requestedPosition);
143 m_surface->requestState(m_state);
144
145 // and sync with surface
146 updatePosition();
147 updateState();
148 updateFocused();
149 }
150
151 Q_EMIT surfaceChanged(surface);
152}
153
154void Window::updatePosition()
155{
156 if (m_surface->position() != m_position) {
157 m_position = m_surface->position();
158 Q_EMIT positionChanged(m_position);
159 }
160}
161
162void Window::updateState()
163{
164 if (m_surface->state() != m_state) {
165 m_state = m_surface->state();
166 Q_EMIT stateChanged(m_state);
167 }
168}
169
170void Window::updateFocused()
171{
172 if (m_surface->focused() != m_focused) {
173 m_focused = m_surface->focused();
174 Q_EMIT focusedChanged(m_focused);
175 }
176}
177
178void Window::setFocused(bool value)
179{
180 if (value != m_focused) {
181 m_focused = value;
182 Q_EMIT focusedChanged(m_focused);
183 // when we have a surface we get focus changes from updateFocused() instead
184 Q_ASSERT(!m_surface);
185 }
186}
1870
=== removed file 'src/modules/Unity/Application/window.h'
--- src/modules/Unity/Application/window.h 2016-11-03 20:17:46 +0000
+++ src/modules/Unity/Application/window.h 1970-01-01 00:00:00 +0000
@@ -1,67 +0,0 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef QTMIR_WINDOW_H
18#define QTMIR_WINDOW_H
19
20// unity-api
21#include <unity/shell/application/WindowInterface.h>
22
23namespace qtmir {
24
25class MirSurface;
26
27class Window : public unity::shell::application::WindowInterface
28{
29 Q_OBJECT
30
31public:
32 Window(int id);
33 QPoint position() const override;
34 QPoint requestedPosition() const override;
35 void setRequestedPosition(const QPoint &) override;
36 Mir::State state() const override;
37 bool focused() const override;
38 bool confinesMousePointer() const override;
39 int id() const override;
40 unity::shell::application::MirSurfaceInterface* surface() const override;
41
42 void setSurface(MirSurface *surface);
43 void setFocused(bool value);
44
45public Q_SLOTS:
46 void requestState(Mir::State state) override;
47 void requestFocus() override;
48 void close() override;
49
50Q_SIGNALS:
51 void closeRequested();
52
53private:
54 void updatePosition();
55 void updateState();
56 void updateFocused();
57
58 QPoint m_position;
59 QPoint m_requestedPosition;
60 bool m_focused{false};
61 int m_id;
62 Mir::State m_state{Mir::RestoredState};
63 MirSurface *m_surface{nullptr};
64};
65
66} // namespace qtmir {
67#endif // QTMIR_WINDOW_H

Subscribers

People subscribed via source and target branches

to all changes: