on xenial help sign in
merge prereq
d73aca0Michael Zanetti
plugins/WindowManager/CMakeLists.txt+2−1
@@ -12,8 +12,9 @@ set(WINDOWMANAGER_SRC
12 TopLevelWindowModel.cpp
12 TopLevelWindowModel.cpp
13 Window.cpp
13 Window.cpp
14 WindowManagerPlugin.cpp
14 WindowManagerPlugin.cpp
15− Screens.cpp
16 Screen.cpp
15 Screen.cpp
16+ ScreenAttached.cpp
17+ Screens.cpp
17 ScreenWindow.cpp
18 ScreenWindow.cpp
18 Workspace.cpp
19 Workspace.cpp
19 WorkspaceManager.cpp
20 WorkspaceManager.cpp
plugins/WindowManager/Screen.cpp+163−125
@@ -15,125 +15,138 @@
15 */
15 */
16
16
17#include "Screen.h"
17#include "Screen.h"
18+#include "Screens.h"
18#include "WorkspaceManager.h"
19#include "WorkspaceManager.h"
19#include "Workspace.h"
20#include "Workspace.h"
20
21
21−#include <QQmlEngine>
22+ScreenInterface::ScreenInterface(QObject *parent)
23+ : QObject(parent)
24+{
25+}
22
26
23−Screen::Screen(qtmir::Screen* screen)
27+void ScreenInterface::connectToScreen(qtmir::Screen *screen)
24− : m_wrapped(screen)
25− , m_workspaces(new WorkspaceModel)
26{
28{
27− QQmlEngine::setObjectOwnership(m_workspaces.data(), QQmlEngine::CppOwnership);
29+ m_wrapped = screen;
30+ connect(screen, &qtmir::Screen::usedChanged, this, &ScreenInterface::usedChanged);
31+ connect(screen, &qtmir::Screen::nameChanged, this, &ScreenInterface::nameChanged);
32+ connect(screen, &qtmir::Screen::outputTypeChanged, this, &ScreenInterface::outputTypeChanged);
33+ connect(screen, &qtmir::Screen::scaleChanged, this, &ScreenInterface::scaleChanged);
34+ connect(screen, &qtmir::Screen::formFactorChanged, this, &ScreenInterface::formFactorChanged);
35+ connect(screen, &qtmir::Screen::physicalSizeChanged, this, &ScreenInterface::physicalSizeChanged);
36+ connect(screen, &qtmir::Screen::positionChanged, this, &ScreenInterface::positionChanged);
37+ connect(screen, &qtmir::Screen::activeChanged, this, &ScreenInterface::activeChanged);
38+ connect(screen, &qtmir::Screen::currentModeIndexChanged, this, &ScreenInterface::currentModeIndexChanged);
39+ connect(screen, &qtmir::Screen::availableModesChanged, this, &ScreenInterface::availableModesChanged);
40+}
28
41
29− connect(m_wrapped, &qtmir::Screen::usedChanged, this, &Screen::usedChanged);
42+qtmir::OutputId ScreenInterface::outputId() const
30− connect(m_wrapped, &qtmir::Screen::nameChanged, this, &Screen::nameChanged);
43+{
31− connect(m_wrapped, &qtmir::Screen::outputTypeChanged, this, &Screen::outputTypeChanged);
44+ if (!m_wrapped) return qtmir::OutputId(-1);
32− connect(m_wrapped, &qtmir::Screen::scaleChanged, this, &Screen::scaleChanged);
45+ return m_wrapped->outputId();
33− connect(m_wrapped, &qtmir::Screen::formFactorChanged, this, &Screen::formFactorChanged);
46+}
34− connect(m_wrapped, &qtmir::Screen::physicalSizeChanged, this, &Screen::physicalSizeChanged);
35− connect(m_wrapped, &qtmir::Screen::positionChanged, this, &Screen::positionChanged);
36− connect(m_wrapped, &qtmir::Screen::activeChanged, this, &Screen::activeChanged);
37− connect(m_wrapped, &qtmir::Screen::currentModeIndexChanged, this, &Screen::currentModeIndexChanged);
38− connect(m_wrapped, &qtmir::Screen::availableModesChanged, this, &Screen::availableModesChanged);
39− connect(m_wrapped, &qtmir::Screen::outputTypeChanged, this, &Screen::outputTypeNameChanged);
40
47
41− // Connect the active workspace to activate the screen.
48+bool ScreenInterface::used() const
42− connect(m_workspaces.data(), &WorkspaceModel::workspaceAdded, this, [this](Workspace* workspace) {
49+{
43− connect(workspace, &Workspace::activeChanged, this, [this, workspace](bool active) {
50+ if (!m_wrapped) return false;
44− if (active) {
51+ return m_wrapped->used();
45− setCurrentWorkspace(workspace);
46− activate();
47− }
48− });
49− if (workspace->isActive()) {
50− activate();
51− setCurrentWorkspace(workspace);
52− }
53− if (!m_currentWorspace) {
54− setCurrentWorkspace(workspace);
55− }
56− });
57− connect(m_workspaces.data(), &WorkspaceModel::workspaceRemoved, this, [this](Workspace* workspace) {
58− disconnect(workspace, &Workspace::activeChanged, this, 0);
59− if (workspace == m_currentWorspace) {
60− resetCurrentWorkspace();
61− }
62− });
63− connect(this, &Screen::activeChanged, this, [this](bool active) {
64− if (active && m_currentWorspace) {
65− m_currentWorspace->activate();
66− }
52+}
67− });
68
53
69− WorkspaceManager::instance()->createWorkspace()->assign(m_workspaces.data());
54+QString ScreenInterface::name() const
70− WorkspaceManager::instance()->createWorkspace()->assign(m_workspaces.data());
55+{
56+ if (!m_wrapped) return QString();
57+ return m_wrapped->name();
71}
58}
72
59
73−Screen::Screen(const Screen &other)
60+float ScreenInterface::scale() const
74− : qtmir::Screen(nullptr)
75− , m_wrapped(other.m_wrapped)
76− , m_workspaces(new WorkspaceModelProxy(other.m_workspaces.data()))
77{
61{
78− QQmlEngine::setObjectOwnership(m_workspaces.data(), QQmlEngine::CppOwnership);
62+ if (!m_wrapped) return 1.0;
63+ return m_wrapped->scale();
64+}
79
65
80− connect(m_wrapped, &qtmir::Screen::usedChanged, this, &Screen::usedChanged);
66+QSizeF ScreenInterface::physicalSize() const
81− connect(m_wrapped, &qtmir::Screen::nameChanged, this, &Screen::nameChanged);
67+{
82− connect(m_wrapped, &qtmir::Screen::outputTypeChanged, this, &Screen::outputTypeChanged);
68+ if (!m_wrapped) return QSizeF();
83− connect(m_wrapped, &qtmir::Screen::scaleChanged, this, &Screen::scaleChanged);
69+ return m_wrapped->physicalSize();
84− connect(m_wrapped, &qtmir::Screen::formFactorChanged, this, &Screen::formFactorChanged);
85− connect(m_wrapped, &qtmir::Screen::physicalSizeChanged, this, &Screen::physicalSizeChanged);
86− connect(m_wrapped, &qtmir::Screen::positionChanged, this, &Screen::positionChanged);
87− connect(m_wrapped, &qtmir::Screen::activeChanged, this, &Screen::activeChanged);
88− connect(m_wrapped, &qtmir::Screen::currentModeIndexChanged, this, &Screen::currentModeIndexChanged);
89− connect(m_wrapped, &qtmir::Screen::availableModesChanged, this, &Screen::availableModesChanged);
90}
70}
91
71
92−void Screen::resetCurrentWorkspace()
72+qtmir::FormFactor ScreenInterface::formFactor() const
93{
73{
94− auto newCurrent = m_workspaces->rowCount() > 0 ? m_workspaces->get(0) : nullptr;
74+ if (!m_wrapped) return qtmir::FormFactorUnknown;
95− if (m_currentWorspace != newCurrent) {
75+ return m_wrapped->formFactor();
96− m_currentWorspace = newCurrent;
97− Q_EMIT currentWorkspaceChanged(newCurrent);
98− }
99}
76}
100
77
101−qtmir::OutputId Screen::outputId() const
78+qtmir::OutputTypes ScreenInterface::outputType() const
102{
79{
80+ if (!m_wrapped) return qtmir::Unknown;
103− return m_wrapped->outputId();
81+ return m_wrapped->outputType();
104}
82}
105
83
106−bool Screen::used() const
84+MirPowerMode ScreenInterface::powerMode() const
107{
85{
86+ if (!m_wrapped) return mir_power_mode_on;
108− return m_wrapped->used();
87+ return m_wrapped->powerMode();
109}
88}
110
89
111−QString Screen::name() const
90+Qt::ScreenOrientation ScreenInterface::orientation() const
112{
91{
92+ if (!m_wrapped) return Qt::PrimaryOrientation;
113− return m_wrapped->name();
93+ return m_wrapped->orientation();
114}
94}
115
95
116−float Screen::scale() const
96+QPoint ScreenInterface::position() const
117{
97{
98+ if (!m_wrapped) return QPoint();
118− return m_wrapped->scale();
99+ return m_wrapped->position();
119}
100}
120
101
121−QSizeF Screen::physicalSize() const
102+QQmlListProperty<qtmir::ScreenMode> ScreenInterface::availableModes()
122{
103{
104+ if (!m_wrapped) return QQmlListProperty<qtmir::ScreenMode>();
123− return m_wrapped->physicalSize();
105+ return m_wrapped->availableModes();
124}
106}
125
107
126−qtmir::FormFactor Screen::formFactor() const
108+uint ScreenInterface::currentModeIndex() const
127{
109{
110+ if (!m_wrapped) return -1;
128− return m_wrapped->formFactor();
111+ return m_wrapped->currentModeIndex();
129}
112}
130
113
131−qtmir::OutputTypes Screen::outputType() const
114+bool ScreenInterface::isActive() const
132{
115{
133− return m_wrapped->outputType();
116+ if (!m_wrapped) return false;
117+ return m_wrapped->isActive();
118+}
119+
120+void ScreenInterface::activate()
121+{
122+ setActive(true);
123+}
124+
125+void ScreenInterface::setActive(bool active)
126+{
127+ if (!m_wrapped) return;
128+ m_wrapped->setActive(active);
129+}
130+
131+QScreen *ScreenInterface::qscreen() const
132+{
133+ if (!m_wrapped) return nullptr;
134+ return m_wrapped->qscreen();
135+}
136+
137+qtmir::ScreenConfiguration *ScreenInterface::beginConfiguration() const
138+{
139+ if (!m_wrapped) return nullptr;
140+ return m_wrapped->beginConfiguration();
141+}
142+
143+bool ScreenInterface::applyConfiguration(qtmir::ScreenConfiguration *configuration)
144+{
145+ if (!m_wrapped) return false;
146+ return m_wrapped->applyConfiguration(configuration);
134}
147}
135
148
136−QString Screen::outputTypeName() const
149+QString ScreenInterface::outputTypeName() const
137{
150{
138 switch (m_wrapped->outputType()) {
151 switch (m_wrapped->outputType()) {
139 case qtmir::Unknown:
152 case qtmir::Unknown:
@@ -162,47 +175,61 @@ QString Screen::outputTypeName() const
162 case qtmir::TV:
175 case qtmir::TV:
163 return tr("TV");
176 return tr("TV");
164 }
177 }
178+ return QString();
165}
179}
166
180
167−MirPowerMode Screen::powerMode() const
181+void ScreenInterface::sync(ScreenInterface *proxy)
168−{
169− return m_wrapped->powerMode();
170−}
171−
172−Qt::ScreenOrientation Screen::orientation() const
173{
182{
174− return m_wrapped->orientation();
183+ if (!proxy) return;
175−}
184+ workspaces()->sync(proxy->workspaces());
176−
177−QPoint Screen::position() const
178−{
179− return m_wrapped->position();
180}
185}
181
186
182−QQmlListProperty<qtmir::ScreenMode> Screen::availableModes()
187+Screen::Screen(qtmir::Screen* wrapped)
188+ : m_workspaces(new WorkspaceModel)
183{
189{
184− return m_wrapped->availableModes();
190+ connectToScreen(wrapped);
185−}
186
191
187−uint Screen::currentModeIndex() const
192+ // Connect the active workspace to activate the screen.
188−{
193+ connect(m_workspaces.data(), &WorkspaceModel::workspaceInserted, this, [this](int, Workspace* workspace) {
189− return m_wrapped->currentModeIndex();
194+ connect(workspace, &Workspace::activeChanged, this, [this, workspace](bool active) {
195+ if (active) {
196+ setCurrentWorkspace(workspace);
197+ activate();
198+ }
199+ });
200+ if (workspace->isActive()) {
201+ activate();
202+ setCurrentWorkspace(workspace);
203+ }
204+ if (!m_currentWorspace) {
205+ setCurrentWorkspace(workspace);
206+ }
207+ });
208+ connect(m_workspaces.data(), &WorkspaceModel::workspaceRemoved, this, [this](Workspace* workspace) {
209+ disconnect(workspace, &Workspace::activeChanged, this, 0);
210+ if (workspace == m_currentWorspace) {
211+ resetCurrentWorkspace();
212+ }
213+ });
214+ connect(this, &Screen::activeChanged, this, [this](bool active) {
215+ if (active && m_currentWorspace) {
216+ m_currentWorspace->activate();
217+ }
190−}
218+ });
191
219
192−bool Screen::isActive() const
220+ WorkspaceManager::instance()->createWorkspace()->assign(m_workspaces.data());
193−{
221+ WorkspaceManager::instance()->createWorkspace()->assign(m_workspaces.data());
194− return m_wrapped->isActive();
195}
222}
196
223
197−qtmir::ScreenConfiguration *Screen::beginConfiguration() const
224+void Screen::resetCurrentWorkspace()
198{
225{
199− return m_wrapped->beginConfiguration();
226+ auto newCurrent = m_workspaces->rowCount() > 0 ? m_workspaces->get(0) : nullptr;
227+ if (m_currentWorspace != newCurrent) {
228+ m_currentWorspace = newCurrent;
229+ Q_EMIT currentWorkspaceChanged(newCurrent);
230+ }
200}
231}
201
232
202−bool Screen::applyConfiguration(qtmir::ScreenConfiguration *configuration)
203−{
204− return m_wrapped->applyConfiguration(configuration);
205−}
206
233
207WorkspaceModel *Screen::workspaces() const
234WorkspaceModel *Screen::workspaces() const
208{
235{
@@ -222,32 +249,43 @@ void Screen::setCurrentWorkspace(Workspace *workspace)
222 }
249 }
223}
250}
224
251
225−void Screen::sync(Screen *proxy)
252+ScreenProxy::ScreenProxy(ScreenInterface *const screen)
226−{
253+ : m_workspaces(new WorkspaceModelProxy(screen->workspaces()))
227− if (!proxy) return;
254+ , m_original(screen)
228−
229− workspaces()->sync(proxy->workspaces());
230−}
231−
232−void Screen::activate()
233{
255{
234− setActive(true);
256+ connectToScreen(screen->wrapped());
257+
258+ auto updateCurrentWorkspaceFn = [this](Workspace* realWorkspace) {
259+ Q_FOREACH(Workspace* workspace, m_workspaces->list()) {
260+ auto p = qobject_cast<WorkspaceProxy*>(workspace);
261+ if (p && p->proxyObject() == realWorkspace) {
262+ if (m_currentWorspace != p) {
263+ m_currentWorspace = p;
264+ Q_EMIT currentWorkspaceChanged(p);
265+ }
266+ }
267+ }
268+ };
269+ connect(screen, &ScreenInterface::currentWorkspaceChanged, this, updateCurrentWorkspaceFn);
270+ updateCurrentWorkspaceFn(screen->currentWorkspace());
235}
271}
236
272
237−void Screen::setActive(bool active)
273+WorkspaceModel *ScreenProxy::workspaces() const
238{
274{
239− m_wrapped->setActive(active);
275+ return m_workspaces.data();
240}
276}
241
277
242−QScreen *Screen::qscreen() const
278+Workspace *ScreenProxy::currentWorkspace() const
243{
279{
244− return m_wrapped->qscreen();
280+ return m_currentWorspace.data();
245}
281}
246
282
247−ScreenProxy::ScreenProxy(ScreenProxy::Screen *const screen)
283+void ScreenProxy::setCurrentWorkspace(Workspace *workspace)
248− : Screen(*screen)
249− , m_original(screen)
250{
284{
285+ auto p = qobject_cast<WorkspaceProxy*>(workspace);
286+ if (p) {
287+ m_original->setCurrentWorkspace(p->proxyObject());
288+ }
251}
289}
252
290
253void ScreenProxy::addWorkspace()
291void ScreenProxy::addWorkspace()
plugins/WindowManager/Screen.h+85−36
@@ -8,77 +8,126 @@
8#include "WorkspaceModel.h"
8#include "WorkspaceModel.h"
9
9
10class ScreenProxy;
10class ScreenProxy;
11+class ScreenAttached;
11
12
12−class Screen : public qtmir::Screen
13+class ScreenInterface: public QObject
13{
14{
14 Q_OBJECT
15 Q_OBJECT
16+
17+ Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
18+
19+ Q_PROPERTY(bool used READ used NOTIFY usedChanged)
20+ Q_PROPERTY(QString name READ name NOTIFY nameChanged)
21+ Q_PROPERTY(qtmir::OutputTypes outputType READ outputType NOTIFY outputTypeChanged)
22+ Q_PROPERTY(float scale READ scale NOTIFY scaleChanged)
23+ Q_PROPERTY(qtmir::FormFactor formFactor READ formFactor NOTIFY formFactorChanged)
24+ Q_PROPERTY(MirPowerMode powerMode READ powerMode NOTIFY powerModeChanged)
25+ Q_PROPERTY(Qt::ScreenOrientation orientation READ orientation NOTIFY orientationChanged)
26+ Q_PROPERTY(QPoint position READ position NOTIFY positionChanged)
27+ Q_PROPERTY(uint currentModeIndex READ currentModeIndex NOTIFY currentModeIndexChanged)
28+ Q_PROPERTY(QQmlListProperty<qtmir::ScreenMode> availableModes READ availableModes NOTIFY availableModesChanged)
29+ Q_PROPERTY(QSizeF physicalSize READ physicalSize NOTIFY physicalSizeChanged)
30+ Q_PROPERTY(QString outputTypeName READ outputTypeName NOTIFY outputTypeChanged)
31+
15 Q_PROPERTY(WorkspaceModel* workspaces READ workspaces CONSTANT)
32 Q_PROPERTY(WorkspaceModel* workspaces READ workspaces CONSTANT)
16 Q_PROPERTY(Workspace* currentWorkspace READ currentWorkspace WRITE setCurrentWorkspace NOTIFY currentWorkspaceChanged)
33 Q_PROPERTY(Workspace* currentWorkspace READ currentWorkspace WRITE setCurrentWorkspace NOTIFY currentWorkspaceChanged)
17− Q_PROPERTY(QString outputTypeName READ outputTypeName NOTIFY outputTypeNameChanged)
18−
19public:
34public:
20− explicit Screen(qtmir::Screen*const wrapped);
35+ // From qtmir::Screen
21−
22− qtmir::OutputId outputId() const override;
36+ qtmir::OutputId outputId() const;
23− bool used() const override;
37+ bool used() const;
24− QString name() const override;
38+ QString name() const;
25− float scale() const override;
39+ float scale() const;
26− QSizeF physicalSize() const override;
40+ QSizeF physicalSize() const;
27− qtmir::FormFactor formFactor() const override;
41+ qtmir::FormFactor formFactor() const;
28− qtmir::OutputTypes outputType() const override;
42+ qtmir::OutputTypes outputType() const;
43+ MirPowerMode powerMode() const;
44+ Qt::ScreenOrientation orientation() const;
45+ QPoint position() const;
46+ QQmlListProperty<qtmir::ScreenMode> availableModes();
47+ uint currentModeIndex() const;
48+ bool isActive() const;
49+ void setActive(bool active);
50+ QScreen* qscreen() const;
51+ qtmir::ScreenConfiguration *beginConfiguration() const;
52+ bool applyConfiguration(qtmir::ScreenConfiguration *configuration);
29 QString outputTypeName() const;
53 QString outputTypeName() const;
30− MirPowerMode powerMode() const override;
31− Qt::ScreenOrientation orientation() const override;
32− QPoint position() const override;
33− QQmlListProperty<qtmir::ScreenMode> availableModes() override;
34− uint currentModeIndex() const override;
35− bool isActive() const override;
36− void setActive(bool active) override;
37
54
38− QScreen* qscreen() const override;
55+ virtual WorkspaceModel* workspaces() const = 0;
56+ virtual Workspace *currentWorkspace() const = 0;
57+ virtual void setCurrentWorkspace(Workspace* workspace) = 0;
39
58
40− qtmir::ScreenConfiguration *beginConfiguration() const override;
59+ void sync(ScreenInterface* proxy);
41− bool applyConfiguration(qtmir::ScreenConfiguration *configuration) override;
42
60
43 qtmir::Screen* wrapped() const { return m_wrapped; }
61 qtmir::Screen* wrapped() const { return m_wrapped; }
44
62
45− WorkspaceModel* workspaces() const;
46−
47− Workspace *currentWorkspace() const;
48− void setCurrentWorkspace(Workspace* workspace);
49−
50− void sync(Screen* proxy);
51−
52public Q_SLOTS:
63public Q_SLOTS:
53 void activate();
64 void activate();
54
65
55Q_SIGNALS:
66Q_SIGNALS:
67+ void usedChanged();
68+ void nameChanged();
69+ void outputTypeChanged();
70+ void scaleChanged();
71+ void formFactorChanged();
72+ void powerModeChanged();
73+ void orientationChanged();
74+ void positionChanged();
75+ void currentModeIndexChanged();
76+ void physicalSizeChanged();
77+ void availableModesChanged();
78+ void activeChanged(bool active);
56 void currentWorkspaceChanged(Workspace*);
79 void currentWorkspaceChanged(Workspace*);
57− void outputTypeNameChanged();
58
80
59protected:
81protected:
60− Screen(Screen const& other);
82+ ScreenInterface(QObject* parent = 0);
83+
84+ void connectToScreen(qtmir::Screen* screen);
85+
86+protected:
87+ QPointer<qtmir::Screen> m_wrapped;
88+};
61
89
90+
91+class Screen : public ScreenInterface
92+{
93+ Q_OBJECT
94+public:
95+ explicit Screen(qtmir::Screen*const wrapped);
96+
97+ // From qtmir::Screen
98+ WorkspaceModel* workspaces() const override;
99+ Workspace *currentWorkspace() const override;
100+ void setCurrentWorkspace(Workspace* workspace) override;
101+
102+ static ScreenAttached *qmlAttachedProperties(QObject *owner);
103+
104+protected:
62 void resetCurrentWorkspace();
105 void resetCurrentWorkspace();
63
106
64− qtmir::Screen*const m_wrapped;
65 const QScopedPointer<WorkspaceModel> m_workspaces;
107 const QScopedPointer<WorkspaceModel> m_workspaces;
66 QPointer<Workspace> m_currentWorspace;
108 QPointer<Workspace> m_currentWorspace;
67};
109};
68
110
69−class ScreenProxy : public Screen
111+class ScreenProxy : public ScreenInterface
70{
112{
71 Q_OBJECT
113 Q_OBJECT
72public:
114public:
73− explicit ScreenProxy(Screen*const screen);
115+ explicit ScreenProxy(ScreenInterface*const screen);
74
116
117+ // From qtmir::Screen
118+ WorkspaceModel* workspaces() const override;
119+ Workspace *currentWorkspace() const override;
120+ void setCurrentWorkspace(Workspace* workspace) override;
121+
75− Screen* proxyObject() const { return m_original.data(); }
122+ ScreenInterface* proxyObject() const { return m_original.data(); }
76
123
77public Q_SLOTS:
124public Q_SLOTS:
78 void addWorkspace();
125 void addWorkspace();
79
126
80private:
127private:
128+ const QScopedPointer<WorkspaceModel> m_workspaces;
81− const QPointer<Screen> m_original;
129+ const QPointer<ScreenInterface> m_original;
130+ QPointer<Workspace> m_currentWorspace;
82};
131};
83
132
84#endif // SCREEN_H
133#endif // SCREEN_H
plugins/WindowManager/ScreenAttached.cppnew file+149
@@ -0,0 +1,149 @@
1+/*
2+ * Copyright (C) 2017 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 "ScreenAttached.h"
18+#include "ScreenWindow.h"
19+#include "Screens.h"
20+
21+#include <QQuickItem>
22+#include <QScreen>
23+
24+ScreenAttached::ScreenAttached(QObject *owner)
25+ : ScreenInterface(owner)
26+ , m_window(nullptr)
27+{
28+ if (auto item = qobject_cast<QQuickItem*>(owner)) {
29+ connect(item, &QQuickItem::windowChanged, this, &ScreenAttached::windowChanged);
30+ windowChanged(item->window());
31+ } else if (auto window = qobject_cast<QQuickWindow*>(owner)) {
32+ windowChanged(window);
33+ }
34+}
35+
36+WorkspaceModel *ScreenAttached::workspaces() const
37+{
38+ if (!m_screen) return nullptr;
39+ return m_screen->workspaces();
40+}
41+
42+Workspace *ScreenAttached::currentWorkspace() const
43+{
44+ if (!m_screen) return nullptr;
45+ return m_screen->currentWorkspace();
46+}
47+
48+void ScreenAttached::setCurrentWorkspace(Workspace *workspace)
49+{
50+ if (!m_screen) return;
51+ return m_screen->setCurrentWorkspace(workspace);
52+}
53+
54+void ScreenAttached::windowChanged(QQuickWindow *window)
55+{
56+ if (m_window) {
57+ disconnect(m_window, &QWindow::screenChanged, this, &ScreenAttached::screenChanged);
58+ }
59+
60+ m_window = window;
61+ auto screenWindow = qobject_cast<ScreenWindow*>(window);
62+
63+ if (screenWindow) {
64+ screenChanged2(screenWindow->screenWrapper());
65+ connect(screenWindow, &ScreenWindow::screenWrapperChanged, this, &ScreenAttached::screenChanged2);
66+ } else {
67+ screenChanged(window ? window->screen() : NULL);
68+ if (window) {
69+ connect(window, &QWindow::screenChanged, this, &ScreenAttached::screenChanged);
70+ }
71+ }
72+}
73+
74+void ScreenAttached::screenChanged(QScreen *qscreen)
75+{
76+ // Find a screen that matches.
77+ // Should only get here in mocks if we don't have a ScreenWindow
78+ ScreenInterface* screen{nullptr};
79+ Q_FOREACH(auto s, Screens::self()->list()) {
80+ if (s->qscreen() == qscreen) {
81+ screen = s;
82+ }
83+ }
84+ screenChanged2(screen);
85+}
86+
87+void ScreenAttached::screenChanged2(ScreenInterface* screen)
88+{
89+ if (screen == m_screen) return;
90+
91+ ScreenInterface* oldScreen = m_screen;
92+ m_screen = screen;
93+
94+ if (oldScreen)
95+ oldScreen->disconnect(this);
96+
97+ if (!screen)
98+ return; //Don't bother emitting signals, because the new values are garbage anyways
99+
100+ if (!oldScreen || screen->isActive() != oldScreen->isActive())
101+ Q_EMIT activeChanged(screen->isActive());
102+ if (!oldScreen || screen->used() != oldScreen->used())
103+ Q_EMIT usedChanged();
104+ if (!oldScreen || screen->name() != oldScreen->name())
105+ Q_EMIT nameChanged();
106+ if (!oldScreen || screen->outputType() != oldScreen->outputType())
107+ Q_EMIT outputTypeChanged();
108+ if (!oldScreen || screen->scale() != oldScreen->scale())
109+ Q_EMIT scaleChanged();
110+ if (!oldScreen || screen->formFactor() != oldScreen->formFactor())
111+ Q_EMIT formFactorChanged();
112+ if (!oldScreen || screen->powerMode() != oldScreen->powerMode())
113+ Q_EMIT powerModeChanged();
114+ if (!oldScreen || screen->orientation() != oldScreen->orientation())
115+ Q_EMIT orientationChanged();
116+ if (!oldScreen || screen->position() != oldScreen->position())
117+ Q_EMIT positionChanged();
118+ if (!oldScreen || screen->currentModeIndex() != oldScreen->currentModeIndex())
119+ Q_EMIT currentModeIndexChanged();
120+ if (!oldScreen || screen->physicalSize() != oldScreen->physicalSize())
121+ Q_EMIT physicalSizeChanged();
122+
123+ if (oldScreen) {
124+ QVector<qtmir::ScreenMode*> oldModes;
125+ auto oldModesQmlList = oldScreen->availableModes();
126+ for (int i = 0; i < oldModesQmlList.count(&oldModesQmlList); i++) {
127+ oldModes << oldModesQmlList.at(&oldModesQmlList, i);
128+ }
129+
130+ QVector<qtmir::ScreenMode*> newModes;
131+ auto newModesQmlList = screen->availableModes();
132+ for (int i = 0; i < newModesQmlList.count(&newModesQmlList); i++) {
133+ newModes << newModesQmlList.at(&newModesQmlList, i);
134+ }
135+
136+ if (newModes != newModes) {
137+ Q_EMIT availableModesChanged();
138+ }
139+ } else {
140+ Q_EMIT availableModesChanged();
141+ }
142+
143+ connectToScreen(screen->wrapped());
144+}
145+
146+ScreenAttached *WMScreen::qmlAttachedProperties(QObject *owner)
147+{
148+ return new ScreenAttached(owner);
149+}
plugins/WindowManager/ScreenAttached.hnew file+56
@@ -0,0 +1,56 @@
1+/*
2+ * Copyright (C) 2017 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 SCREENATTACHED_H
18+#define SCREENATTACHED_H
19+
20+#include "Screen.h"
21+
22+#include <QQmlEngine>
23+#include <QtQml>
24+
25+class QQuickWindow;
26+
27+class ScreenAttached : public ScreenInterface
28+{
29+ Q_OBJECT
30+public:
31+ ScreenAttached(QObject* owner);
32+
33+ WorkspaceModel* workspaces() const override;
34+ Workspace *currentWorkspace() const override;
35+ void setCurrentWorkspace(Workspace* workspace) override;
36+
37+private Q_SLOTS:
38+ void windowChanged(QQuickWindow*);
39+ void screenChanged(QScreen*);
40+ void screenChanged2(ScreenInterface* screen);
41+
42+private:
43+ QPointer<ScreenInterface> m_screen;
44+ QQuickWindow* m_window;
45+};
46+
47+class WMScreen : public QObject
48+{
49+ Q_OBJECT
50+public:
51+ static ScreenAttached *qmlAttachedProperties(QObject *owner);
52+};
53+
54+QML_DECLARE_TYPEINFO(WMScreen, QML_HAS_ATTACHED_PROPERTIES)
55+
56+#endif // SCREENATTACHED_H
plugins/WindowManager/ScreenWindow.cpp+1−4
@@ -24,9 +24,6 @@
24ScreenWindow::ScreenWindow(QQuickWindow *parent)
24ScreenWindow::ScreenWindow(QQuickWindow *parent)
25 : QQuickWindow(parent)
25 : QQuickWindow(parent)
26{
26{
27− if (qGuiApp->platformName() != QLatin1String("mirserver")) {
28− qCritical("Not using 'mirserver' QPA plugin. Using ScreenWindow may produce unknown results.");
29− }
30}
27}
31
28
32ScreenWindow::~ScreenWindow()
29ScreenWindow::~ScreenWindow()
@@ -42,7 +39,7 @@ void ScreenWindow::setScreenWrapper(Screen *screen)
42{
39{
43 if (m_screen != screen) {
40 if (m_screen != screen) {
44 m_screen = screen;
41 m_screen = screen;
45− Q_EMIT screenWrapperChanged();
42+ Q_EMIT screenWrapperChanged(screen);
46 }
43 }
47 QQuickWindow::setScreen(screen->qscreen());
44 QQuickWindow::setScreen(screen->qscreen());
48}
45}
plugins/WindowManager/ScreenWindow.h+1−1
@@ -40,7 +40,7 @@ public:
40 void setScreenWrapper(Screen *screen);
40 void setScreenWrapper(Screen *screen);
41
41
42Q_SIGNALS:
42Q_SIGNALS:
43− void screenWrapperChanged();
43+ void screenWrapperChanged(Screen* screen);
44
44
45private:
45private:
46 QPointer<Screen> m_screen;
46 QPointer<Screen> m_screen;
plugins/WindowManager/Screens.cpp+13−5
@@ -27,9 +27,12 @@
27#include <QScreen>
27#include <QScreen>
28#include <QWindow>
28#include <QWindow>
29
29
30+Screens* Screens::m_self{nullptr};
31+
30Screens::Screens(const QSharedPointer<qtmir::Screens>& model)
32Screens::Screens(const QSharedPointer<qtmir::Screens>& model)
31 : m_wrapped(model)
33 : m_wrapped(model)
32{
34{
35+ m_self = this;
33 connect(m_wrapped.data(), &qtmir::Screens::screenAdded, this, &Screens::onScreenAdded);
36 connect(m_wrapped.data(), &qtmir::Screens::screenAdded, this, &Screens::onScreenAdded);
34 connect(m_wrapped.data(), &qtmir::Screens::screenRemoved, this, &Screens::onScreenRemoved);
37 connect(m_wrapped.data(), &qtmir::Screens::screenRemoved, this, &Screens::onScreenRemoved);
35 connect(m_wrapped.data(), &qtmir::Screens::activeScreenChanged, this, &Screens::activeScreenChanged);
38 connect(m_wrapped.data(), &qtmir::Screens::activeScreenChanged, this, &Screens::activeScreenChanged);
@@ -92,6 +95,11 @@ QVariant Screens::activeScreen() const
92 return QVariant();
95 return QVariant();
93}
96}
94
97
98+Screens *Screens::self()
99+{
100+ return Screens::m_self;
101+}
102+
95ScreensProxy *Screens::createProxy()
103ScreensProxy *Screens::createProxy()
96{
104{
97 return new ScreensProxy(this);
105 return new ScreensProxy(this);
@@ -138,7 +146,7 @@ void Screens::onScreenAdded(qtmir::Screen *added)
138void Screens::onScreenRemoved(qtmir::Screen *removed)
146void Screens::onScreenRemoved(qtmir::Screen *removed)
139{
147{
140 int index = 0;
148 int index = 0;
141− QMutableVectorIterator<Screen*> iter(m_screens);
149+ QMutableVectorIterator<ScreenInterface*> iter(m_screens);
142 while(iter.hasNext()) {
150 while(iter.hasNext()) {
143 auto screenWrapper = iter.next();
151 auto screenWrapper = iter.next();
144 if (screenWrapper->wrapped() == removed) {
152 if (screenWrapper->wrapped() == removed) {
@@ -161,7 +169,7 @@ ScreensProxy::ScreensProxy(Screens * const screens)
161 : Screens(*screens)
169 : Screens(*screens)
162 , m_original(screens)
170 , m_original(screens)
163{
171{
164− connect(screens, &Screens::screenAdded, this, [this](Screen *added) {
172+ connect(screens, &Screens::screenAdded, this, [this](ScreenInterface *added) {
165 Q_FOREACH(auto screen, m_screens) {
173 Q_FOREACH(auto screen, m_screens) {
166 auto proxy = static_cast<ScreenProxy*>(screen);
174 auto proxy = static_cast<ScreenProxy*>(screen);
167 if (proxy->proxyObject() == added) return;
175 if (proxy->proxyObject() == added) return;
@@ -176,9 +184,9 @@ ScreensProxy::ScreensProxy(Screens * const screens)
176 Q_EMIT countChanged();
184 Q_EMIT countChanged();
177 });
185 });
178
186
179− connect(screens, &Screens::screenRemoved, this, [this](Screen *removed) {
187+ connect(screens, &Screens::screenRemoved, this, [this](ScreenInterface *removed) {
180 int index = 0;
188 int index = 0;
181− QMutableVectorIterator<Screen*> iter(m_screens);
189+ QMutableVectorIterator<ScreenInterface*> iter(m_screens);
182 while(iter.hasNext()) {
190 while(iter.hasNext()) {
183 auto proxy = static_cast<ScreenProxy*>(iter.next());
191 auto proxy = static_cast<ScreenProxy*>(iter.next());
184 if (proxy->proxyObject() == removed) {
192 if (proxy->proxyObject() == removed) {
@@ -197,7 +205,7 @@ ScreensProxy::ScreensProxy(Screens * const screens)
197 }
205 }
198 });
206 });
199
207
200− Q_FOREACH(Screen* screen, screens->list()) {
208+ Q_FOREACH(ScreenInterface* screen, screens->list()) {
201 auto screenWrapper(new ScreenProxy(screen));
209 auto screenWrapper(new ScreenProxy(screen));
202 QQmlEngine::setObjectOwnership(screenWrapper, QQmlEngine::CppOwnership);
210 QQmlEngine::setObjectOwnership(screenWrapper, QQmlEngine::CppOwnership);
203 m_screens.push_back(new ScreenProxy(screen));
211 m_screens.push_back(new ScreenProxy(screen));
plugins/WindowManager/Screens.h+8−5
@@ -27,7 +27,7 @@ class Screen;
27class Screens;
27class Screens;
28}
28}
29
29
30−class Screen;
30+class ScreenInterface;
31class ScreensProxy;
31class ScreensProxy;
32
32
33class Screens : public QAbstractListModel
33class Screens : public QAbstractListModel
@@ -55,7 +55,9 @@ public:
55 int count() const;
55 int count() const;
56 QVariant activeScreen() const;
56 QVariant activeScreen() const;
57
57
58− const QVector<Screen*>& list() const { return m_screens; }
58+ const QVector<ScreenInterface*>& list() const { return m_screens; }
59+
60+ static Screens *self();
59
61
60public Q_SLOTS:
62public Q_SLOTS:
61 void activateScreen(const QVariant& index);
63 void activateScreen(const QVariant& index);
@@ -64,8 +66,8 @@ Q_SIGNALS:
64 void countChanged();
66 void countChanged();
65 void activeScreenChanged();
67 void activeScreenChanged();
66
68
67− void screenAdded(Screen* screen);
69+ void screenAdded(ScreenInterface* screen);
68− void screenRemoved(Screen* screen);
70+ void screenRemoved(ScreenInterface* screen);
69
71
70private Q_SLOTS:
72private Q_SLOTS:
71 void onScreenAdded(qtmir::Screen *screen);
73 void onScreenAdded(qtmir::Screen *screen);
@@ -74,8 +76,9 @@ private Q_SLOTS:
74protected:
76protected:
75 Screens(const Screens& other);
77 Screens(const Screens& other);
76
78
77− QVector<Screen*> m_screens;
79+ QVector<ScreenInterface*> m_screens;
78 QSharedPointer<qtmir::Screens> m_wrapped;
80 QSharedPointer<qtmir::Screens> m_wrapped;
81+ static Screens* m_self;
79};
82};
80
83
81class ScreensProxy : public Screens
84class ScreensProxy : public Screens
plugins/WindowManager/WindowManagerPlugin.cpp+9−4
@@ -16,8 +16,9 @@
16
16
17#include "WindowManagerPlugin.h"
17#include "WindowManagerPlugin.h"
18
18
19−#include "Screens.h"
20#include "Screen.h"
19#include "Screen.h"
20+#include "ScreenAttached.h"
21+#include "Screens.h"
21#include "ScreenWindow.h"
22#include "ScreenWindow.h"
22#include "TopLevelWindowModel.h"
23#include "TopLevelWindowModel.h"
23#include "Window.h"
24#include "Window.h"
@@ -28,6 +29,8 @@
28#include <QtQml>
29#include <QtQml>
29#include <qtmir/qtmir.h>
30#include <qtmir/qtmir.h>
30
31
32+static const QString notInstantiatable = QStringLiteral("Not instantiatable");
33+
31static QObject *workspace_manager(QQmlEngine *engine, QJSEngine *scriptEngine)
34static QObject *workspace_manager(QQmlEngine *engine, QJSEngine *scriptEngine)
32{
35{
33 Q_UNUSED(engine)
36 Q_UNUSED(engine)
@@ -44,10 +47,10 @@ void WindowManagerPlugin::registerTypes(const char *uri)
44{
47{
45 qmlRegisterType<TopLevelWindowModel>(uri, 1, 0, "TopLevelWindowModel");
48 qmlRegisterType<TopLevelWindowModel>(uri, 1, 0, "TopLevelWindowModel");
46 qmlRegisterSingletonType<WorkspaceManager>(uri, 1, 0, "WorkspaceManager", workspace_manager);
49 qmlRegisterSingletonType<WorkspaceManager>(uri, 1, 0, "WorkspaceManager", workspace_manager);
47− qmlRegisterUncreatableType<WorkspaceModel>(uri, 1, 0, "WorkspaceModel", "Not a creatable type");
50+ qmlRegisterUncreatableType<WorkspaceModel>(uri, 1, 0, "WorkspaceModel", notInstantiatable);
48 qmlRegisterSingletonType<Screens>(uri, 1, 0, "Screens", screensSingleton);
51 qmlRegisterSingletonType<Screens>(uri, 1, 0, "Screens", screensSingleton);
49− qmlRegisterUncreatableType<qtmir::ScreenMode>(uri, 1, 0, "ScreenMode", "ScreenMode is not creatable.");
52+ qmlRegisterUncreatableType<qtmir::ScreenMode>(uri, 1, 0, "ScreenMode", notInstantiatable);
50− qmlRegisterUncreatableType<Workspace>(uri, 1, 0, "Workspace", "Workspace is not creatable.");
53+ qmlRegisterUncreatableType<Workspace>(uri, 1, 0, "Workspace", notInstantiatable);
51
54
52 qRegisterMetaType<Screen*>("Screen*");
55 qRegisterMetaType<Screen*>("Screen*");
53 qRegisterMetaType<ScreensProxy*>("ScreensProxy*");
56 qRegisterMetaType<ScreensProxy*>("ScreensProxy*");
@@ -58,4 +61,6 @@ void WindowManagerPlugin::registerTypes(const char *uri)
58
61
59 qmlRegisterType<ScreenWindow>(uri, 1, 0, "ScreenWindow");
62 qmlRegisterType<ScreenWindow>(uri, 1, 0, "ScreenWindow");
60 qmlRegisterRevision<QWindow,1>(uri, 1, 0);
63 qmlRegisterRevision<QWindow,1>(uri, 1, 0);
64+
65+ qmlRegisterUncreatableType<WMScreen>(uri, 1, 0, "WMScreen", notInstantiatable);
61}
66}
plugins/WindowManager/WorkspaceModel.cpp+33−4
@@ -43,7 +43,7 @@ void WorkspaceModel::insert(int index, Workspace *workspace)
43
43
44 endInsertRows();
44 endInsertRows();
45
45
46− Q_EMIT workspaceAdded(workspace);
46+ Q_EMIT workspaceInserted(index, workspace);
47 Q_EMIT countChanged();
47 Q_EMIT countChanged();
48}
48}
49
49
@@ -78,7 +78,8 @@ void WorkspaceModel::move(int from, int to)
78 m_workspaces.move(from, to);
78 m_workspaces.move(from, to);
79#endif
79#endif
80 endMoveRows();
80 endMoveRows();
81− Q_EMIT countChanged();
81+
82+ Q_EMIT workspaceMoved(from, to);
82 }
83 }
83}
84}
84
85
@@ -114,6 +115,7 @@ QVariant WorkspaceModel::data(const QModelIndex &index, int role) const
114void WorkspaceModel::sync(WorkspaceModel *proxy)
115void WorkspaceModel::sync(WorkspaceModel *proxy)
115{
116{
116 if (!proxy) return;
117 if (!proxy) return;
118+ m_syncing = proxy;
117 const auto& proxyList = proxy->list();
119 const auto& proxyList = proxy->list();
118
120
119 // check for removals
121 // check for removals
@@ -123,7 +125,7 @@ void WorkspaceModel::sync(WorkspaceModel *proxy)
123
125
124 bool found = false;
126 bool found = false;
125 Q_FOREACH(auto p, proxyList) {
127 Q_FOREACH(auto p, proxyList) {
126− auto workspaceProxy = static_cast<WorkspaceProxy*>(p);
128+ auto workspaceProxy = qobject_cast<WorkspaceProxy*>(p);
127 if (workspaceProxy->proxyObject() == workspace) {
129 if (workspaceProxy->proxyObject() == workspace) {
128 found = true;
130 found = true;
129 break;
131 break;
@@ -140,7 +142,7 @@ void WorkspaceModel::sync(WorkspaceModel *proxy)
140 // existing
142 // existing
141 QSet<Workspace*> newWorkspaces;
143 QSet<Workspace*> newWorkspaces;
142 for (int i = 0; i < proxyList.count(); i++) {
144 for (int i = 0; i < proxyList.count(); i++) {
143− auto workspaceProxy = static_cast<WorkspaceProxy*>(proxyList[i]);
145+ auto workspaceProxy = qobject_cast<WorkspaceProxy*>(proxyList[i]);
144 auto workspace = workspaceProxy->proxyObject();
146 auto workspace = workspaceProxy->proxyObject();
145
147
146 int oldIndex = this->indexOf(workspace);
148 int oldIndex = this->indexOf(workspace);
@@ -166,8 +168,13 @@ void WorkspaceModel::sync(WorkspaceModel *proxy)
166
168
167 WorkspaceManager::instance()->setActiveWorkspace(newActiveWorkspace);
169 WorkspaceManager::instance()->setActiveWorkspace(newActiveWorkspace);
168 }
170 }
171+ m_syncing = nullptr;
169}
172}
170
173
174+bool WorkspaceModel::isSyncingWith(WorkspaceModel *m)
175+{
176+ return m_syncing == m;
177+}
171
178
172WorkspaceModelProxy::WorkspaceModelProxy(WorkspaceModel * const model)
179WorkspaceModelProxy::WorkspaceModelProxy(WorkspaceModel * const model)
173 : m_original(model)
180 : m_original(model)
@@ -177,6 +184,28 @@ WorkspaceModelProxy::WorkspaceModelProxy(WorkspaceModel * const model)
177 QQmlEngine::setObjectOwnership(proxy, QQmlEngine::CppOwnership);
184 QQmlEngine::setObjectOwnership(proxy, QQmlEngine::CppOwnership);
178 proxy->assign(this);
185 proxy->assign(this);
179 }
186 }
187+ connect(m_original, &WorkspaceModel::workspaceInserted, this, [this](int index, Workspace* inserted) {
188+ if (m_original->isSyncingWith(this)) return;
189+
190+ (new WorkspaceProxy(inserted))->assign(this, index);
191+ });
192+ connect(m_original, &WorkspaceModel::workspaceRemoved, this, [this](Workspace* removed) {
193+ if (m_original->isSyncingWith(this)) return;
194+
195+ for (int i = 0; i < rowCount(); i++) {
196+ auto workspaceProxy = qobject_cast<WorkspaceProxy*>(get(i));
197+ auto w = workspaceProxy->proxyObject();
198+ if (w == removed) {
199+ remove(workspaceProxy);
200+ break;
201+ }
202+ }
203+ });
204+ connect(m_original, &WorkspaceModel::workspaceMoved, this, [this](int from, int to) {
205+ if (m_original->isSyncingWith(this)) return;
206+
207+ move(from, to);
208+ });
180}
209}
181
210
182WorkspaceModelProxy::~WorkspaceModelProxy()
211WorkspaceModelProxy::~WorkspaceModelProxy()
plugins/WindowManager/WorkspaceModel.h+5−2
@@ -61,15 +61,18 @@ public:
61 const QVector<Workspace*>& list() const { return m_workspaces; }
61 const QVector<Workspace*>& list() const { return m_workspaces; }
62
62
63 void sync(WorkspaceModel* proxy);
63 void sync(WorkspaceModel* proxy);
64+ bool isSyncingWith(WorkspaceModel*);
64
65
65Q_SIGNALS:
66Q_SIGNALS:
66 void countChanged();
67 void countChanged();
67
68
68− void workspaceAdded(Workspace *workspace);
69+ void workspaceInserted(int index, Workspace *workspace);
69 void workspaceRemoved(Workspace *workspace);
70 void workspaceRemoved(Workspace *workspace);
71+ void workspaceMoved(int from, int to);
70
72
71protected:
73protected:
72 QVector<Workspace*> m_workspaces;
74 QVector<Workspace*> m_workspaces;
75+ WorkspaceModel* m_syncing;
73};
76};
74
77
75class WorkspaceModelProxy : public WorkspaceModel
78class WorkspaceModelProxy : public WorkspaceModel
@@ -81,7 +84,7 @@ public:
81
84
82 Q_INVOKABLE void move(int from, int to) override;
85 Q_INVOKABLE void move(int from, int to) override;
83
86
84−private:
87+protected:
85 const QPointer<WorkspaceModel> m_original;
88 const QPointer<WorkspaceModel> m_original;
86};
89};
87
90
tests/mocks/WindowManager/CMakeLists.txt+3−1
@@ -21,14 +21,16 @@ qt5_use_modules(mockwindowmanagmentpolicy Core)
21
21
22set(WINDOWMANAGER_SRC
22set(WINDOWMANAGER_SRC
23 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Screen.cpp
23 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Screen.cpp
24+ ${CMAKE_SOURCE_DIR}/plugins/WindowManager/ScreenAttached.cpp
24 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Screens.cpp
25 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Screens.cpp
26+ ${CMAKE_SOURCE_DIR}/plugins/WindowManager/ScreenWindow.cpp
25 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/TopLevelWindowModel.cpp
27 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/TopLevelWindowModel.cpp
26 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Window.cpp
28 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Window.cpp
27 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/WorkspaceManager.cpp
29 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/WorkspaceManager.cpp
28 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/WorkspaceModel.cpp
30 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/WorkspaceModel.cpp
29 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Workspace.cpp
31 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Workspace.cpp
30 MockScreens.cpp
32 MockScreens.cpp
31− ScreenWindow.cpp
33+ MockScreenWindow.cpp
32 WindowManagerPlugin.cpp
34 WindowManagerPlugin.cpp
33 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
35 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
34 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
36 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
tests/mocks/WindowManager/ScreenWindow.cpp → tests/mocks/WindowManager/MockScreenWindow.cpprenamed+8−22
@@ -14,35 +14,21 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
15 */
16
16
17−#include "ScreenWindow.h"
17+#include "MockScreenWindow.h"
18−#include "Screen.h"
18+#include "MockScreens.h"
19
19
20// Qt
20// Qt
21#include <QGuiApplication>
21#include <QGuiApplication>
22#include <QDebug>
22#include <QDebug>
23
23
24−ScreenWindow::ScreenWindow(QQuickWindow *parent)
24+MockScreenWindow::MockScreenWindow(QQuickWindow *parent)
25− : QQuickWindow(parent)
25+ : ScreenWindow(parent)
26{
26{
27− if (qGuiApp->platformName() != QLatin1String("mirserver")) {
27+ connect(this, &ScreenWindow::screenWrapperChanged, this, [this]() {
28− qCritical("Not using 'mirserver' QPA plugin. Using ScreenWindow may produce unknown results.");
28+ MockScreens::instance()->connectWindow(this);
29− }
29+ });
30}
30}
31
31
32−ScreenWindow::~ScreenWindow()
32+MockScreenWindow::~MockScreenWindow()
33{
33{
34}
34}
35−
36−Screen *ScreenWindow::screenWrapper() const
37−{
38− return m_screen.data();
39−}
40−
41−void ScreenWindow::setScreenWrapper(Screen *screen)
42−{
43− if (m_screen != screen) {
44− m_screen = screen;
45− Q_EMIT screenWrapperChanged();
46− }
47− QQuickWindow::setScreen(screen->qscreen());
48−}
tests/mocks/WindowManager/ScreenWindow.h → tests/mocks/WindowManager/MockScreenWindow.hrenamed+7−26
@@ -14,36 +14,17 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
15 */
16
16
17−#ifndef UNITY_SCREENWINDOW_H
17+#ifndef MOCK_SCREENWINDOW_H
18−#define UNITY_SCREENWINDOW_H
18+#define MOCK_SCREENWINDOW_H
19
19
20−#include <QQuickWindow>
20+#include "ScreenWindow.h"
21−#include <QPointer>
22
21
23−#include "Screen.h"
22+class MockScreenWindow : public ScreenWindow
24−
25−class ScreenAdapter;
26−
27−/*
28− * ScreenWindow - wrapper of QQuickWindow to enable QML to specify destination screen.
29−**/
30−class ScreenWindow : public QQuickWindow
31{
23{
32 Q_OBJECT
24 Q_OBJECT
33− Q_PROPERTY(Screen *screen READ screenWrapper WRITE setScreenWrapper NOTIFY screenWrapperChanged)
34− Q_PROPERTY(int winId READ winId CONSTANT)
35public:
25public:
36− explicit ScreenWindow(QQuickWindow *parent = 0);
26+ explicit MockScreenWindow(QQuickWindow *parent = 0);
37− ~ScreenWindow();
27+ ~MockScreenWindow();
38−
39− Screen *screenWrapper() const;
40− void setScreenWrapper(Screen *screen);
41−
42−Q_SIGNALS:
43− void screenWrapperChanged();
44−
45−private:
46− QPointer<Screen> m_screen;
47};
28};
48
29
49−#endif // UNITY_SCREENWINDOW_H
30+#endif // MOCK_SCREENWINDOW_H
tests/mocks/WindowManager/MockScreens.cpp+69−1
@@ -15,12 +15,19 @@
15 */
15 */
16
16
17#include "MockScreens.h"
17#include "MockScreens.h"
18+#include "ScreenWindow.h"
18
19
19// qtmirserver
20// qtmirserver
20#include <qtmir/screen.h>
21#include <qtmir/screen.h>
21
22
23+#include <QGuiApplication>
24+#include <QWindow>
25+#include <QWeakPointer>
26+
22namespace {
27namespace {
23
28
29+QWeakPointer<MockScreens> m_screens;
30+
24class MockScreen : public qtmir::Screen
31class MockScreen : public qtmir::Screen
25{
32{
26 Q_OBJECT
33 Q_OBJECT
@@ -34,6 +41,37 @@ public:
34 m_sizes.append(new qtmir::ScreenMode(60, QSize(1920,1080)));
41 m_sizes.append(new qtmir::ScreenMode(60, QSize(1920,1080)));
35 m_physicalSize = QSize(800,568);
42 m_physicalSize = QSize(800,568);
36 }
43 }
44+ ~MockScreen() {
45+ qDeleteAll(m_sizes);
46+ m_sizes.clear();
47+ }
48+
49+ void connectToWindow(QWindow* w)
50+ {
51+ if (m_connectedWindow == w) return;
52+
53+ if (m_connectedWindow) {
54+ disconnect(m_connectedWindow.data());
55+ m_sizes.takeFirst()->deleteLater();
56+ }
57+
58+ m_connectedWindow = w;
59+
60+ if (w) {
61+ connect(w, &ScreenWindow::heightChanged, this, [this](int height) {
62+ m_sizes.first()->size.rheight() = height;
63+ Q_EMIT availableModesChanged();
64+
65+ });
66+ connect(w, &ScreenWindow::widthChanged, this, [this](int width) {
67+ m_sizes.first()->size.rwidth() = width;
68+ Q_EMIT availableModesChanged();
69+ });
70+
71+ m_sizes.push_front(new qtmir::ScreenMode(50, w->size()));
72+ Q_EMIT availableModesChanged();
73+ }
74+ }
37
75
38 qtmir::OutputId outputId() const override { return m_id; }
76 qtmir::OutputId outputId() const override { return m_id; }
39 bool used() const override { return m_used; }
77 bool used() const override { return m_used; }
@@ -60,7 +98,12 @@ public:
60 }
98 }
61 }
99 }
62
100
63− QScreen* qscreen() const override { return nullptr; }
101+ QScreen* qscreen() const override {
102+ if (qGuiApp->topLevelWindows().count() > 0) {
103+ return qGuiApp->topLevelWindows()[0]->screen();
104+ }
105+ return qGuiApp->primaryScreen();
106+ }
64
107
65 qtmir::ScreenConfiguration *beginConfiguration() const override {
108 qtmir::ScreenConfiguration *beginConfiguration() const override {
66 auto config = new qtmir::ScreenConfiguration;
109 auto config = new qtmir::ScreenConfiguration;
@@ -102,6 +145,8 @@ public:
102 uint m_currentModeIndex{0};
145 uint m_currentModeIndex{0};
103 QList<qtmir::ScreenMode*> m_sizes;
146 QList<qtmir::ScreenMode*> m_sizes;
104 QSizeF m_physicalSize;
147 QSizeF m_physicalSize;
148+
149+ QPointer<QWindow> m_connectedWindow;
105};
150};
106}
151}
107
152
@@ -127,6 +172,7 @@ MockScreens::MockScreens()
127MockScreens::~MockScreens()
172MockScreens::~MockScreens()
128{
173{
129 qDeleteAll(m_mocks);
174 qDeleteAll(m_mocks);
175+ m_mocks.clear();
130}
176}
131
177
132QVector<qtmir::Screen *> MockScreens::screens() const
178QVector<qtmir::Screen *> MockScreens::screens() const
@@ -142,4 +188,26 @@ qtmir::Screen *MockScreens::activeScreen() const
142 return nullptr;
188 return nullptr;
143}
189}
144
190
191+QSharedPointer<MockScreens> MockScreens::instance()
192+{
193+ if (!m_screens) {
194+ QSharedPointer<MockScreens> screens(new MockScreens());
195+ m_screens = screens.toWeakRef();
196+ return screens;
197+ } else {
198+ return m_screens.lock();
199+ }
200+}
201+
202+void MockScreens::connectWindow(ScreenWindow *w)
203+{
204+ Screen* screen = w->screenWrapper();
205+ if (!screen) return;
206+
207+ auto mockScreen = qobject_cast<MockScreen*>(screen->wrapped());
208+ if (mockScreen) {
209+ mockScreen->connectToWindow(w);
210+ }
211+}
212+
145#include "MockScreens.moc"
213#include "MockScreens.moc"
tests/mocks/WindowManager/MockScreens.h+9−1
@@ -22,12 +22,14 @@
22
22
23#include <qtmir/screens.h>
23#include <qtmir/screens.h>
24
24
25−class Screen;
26namespace qtmir
25namespace qtmir
27{
26{
28class Screens;
27class Screens;
29}
28}
30
29
30+class Screen;
31+class ScreenWindow;
32+
31class MockScreens : public qtmir::Screens
33class MockScreens : public qtmir::Screens
32{
34{
33 Q_OBJECT
35 Q_OBJECT
@@ -39,8 +41,14 @@ public:
39
41
40 qtmir::Screen *activeScreen() const override;
42 qtmir::Screen *activeScreen() const override;
41
43
44+ static QSharedPointer<MockScreens> instance();
45+
46+public Q_SLOTS:
47+ void connectWindow(ScreenWindow *w);
48+
42private:
49private:
43 QVector<qtmir::Screen*> m_mocks;
50 QVector<qtmir::Screen*> m_mocks;
44};
51};
45
52
53+
46#endif // MOCK_SCREENS_H
54#endif // MOCK_SCREENS_H
tests/mocks/WindowManager/WindowManagerPlugin.cpp+13−9
@@ -16,10 +16,11 @@
16
16
17#include "WindowManagerPlugin.h"
17#include "WindowManagerPlugin.h"
18
18
19−#include "Screens.h"
20−#include "Screen.h"
21#include "MockScreens.h"
19#include "MockScreens.h"
22−#include "ScreenWindow.h"
20+#include "MockScreenWindow.h"
21+#include "Screen.h"
22+#include "ScreenAttached.h"
23+#include "Screens.h"
23#include "TopLevelWindowModel.h"
24#include "TopLevelWindowModel.h"
24#include "Window.h"
25#include "Window.h"
25#include "WorkspaceManager.h"
26#include "WorkspaceManager.h"
@@ -29,6 +30,8 @@
29
30
30#include <QtQml>
31#include <QtQml>
31
32
33+static const QString notInstantiatable = QStringLiteral("Not instantiatable");
34+
32static QObject *workspace_manager(QQmlEngine *engine, QJSEngine *scriptEngine)
35static QObject *workspace_manager(QQmlEngine *engine, QJSEngine *scriptEngine)
33{
36{
34 Q_UNUSED(engine)
37 Q_UNUSED(engine)
@@ -38,18 +41,17 @@ static QObject *workspace_manager(QQmlEngine *engine, QJSEngine *scriptEngine)
38QObject* screensSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
41QObject* screensSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
39 Q_UNUSED(engine);
42 Q_UNUSED(engine);
40 Q_UNUSED(scriptEngine);
43 Q_UNUSED(scriptEngine);
41− QSharedPointer<qtmir::Screens> mockScreens(new MockScreens());
44+ return new Screens(MockScreens::instance());
42− return new Screens(mockScreens);
43}
45}
44
46
45void WindowManagerPlugin::registerTypes(const char *uri)
47void WindowManagerPlugin::registerTypes(const char *uri)
46{
48{
47 qmlRegisterType<TopLevelWindowModel>(uri, 1, 0, "TopLevelWindowModel");
49 qmlRegisterType<TopLevelWindowModel>(uri, 1, 0, "TopLevelWindowModel");
48 qmlRegisterSingletonType<WorkspaceManager>(uri, 1, 0, "WorkspaceManager", workspace_manager);
50 qmlRegisterSingletonType<WorkspaceManager>(uri, 1, 0, "WorkspaceManager", workspace_manager);
49− qmlRegisterUncreatableType<WorkspaceModel>(uri, 1, 0, "WorkspaceModel", "Not a creatable type");
51+ qmlRegisterUncreatableType<WorkspaceModel>(uri, 1, 0, "WorkspaceModel", notInstantiatable);
50 qmlRegisterSingletonType<Screens>(uri, 1, 0, "Screens", screensSingleton);
52 qmlRegisterSingletonType<Screens>(uri, 1, 0, "Screens", screensSingleton);
51− qmlRegisterUncreatableType<qtmir::ScreenMode>(uri, 1, 0, "ScreenMode", "ScreenMode is not creatable.");
53+ qmlRegisterUncreatableType<qtmir::ScreenMode>(uri, 1, 0, "ScreenMode", notInstantiatable);
52− qmlRegisterUncreatableType<Workspace>(uri, 1, 0, "Workspace", "Workspace is not creatable.");
54+ qmlRegisterUncreatableType<Workspace>(uri, 1, 0, "Workspace", notInstantiatable);
53
55
54 qRegisterMetaType<Screen*>("Screen*");
56 qRegisterMetaType<Screen*>("Screen*");
55 qRegisterMetaType<ScreensProxy*>("ScreensProxy*");
57 qRegisterMetaType<ScreensProxy*>("ScreensProxy*");
@@ -58,8 +60,10 @@ void WindowManagerPlugin::registerTypes(const char *uri)
58 qRegisterMetaType<Window*>("Window*");
60 qRegisterMetaType<Window*>("Window*");
59 qRegisterMetaType<QAbstractListModel*>("QAbstractListModel*");
61 qRegisterMetaType<QAbstractListModel*>("QAbstractListModel*");
60
62
61− qmlRegisterType<ScreenWindow>(uri, 1, 0, "ScreenWindow");
63+ qmlRegisterType<MockScreenWindow>(uri, 1, 0, "ScreenWindow");
62 qmlRegisterRevision<QWindow,1>(uri, 1, 0);
64 qmlRegisterRevision<QWindow,1>(uri, 1, 0);
65+
66+ qmlRegisterUncreatableType<WMScreen>(uri, 1, 0, "WMScreen", notInstantiatable);
63}
67}
64
68
65void WindowManagerPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
69void WindowManagerPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
tests/qmltests/tst_ShellApplication.qml+1
@@ -22,6 +22,7 @@ import Unity.Application 0.1
22import Unity.Test 0.1
22import Unity.Test 0.1
23
23
24import "../../qml"
24import "../../qml"
25+import "../../qml/Components"
25import "Stage"
26import "Stage"
26
27
27Rectangle {
28Rectangle {