on xenial help sign in
WMScreens attached property & screen fixes
bbd0b9bNick Dedekind
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+142−104
@@ -15,163 +15,190 @@
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)
22−
23+ : QObject(parent)
23−Screen::Screen(qtmir::Screen* screen)
24− : m_wrapped(screen)
25− , m_workspaces(new WorkspaceModel)
26−{
27− QQmlEngine::setObjectOwnership(m_workspaces.data(), QQmlEngine::CppOwnership);
28−
29− connect(m_wrapped, &qtmir::Screen::usedChanged, this, &Screen::usedChanged);
30− connect(m_wrapped, &qtmir::Screen::nameChanged, this, &Screen::nameChanged);
31− connect(m_wrapped, &qtmir::Screen::outputTypeChanged, this, &Screen::outputTypeChanged);
32− connect(m_wrapped, &qtmir::Screen::scaleChanged, this, &Screen::scaleChanged);
33− connect(m_wrapped, &qtmir::Screen::formFactorChanged, this, &Screen::formFactorChanged);
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−
40− // Connect the active workspace to activate the screen.
41− connect(m_workspaces.data(), &WorkspaceModel::workspaceAdded, this, [this](Workspace* workspace) {
42− connect(workspace, &Workspace::activeChanged, this, [this, workspace](bool active) {
43− if (active) {
44− setCurrentWorkspace(workspace);
45− activate();
46− }
47− });
48− if (workspace->isActive()) {
49− activate();
50− setCurrentWorkspace(workspace);
51− }
52− if (!m_currentWorspace) {
53− setCurrentWorkspace(workspace);
54− }
55− });
56− connect(m_workspaces.data(), &WorkspaceModel::workspaceRemoved, this, [this](Workspace* workspace) {
57− disconnect(workspace, &Workspace::activeChanged, this, 0);
58− if (workspace == m_currentWorspace) {
59− resetCurrentWorkspace();
60− }
61− });
62− connect(this, &Screen::activeChanged, this, [this](bool active) {
63− if (active && m_currentWorspace) {
64− m_currentWorspace->activate();
65− }
66− });
67−
68− WorkspaceManager::instance()->createWorkspace()->assign(m_workspaces.data());
69− WorkspaceManager::instance()->createWorkspace()->assign(m_workspaces.data());
70−}
71−
72−Screen::Screen(const Screen &other)
73− : qtmir::Screen(nullptr)
74− , m_wrapped(other.m_wrapped)
75− , m_workspaces(new WorkspaceModelProxy(other.m_workspaces.data()))
76{
24{
77− QQmlEngine::setObjectOwnership(m_workspaces.data(), QQmlEngine::CppOwnership);
78−
79− connect(m_wrapped, &qtmir::Screen::usedChanged, this, &Screen::usedChanged);
80− connect(m_wrapped, &qtmir::Screen::nameChanged, this, &Screen::nameChanged);
81− connect(m_wrapped, &qtmir::Screen::outputTypeChanged, this, &Screen::outputTypeChanged);
82− connect(m_wrapped, &qtmir::Screen::scaleChanged, this, &Screen::scaleChanged);
83− connect(m_wrapped, &qtmir::Screen::formFactorChanged, this, &Screen::formFactorChanged);
84− connect(m_wrapped, &qtmir::Screen::physicalSizeChanged, this, &Screen::physicalSizeChanged);
85− connect(m_wrapped, &qtmir::Screen::positionChanged, this, &Screen::positionChanged);
86− connect(m_wrapped, &qtmir::Screen::activeChanged, this, &Screen::activeChanged);
87− connect(m_wrapped, &qtmir::Screen::currentModeIndexChanged, this, &Screen::currentModeIndexChanged);
88− connect(m_wrapped, &qtmir::Screen::availableModesChanged, this, &Screen::availableModesChanged);
89}
25}
90
26
91−void Screen::resetCurrentWorkspace()
27+void ScreenInterface::connectToScreen(qtmir::Screen *screen)
92{
28{
93− auto newCurrent = m_workspaces->rowCount() > 0 ? m_workspaces->get(0) : nullptr;
29+ m_wrapped = screen;
94− if (m_currentWorspace != newCurrent) {
30+ connect(screen, &qtmir::Screen::usedChanged, this, &ScreenInterface::usedChanged);
95− m_currentWorspace = newCurrent;
31+ connect(screen, &qtmir::Screen::nameChanged, this, &ScreenInterface::nameChanged);
96− Q_EMIT currentWorkspaceChanged(newCurrent);
32+ connect(screen, &qtmir::Screen::outputTypeChanged, this, &ScreenInterface::outputTypeChanged);
97− }
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);
98}
40}
99
41
100−qtmir::OutputId Screen::outputId() const
42+qtmir::OutputId ScreenInterface::outputId() const
101{
43{
44+ if (!m_wrapped) return qtmir::OutputId(-1);
102 return m_wrapped->outputId();
45 return m_wrapped->outputId();
103}
46}
104
47
105−bool Screen::used() const
48+bool ScreenInterface::used() const
106{
49{
50+ if (!m_wrapped) return false;
107 return m_wrapped->used();
51 return m_wrapped->used();
108}
52}
109
53
110−QString Screen::name() const
54+QString ScreenInterface::name() const
111{
55{
56+ if (!m_wrapped) return QString();
112 return m_wrapped->name();
57 return m_wrapped->name();
113}
58}
114
59
115−float Screen::scale() const
60+float ScreenInterface::scale() const
116{
61{
62+ if (!m_wrapped) return 1.0;
117 return m_wrapped->scale();
63 return m_wrapped->scale();
118}
64}
119
65
120−QSizeF Screen::physicalSize() const
66+QSizeF ScreenInterface::physicalSize() const
121{
67{
68+ if (!m_wrapped) return QSizeF();
122 return m_wrapped->physicalSize();
69 return m_wrapped->physicalSize();
123}
70}
124
71
125−qtmir::FormFactor Screen::formFactor() const
72+qtmir::FormFactor ScreenInterface::formFactor() const
126{
73{
74+ if (!m_wrapped) return qtmir::FormFactorUnknown;
127 return m_wrapped->formFactor();
75 return m_wrapped->formFactor();
128}
76}
129
77
130−qtmir::OutputTypes Screen::outputType() const
78+qtmir::OutputTypes ScreenInterface::outputType() const
131{
79{
80+ if (!m_wrapped) return qtmir::Unknown;
132 return m_wrapped->outputType();
81 return m_wrapped->outputType();
133}
82}
134
83
135−MirPowerMode Screen::powerMode() const
84+MirPowerMode ScreenInterface::powerMode() const
136{
85{
86+ if (!m_wrapped) return mir_power_mode_on;
137 return m_wrapped->powerMode();
87 return m_wrapped->powerMode();
138}
88}
139
89
140−Qt::ScreenOrientation Screen::orientation() const
90+Qt::ScreenOrientation ScreenInterface::orientation() const
141{
91{
92+ if (!m_wrapped) return Qt::PrimaryOrientation;
142 return m_wrapped->orientation();
93 return m_wrapped->orientation();
143}
94}
144
95
145−QPoint Screen::position() const
96+QPoint ScreenInterface::position() const
146{
97{
98+ if (!m_wrapped) return QPoint();
147 return m_wrapped->position();
99 return m_wrapped->position();
148}
100}
149
101
150−QQmlListProperty<qtmir::ScreenMode> Screen::availableModes()
102+QQmlListProperty<qtmir::ScreenMode> ScreenInterface::availableModes()
151{
103{
104+ if (!m_wrapped) return QQmlListProperty<qtmir::ScreenMode>();
152 return m_wrapped->availableModes();
105 return m_wrapped->availableModes();
153}
106}
154
107
155−uint Screen::currentModeIndex() const
108+uint ScreenInterface::currentModeIndex() const
156{
109{
110+ if (!m_wrapped) return -1;
157 return m_wrapped->currentModeIndex();
111 return m_wrapped->currentModeIndex();
158}
112}
159
113
160−bool Screen::isActive() const
114+bool ScreenInterface::isActive() const
161{
115{
116+ if (!m_wrapped) return false;
162 return m_wrapped->isActive();
117 return m_wrapped->isActive();
163}
118}
164
119
165−qtmir::ScreenConfiguration *Screen::beginConfiguration() const
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
166{
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;
167 return m_wrapped->beginConfiguration();
140 return m_wrapped->beginConfiguration();
168}
141}
169
142
170−bool Screen::applyConfiguration(qtmir::ScreenConfiguration *configuration)
143+bool ScreenInterface::applyConfiguration(qtmir::ScreenConfiguration *configuration)
171{
144{
145+ if (!m_wrapped) return false;
172 return m_wrapped->applyConfiguration(configuration);
146 return m_wrapped->applyConfiguration(configuration);
173}
147}
174
148
149+void ScreenInterface::sync(ScreenInterface *proxy)
150+{
151+ if (!proxy) return;
152+ workspaces()->sync(proxy->workspaces());
153+}
154+
155+Screen::Screen(qtmir::Screen* wrapped)
156+ : m_workspaces(new WorkspaceModel)
157+{
158+ connectToScreen(wrapped);
159+
160+ // Connect the active workspace to activate the screen.
161+ connect(m_workspaces.data(), &WorkspaceModel::workspaceAdded, this, [this](Workspace* workspace) {
162+ connect(workspace, &Workspace::activeChanged, this, [this, workspace](bool active) {
163+ if (active) {
164+ setCurrentWorkspace(workspace);
165+ activate();
166+ }
167+ });
168+ if (workspace->isActive()) {
169+ activate();
170+ setCurrentWorkspace(workspace);
171+ }
172+ if (!m_currentWorspace) {
173+ setCurrentWorkspace(workspace);
174+ }
175+ });
176+ connect(m_workspaces.data(), &WorkspaceModel::workspaceRemoved, this, [this](Workspace* workspace) {
177+ disconnect(workspace, &Workspace::activeChanged, this, 0);
178+ if (workspace == m_currentWorspace) {
179+ resetCurrentWorkspace();
180+ }
181+ });
182+ connect(this, &Screen::activeChanged, this, [this](bool active) {
183+ if (active && m_currentWorspace) {
184+ m_currentWorspace->activate();
185+ }
186+ });
187+
188+ WorkspaceManager::instance()->createWorkspace()->assign(m_workspaces.data());
189+ WorkspaceManager::instance()->createWorkspace()->assign(m_workspaces.data());
190+}
191+
192+void Screen::resetCurrentWorkspace()
193+{
194+ auto newCurrent = m_workspaces->rowCount() > 0 ? m_workspaces->get(0) : nullptr;
195+ if (m_currentWorspace != newCurrent) {
196+ m_currentWorspace = newCurrent;
197+ Q_EMIT currentWorkspaceChanged(newCurrent);
198+ }
199+}
200+
201+
175WorkspaceModel *Screen::workspaces() const
202WorkspaceModel *Screen::workspaces() const
176{
203{
177 return m_workspaces.data();
204 return m_workspaces.data();
@@ -190,32 +217,43 @@ void Screen::setCurrentWorkspace(Workspace *workspace)
190 }
217 }
191}
218}
192
219
193−void Screen::sync(Screen *proxy)
220+ScreenProxy::ScreenProxy(ScreenInterface *const screen)
194−{
221+ : m_workspaces(new WorkspaceModelProxy(screen->workspaces()))
195− if (!proxy) return;
222+ , m_original(screen)
196−
197− workspaces()->sync(proxy->workspaces());
198−}
199−
200−void Screen::activate()
201{
223{
202− setActive(true);
224+ connectToScreen(screen->wrapped());
225+
226+ auto updateCurrentWorkspaceFn = [this](Workspace* realWorkspace) {
227+ Q_FOREACH(Workspace* workspace, m_workspaces->list()) {
228+ auto p = qobject_cast<WorkspaceProxy*>(workspace);
229+ if (p && p->proxyObject() == realWorkspace) {
230+ if (m_currentWorspace != p) {
231+ m_currentWorspace = p;
232+ Q_EMIT currentWorkspaceChanged(p);
233+ }
234+ }
235+ }
236+ };
237+ connect(screen, &ScreenInterface::currentWorkspaceChanged, this, updateCurrentWorkspaceFn);
238+ updateCurrentWorkspaceFn(screen->currentWorkspace());
203}
239}
204
240
205−void Screen::setActive(bool active)
241+WorkspaceModel *ScreenProxy::workspaces() const
206{
242{
207− m_wrapped->setActive(active);
243+ return m_workspaces.data();
208}
244}
209
245
210−QScreen *Screen::qscreen() const
246+Workspace *ScreenProxy::currentWorkspace() const
211{
247{
212− return m_wrapped->qscreen();
248+ return m_currentWorspace.data();
213}
249}
214
250
215−ScreenProxy::ScreenProxy(ScreenProxy::Screen *const screen)
251+void ScreenProxy::setCurrentWorkspace(Workspace *workspace)
216− : Screen(*screen)
217− , m_original(screen)
218{
252{
253+ auto p = qobject_cast<WorkspaceProxy*>(workspace);
254+ if (p) {
255+ m_original->setCurrentWorkspace(p->proxyObject());
256+ }
219}
257}
220
258
221void ScreenProxy::addWorkspace()
259void ScreenProxy::addWorkspace()
plugins/WindowManager/Screen.h+86−36
@@ -8,74 +8,124 @@
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+
15 Q_PROPERTY(WorkspaceModel* workspaces READ workspaces CONSTANT)
31 Q_PROPERTY(WorkspaceModel* workspaces READ workspaces CONSTANT)
16 Q_PROPERTY(Workspace* currentWorkspace READ currentWorkspace WRITE setCurrentWorkspace NOTIFY currentWorkspaceChanged)
32 Q_PROPERTY(Workspace* currentWorkspace READ currentWorkspace WRITE setCurrentWorkspace NOTIFY currentWorkspaceChanged)
17−
18public:
33public:
19− explicit Screen(qtmir::Screen*const wrapped);
34+ // From qtmir::Screen
20−
21− qtmir::OutputId outputId() const override;
35+ qtmir::OutputId outputId() const;
22− bool used() const override;
36+ bool used() const;
23− QString name() const override;
37+ QString name() const;
24− float scale() const override;
38+ float scale() const;
25− QSizeF physicalSize() const override;
39+ QSizeF physicalSize() const;
26− qtmir::FormFactor formFactor() const override;
40+ qtmir::FormFactor formFactor() const;
27− qtmir::OutputTypes outputType() const override;
41+ qtmir::OutputTypes outputType() const;
28− MirPowerMode powerMode() const override;
42+ MirPowerMode powerMode() const;
29− Qt::ScreenOrientation orientation() const override;
43+ Qt::ScreenOrientation orientation() const;
30− QPoint position() const override;
44+ QPoint position() const;
31− QQmlListProperty<qtmir::ScreenMode> availableModes() override;
45+ QQmlListProperty<qtmir::ScreenMode> availableModes();
32− uint currentModeIndex() const override;
46+ uint currentModeIndex() const;
33− bool isActive() const override;
47+ bool isActive() const;
34− void setActive(bool active) override;
48+ void setActive(bool active);
35−
36− QScreen* qscreen() const override;
49+ QScreen* qscreen() const;
37−
38− qtmir::ScreenConfiguration *beginConfiguration() const override;
50+ qtmir::ScreenConfiguration *beginConfiguration() const;
39− bool applyConfiguration(qtmir::ScreenConfiguration *configuration) override;
51+ bool applyConfiguration(qtmir::ScreenConfiguration *configuration);
52+
53+ virtual WorkspaceModel* workspaces() const = 0;
54+ virtual Workspace *currentWorkspace() const = 0;
55+ virtual void setCurrentWorkspace(Workspace* workspace) = 0;
56+
57+ void sync(ScreenInterface* proxy);
40
58
41 qtmir::Screen* wrapped() const { return m_wrapped; }
59 qtmir::Screen* wrapped() const { return m_wrapped; }
42
60
43− WorkspaceModel* workspaces() const;
44−
45− Workspace *currentWorkspace() const;
46− void setCurrentWorkspace(Workspace* workspace);
47−
48− void sync(Screen* proxy);
49−
50public Q_SLOTS:
61public Q_SLOTS:
51 void activate();
62 void activate();
52
63
53Q_SIGNALS:
64Q_SIGNALS:
65+ void usedChanged();
66+ void nameChanged();
67+ void outputTypeChanged();
68+ void scaleChanged();
69+ void formFactorChanged();
70+ void powerModeChanged();
71+ void orientationChanged();
72+ void positionChanged();
73+ void currentModeIndexChanged();
74+ void physicalSizeChanged();
75+ void availableModesChanged();
76+ void activeChanged(bool active);
54 void currentWorkspaceChanged(Workspace*);
77 void currentWorkspaceChanged(Workspace*);
55
78
56protected:
79protected:
57− Screen(Screen const& other);
80+ ScreenInterface(QObject* parent = 0);
81+
82+ void connectToScreen(qtmir::Screen* screen);
83+
84+protected:
85+ QPointer<qtmir::Screen> m_wrapped;
86+};
58
87
88+
89+class Screen : public ScreenInterface
90+{
91+ Q_OBJECT
92+public:
93+ explicit Screen(qtmir::Screen*const wrapped);
94+
95+ // From qtmir::Screen
96+ WorkspaceModel* workspaces() const override;
97+ Workspace *currentWorkspace() const override;
98+ void setCurrentWorkspace(Workspace* workspace) override;
99+
100+ static ScreenAttached *qmlAttachedProperties(QObject *owner);
101+
102+protected:
59 void resetCurrentWorkspace();
103 void resetCurrentWorkspace();
60
104
61− qtmir::Screen*const m_wrapped;
62 const QScopedPointer<WorkspaceModel> m_workspaces;
105 const QScopedPointer<WorkspaceModel> m_workspaces;
63 QPointer<Workspace> m_currentWorspace;
106 QPointer<Workspace> m_currentWorspace;
64};
107};
65
108
66−class ScreenProxy : public Screen
109+class ScreenProxy : public ScreenInterface
67{
110{
68 Q_OBJECT
111 Q_OBJECT
69public:
112public:
70− explicit ScreenProxy(Screen*const screen);
113+ explicit ScreenProxy(ScreenInterface*const screen);
71
114
115+ // From qtmir::Screen
116+ WorkspaceModel* workspaces() const override;
117+ Workspace *currentWorkspace() const override;
118+ void setCurrentWorkspace(Workspace* workspace) override;
119+
72− Screen* proxyObject() const { return m_original.data(); }
120+ ScreenInterface* proxyObject() const { return m_original.data(); }
73
121
74public Q_SLOTS:
122public Q_SLOTS:
75 void addWorkspace();
123 void addWorkspace();
76
124
77private:
125private:
126+ const QScopedPointer<WorkspaceModel> m_workspaces;
78− const QPointer<Screen> m_original;
127+ const QPointer<ScreenInterface> m_original;
128+ QPointer<Workspace> m_currentWorspace;
79};
129};
80
130
81#endif // SCREEN_H
131#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+55
@@ -0,0 +1,55 @@
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+
24+class QQuickWindow;
25+
26+class ScreenAttached : public ScreenInterface
27+{
28+ Q_OBJECT
29+public:
30+ ScreenAttached(QObject* owner);
31+
32+ WorkspaceModel* workspaces() const override;
33+ Workspace *currentWorkspace() const override;
34+ void setCurrentWorkspace(Workspace* workspace) override;
35+
36+private Q_SLOTS:
37+ void windowChanged(QQuickWindow*);
38+ void screenChanged(QScreen*);
39+ void screenChanged2(ScreenInterface* screen);
40+
41+private:
42+ QPointer<ScreenInterface> m_screen;
43+ QQuickWindow* m_window;
44+};
45+
46+class WMScreen : public QObject
47+{
48+ Q_OBJECT
49+public:
50+ static ScreenAttached *qmlAttachedProperties(QObject *owner);
51+};
52+
53+QML_DECLARE_TYPEINFO(WMScreen, QML_HAS_ATTACHED_PROPERTIES)
54+
55+#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}
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
@@ -33,6 +40,37 @@ public:
33 m_sizes.append(new qtmir::ScreenMode(60, QSize(1920,1080)));
40 m_sizes.append(new qtmir::ScreenMode(60, QSize(1920,1080)));
34 m_physicalSize = QSize(800,568);
41 m_physicalSize = QSize(800,568);
35 }
42 }
43+ ~MockScreen() {
44+ qDeleteAll(m_sizes);
45+ m_sizes.clear();
46+ }
47+
48+ void connectToWindow(QWindow* w)
49+ {
50+ if (m_connectedWindow == w) return;
51+
52+ if (m_connectedWindow) {
53+ disconnect(m_connectedWindow.data());
54+ m_sizes.takeFirst()->deleteLater();
55+ }
56+
57+ m_connectedWindow = w;
58+
59+ if (w) {
60+ connect(w, &ScreenWindow::heightChanged, this, [this](int height) {
61+ m_sizes.first()->size.rheight() = height;
62+ Q_EMIT availableModesChanged();
63+
64+ });
65+ connect(w, &ScreenWindow::widthChanged, this, [this](int width) {
66+ m_sizes.first()->size.rwidth() = width;
67+ Q_EMIT availableModesChanged();
68+ });
69+
70+ m_sizes.push_front(new qtmir::ScreenMode(50, w->size()));
71+ Q_EMIT availableModesChanged();
72+ }
73+ }
36
74
37 qtmir::OutputId outputId() const override { return m_id; }
75 qtmir::OutputId outputId() const override { return m_id; }
38 bool used() const override { return m_used; }
76 bool used() const override { return m_used; }
@@ -58,7 +96,12 @@ public:
58 }
96 }
59 }
97 }
60
98
61− QScreen* qscreen() const override { return nullptr; }
99+ QScreen* qscreen() const override {
100+ if (qGuiApp->topLevelWindows().count() > 0) {
101+ return qGuiApp->topLevelWindows()[0]->screen();
102+ }
103+ return qGuiApp->primaryScreen();
104+ }
62
105
63 qtmir::ScreenConfiguration *beginConfiguration() const override {
106 qtmir::ScreenConfiguration *beginConfiguration() const override {
64 auto config = new qtmir::ScreenConfiguration;
107 auto config = new qtmir::ScreenConfiguration;
@@ -97,6 +140,8 @@ public:
97 uint m_currentModeIndex{0};
140 uint m_currentModeIndex{0};
98 QList<qtmir::ScreenMode*> m_sizes;
141 QList<qtmir::ScreenMode*> m_sizes;
99 QSizeF m_physicalSize;
142 QSizeF m_physicalSize;
143+
144+ QPointer<QWindow> m_connectedWindow;
100};
145};
101}
146}
102
147
@@ -122,6 +167,7 @@ MockScreens::MockScreens()
122MockScreens::~MockScreens()
167MockScreens::~MockScreens()
123{
168{
124 qDeleteAll(m_mocks);
169 qDeleteAll(m_mocks);
170+ m_mocks.clear();
125}
171}
126
172
127QVector<qtmir::Screen *> MockScreens::screens() const
173QVector<qtmir::Screen *> MockScreens::screens() const
@@ -137,4 +183,26 @@ qtmir::Screen *MockScreens::activeScreen() const
137 return nullptr;
183 return nullptr;
138}
184}
139
185
186+QSharedPointer<MockScreens> MockScreens::instance()
187+{
188+ if (!m_screens) {
189+ QSharedPointer<MockScreens> screens(new MockScreens());
190+ m_screens = screens.toWeakRef();
191+ return screens;
192+ } else {
193+ return m_screens.lock();
194+ }
195+}
196+
197+void MockScreens::connectWindow(ScreenWindow *w)
198+{
199+ Screen* screen = w->screenWrapper();
200+ if (!screen) return;
201+
202+ auto mockScreen = qobject_cast<MockScreen*>(screen->wrapped());
203+ if (mockScreen) {
204+ mockScreen->connectToWindow(w);
205+ }
206+}
207+
140#include "MockScreens.moc"
208#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)