on xenial help sign in
Fixed issues with syncing
commitac938866720bfb60882ba4e1e14566fc9c834c06 authorNick Dedekind <nick.dedekind@canonical.com> dateWed 22 Mar 2017, 10:55 (10 years ago) parentfbc9a88
22 files changed+362−264
plugins/WindowManager/Screen.cpp+87−49 plugins/WindowManager/Screen.h+16−11 plugins/WindowManager/ScreenAttached.cpp+7−5 plugins/WindowManager/ScreenAttached.h+3−3 plugins/WindowManager/ScreenWindow.cpp+2−2 plugins/WindowManager/ScreenWindow.h+5−5 plugins/WindowManager/Screens.cpp+55−49 plugins/WindowManager/Screens.h+32−19 plugins/WindowManager/TopLevelWindowModel.cpp+5 plugins/WindowManager/TopLevelWindowModel.h+1 plugins/WindowManager/WindowManagerPlugin.cpp+16−5 plugins/WindowManager/WindowManagerPlugin.h+1 plugins/WindowManager/Workspace.cpp+48−35 plugins/WindowManager/Workspace.h+25−13 plugins/WindowManager/WorkspaceManager.cpp+2−29 plugins/WindowManager/WorkspaceManager.h+1−5 plugins/WindowManager/WorkspaceModel.cpp+36−16 plugins/WindowManager/WorkspaceModel.h+10−6 tests/mocks/WindowManager/MockScreens.cpp+2−1 tests/mocks/WindowManager/MockScreens.h+1−1 tests/mocks/WindowManager/WindowManagerPlugin.cpp+6−5 tests/qmltests/Stage/tst_DesktopStage.qml+1−5
plugins/WindowManager/Screen.cpp+87−49
@@ -19,146 +19,184 @@
1919#include "WorkspaceManager.h"
2020#include "Workspace.h"
2121
22−ScreenInterface::ScreenInterface(QObject *parent)
22+Screen::Screen(QObject *parent)
2323 : QObject(parent)
2424{
2525}
2626
27−void ScreenInterface::connectToScreen(qtmir::Screen *screen)
27+void Screen::connectToScreen(qtmir::Screen *screen)
2828{
2929 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);
30+ connect(screen, &qtmir::Screen::usedChanged, this, &Screen::usedChanged);
31+ connect(screen, &qtmir::Screen::nameChanged, this, &Screen::nameChanged);
32+ connect(screen, &qtmir::Screen::outputTypeChanged, this, &Screen::outputTypeChanged);
33+ connect(screen, &qtmir::Screen::outputTypeChanged, this, &Screen::outputTypeNameChanged);
34+ connect(screen, &qtmir::Screen::scaleChanged, this, &Screen::scaleChanged);
35+ connect(screen, &qtmir::Screen::formFactorChanged, this, &Screen::formFactorChanged);
36+ connect(screen, &qtmir::Screen::physicalSizeChanged, this, &Screen::physicalSizeChanged);
37+ connect(screen, &qtmir::Screen::positionChanged, this, &Screen::positionChanged);
38+ connect(screen, &qtmir::Screen::activeChanged, this, &Screen::activeChanged);
39+ connect(screen, &qtmir::Screen::currentModeIndexChanged, this, &Screen::currentModeIndexChanged);
40+ connect(screen, &qtmir::Screen::availableModesChanged, this, &Screen::availableModesChanged);
4041}
4142
42−void ScreenInterface::connectToScreen(ScreenInterface *screen)
43+void Screen::connectToScreen(Screen *screen)
4344{
4445 connectToScreen(screen->wrapped());
45− connect(screen, &ScreenInterface::currentWorkspaceChanged, this, &ScreenInterface::currentWorkspaceChanged);
46+ connect(screen, &Screen::currentWorkspaceChanged, this, &Screen::currentWorkspaceChanged);
4647}
4748
48−qtmir::OutputId ScreenInterface::outputId() const
49+qtmir::OutputId Screen::outputId() const
4950{
5051 if (!m_wrapped) return qtmir::OutputId(-1);
5152 return m_wrapped->outputId();
5253}
5354
54−bool ScreenInterface::used() const
55+bool Screen::used() const
5556{
5657 if (!m_wrapped) return false;
5758 return m_wrapped->used();
5859}
5960
60−QString ScreenInterface::name() const
61+QString Screen::name() const
6162{
6263 if (!m_wrapped) return QString();
6364 return m_wrapped->name();
6465}
6566
66−float ScreenInterface::scale() const
67+float Screen::scale() const
6768{
6869 if (!m_wrapped) return 1.0;
6970 return m_wrapped->scale();
7071}
7172
72−QSizeF ScreenInterface::physicalSize() const
73+QSizeF Screen::physicalSize() const
7374{
7475 if (!m_wrapped) return QSizeF();
7576 return m_wrapped->physicalSize();
7677}
7778
78−qtmir::FormFactor ScreenInterface::formFactor() const
79+qtmir::FormFactor Screen::formFactor() const
7980{
8081 if (!m_wrapped) return qtmir::FormFactorUnknown;
8182 return m_wrapped->formFactor();
8283}
8384
84−qtmir::OutputTypes ScreenInterface::outputType() const
85+qtmir::OutputTypes Screen::outputType() const
8586{
8687 if (!m_wrapped) return qtmir::Unknown;
8788 return m_wrapped->outputType();
8889}
8990
90−MirPowerMode ScreenInterface::powerMode() const
91+MirPowerMode Screen::powerMode() const
9192{
9293 if (!m_wrapped) return mir_power_mode_on;
9394 return m_wrapped->powerMode();
9495}
9596
96−Qt::ScreenOrientation ScreenInterface::orientation() const
97+Qt::ScreenOrientation Screen::orientation() const
9798{
9899 if (!m_wrapped) return Qt::PrimaryOrientation;
99100 return m_wrapped->orientation();
100101}
101102
102−QPoint ScreenInterface::position() const
103+QPoint Screen::position() const
103104{
104105 if (!m_wrapped) return QPoint();
105106 return m_wrapped->position();
106107}
107108
108−QQmlListProperty<qtmir::ScreenMode> ScreenInterface::availableModes()
109+QQmlListProperty<qtmir::ScreenMode> Screen::availableModes()
109110{
110111 if (!m_wrapped) return QQmlListProperty<qtmir::ScreenMode>();
111112 return m_wrapped->availableModes();
112113}
113114
114−uint ScreenInterface::currentModeIndex() const
115+uint Screen::currentModeIndex() const
115116{
116117 if (!m_wrapped) return -1;
117118 return m_wrapped->currentModeIndex();
118119}
119120
120−bool ScreenInterface::isActive() const
121+bool Screen::isActive() const
121122{
122123 if (!m_wrapped) return false;
123124 return m_wrapped->isActive();
124125}
125126
126−void ScreenInterface::activate()
127+void Screen::activate()
127128{
128129 setActive(true);
129130}
130131
131−void ScreenInterface::setActive(bool active)
132+void Screen::setActive(bool active)
132133{
133134 if (!m_wrapped) return;
134135 m_wrapped->setActive(active);
135136}
136137
137−QScreen *ScreenInterface::qscreen() const
138+QScreen *Screen::qscreen() const
138139{
139140 if (!m_wrapped) return nullptr;
140141 return m_wrapped->qscreen();
141142}
142143
143−qtmir::ScreenConfiguration *ScreenInterface::beginConfiguration() const
144+qtmir::ScreenConfiguration *Screen::beginConfiguration() const
144145{
145146 if (!m_wrapped) return nullptr;
146147 return m_wrapped->beginConfiguration();
147148}
148149
149−bool ScreenInterface::applyConfiguration(qtmir::ScreenConfiguration *configuration)
150+bool Screen::applyConfiguration(qtmir::ScreenConfiguration *configuration)
150151{
151152 if (!m_wrapped) return false;
152153 return m_wrapped->applyConfiguration(configuration);
153154}
154155
155−void ScreenInterface::sync(ScreenInterface *proxy)
156+QString Screen::outputTypeName() const
157+{
158+ switch (m_wrapped->outputType()) {
159+ case qtmir::Unknown:
160+ return tr("Unknown");
161+ case qtmir::VGA:
162+ return tr("VGA");
163+ case qtmir::DVII:
164+ case qtmir::DVID:
165+ case qtmir::DVIA:
166+ return tr("DVI");
167+ case qtmir::Composite:
168+ return tr("Composite");
169+ case qtmir::SVideo:
170+ return tr("S-Video");
171+ case qtmir::LVDS:
172+ case qtmir::NinePinDIN:
173+ case qtmir::EDP:
174+ return tr("Internal");
175+ case qtmir::Component:
176+ return tr("Component");
177+ case qtmir::DisplayPort:
178+ return tr("DisplayPort");
179+ case qtmir::HDMIA:
180+ case qtmir::HDMIB:
181+ return tr("HDMI");
182+ case qtmir::TV:
183+ return tr("TV");
184+ }
185+ return QString();
186+}
187+
188+void Screen::setSyncing(bool syncing)
189+{
190+ workspaces()->setSyncing(syncing);
191+}
192+
193+void Screen::sync(Screen *proxy)
156194{
157195 if (!proxy) return;
158196 workspaces()->sync(proxy->workspaces());
159197}
160198
161−Screen::Screen(qtmir::Screen* wrapped)
199+ConcreteScreen::ConcreteScreen(qtmir::Screen* wrapped)
162200 : m_workspaces(new WorkspaceModel)
163201{
164202 connectToScreen(wrapped);
@@ -185,7 +223,7 @@ Screen::Screen(qtmir::Screen* wrapped)
185223 resetCurrentWorkspace();
186224 }
187225 });
188− connect(this, &Screen::activeChanged, this, [this](bool active) {
226+ connect(this, &ConcreteScreen::activeChanged, this, [this](bool active) {
189227 if (active && m_currentWorspace) {
190228 m_currentWorspace->activate();
191229 }
@@ -195,7 +233,7 @@ Screen::Screen(qtmir::Screen* wrapped)
195233 WorkspaceManager::instance()->createWorkspace()->assign(m_workspaces.data());
196234}
197235
198−void Screen::resetCurrentWorkspace()
236+void ConcreteScreen::resetCurrentWorkspace()
199237{
200238 auto newCurrent = m_workspaces->rowCount() > 0 ? m_workspaces->get(0) : nullptr;
201239 if (m_currentWorspace != newCurrent) {
@@ -205,17 +243,17 @@ void Screen::resetCurrentWorkspace()
205243}
206244
207245
208−WorkspaceModel *Screen::workspaces() const
246+WorkspaceModel *ConcreteScreen::workspaces() const
209247{
210248 return m_workspaces.data();
211249}
212250
213−Workspace *Screen::currentWorkspace() const
251+Workspace *ConcreteScreen::currentWorkspace() const
214252{
215253 return m_currentWorspace.data();
216254}
217255
218−void Screen::setCurrentWorkspace(Workspace *workspace)
256+void ConcreteScreen::setCurrentWorkspace(Workspace *workspace)
219257{
220258 if (m_currentWorspace != workspace) {
221259 m_currentWorspace = workspace;
@@ -223,15 +261,15 @@ void Screen::setCurrentWorkspace(Workspace *workspace)
223261 }
224262}
225263
226−ScreenProxy::ScreenProxy(ScreenInterface *const screen)
227− : m_workspaces(new WorkspaceModelProxy(screen->workspaces()))
264+ProxyScreen::ProxyScreen(Screen *const screen)
265+ : m_workspaces(new ProxyWorkspaceModel(screen->workspaces()))
228266 , m_original(screen)
229267{
230268 connectToScreen(screen);
231269
232270 auto updateCurrentWorkspaceFn = [this](Workspace* realWorkspace) {
233271 Q_FOREACH(Workspace* workspace, m_workspaces->list()) {
234− auto p = qobject_cast<WorkspaceProxy*>(workspace);
272+ auto p = qobject_cast<ProxyWorkspace*>(workspace);
235273 if (p && p->proxyObject() == realWorkspace) {
236274 if (m_currentWorspace != p) {
237275 m_currentWorspace = p;
@@ -240,29 +278,29 @@ ScreenProxy::ScreenProxy(ScreenInterface *const screen)
240278 }
241279 }
242280 };
243− connect(screen, &ScreenInterface::currentWorkspaceChanged, this, updateCurrentWorkspaceFn);
281+ connect(screen, &Screen::currentWorkspaceChanged, this, updateCurrentWorkspaceFn);
244282 updateCurrentWorkspaceFn(screen->currentWorkspace());
245283}
246284
247−WorkspaceModel *ScreenProxy::workspaces() const
285+WorkspaceModel *ProxyScreen::workspaces() const
248286{
249287 return m_workspaces.data();
250288}
251289
252−Workspace *ScreenProxy::currentWorkspace() const
290+Workspace *ProxyScreen::currentWorkspace() const
253291{
254292 return m_currentWorspace.data();
255293}
256294
257−void ScreenProxy::setCurrentWorkspace(Workspace *workspace)
295+void ProxyScreen::setCurrentWorkspace(Workspace *workspace)
258296{
259− auto p = qobject_cast<WorkspaceProxy*>(workspace);
297+ auto p = qobject_cast<ProxyWorkspace*>(workspace);
260298 if (p) {
261299 m_original->setCurrentWorkspace(p->proxyObject());
262300 }
263301}
264302
265−void ScreenProxy::addWorkspace()
303+void ProxyScreen::addWorkspace()
266304{
267− (new WorkspaceProxy(WorkspaceManager::instance()->createWorkspace()))->assign(workspaces());
305+ (new ProxyWorkspace(WorkspaceManager::instance()->createWorkspace()))->assign(workspaces());
268306}
plugins/WindowManager/Screen.h+16−11
@@ -7,10 +7,10 @@
77
88#include "WorkspaceModel.h"
99
10−class ScreenProxy;
10+class ProxyScreen;
1111class ScreenAttached;
1212
13−class ScreenInterface: public QObject
13+class Screen: public QObject
1414{
1515 Q_OBJECT
1616
@@ -27,6 +27,7 @@ class ScreenInterface: public QObject
2727 Q_PROPERTY(uint currentModeIndex READ currentModeIndex NOTIFY currentModeIndexChanged)
2828 Q_PROPERTY(QQmlListProperty<qtmir::ScreenMode> availableModes READ availableModes NOTIFY availableModesChanged)
2929 Q_PROPERTY(QSizeF physicalSize READ physicalSize NOTIFY physicalSizeChanged)
30+ Q_PROPERTY(QString outputTypeName READ outputTypeName NOTIFY outputTypeChanged)
3031 Q_PROPERTY(WorkspaceModel* workspaces READ workspaces CONSTANT)
3132 Q_PROPERTY(Workspace* currentWorkspace READ currentWorkspace WRITE setCurrentWorkspace NOTIFY currentWorkspaceChanged)
3233public:
@@ -46,6 +47,8 @@ public:
4647 bool isActive() const;
4748 void setActive(bool active);
4849 QScreen* qscreen() const;
50+ QString outputTypeName() const;
51+
4952 qtmir::ScreenConfiguration *beginConfiguration() const;
5053 bool applyConfiguration(qtmir::ScreenConfiguration *configuration);
5154
@@ -53,7 +56,8 @@ public:
5356 virtual Workspace *currentWorkspace() const = 0;
5457 virtual void setCurrentWorkspace(Workspace* workspace) = 0;
5558
56− void sync(ScreenInterface* proxy);
59+ void setSyncing(bool);
60+ void sync(Screen* proxy);
5761
5862 qtmir::Screen* wrapped() const { return m_wrapped; }
5963
@@ -64,6 +68,7 @@ Q_SIGNALS:
6468 void usedChanged();
6569 void nameChanged();
6670 void outputTypeChanged();
71+ void outputTypeNameChanged();
6772 void scaleChanged();
6873 void formFactorChanged();
6974 void powerModeChanged();
@@ -76,21 +81,21 @@ Q_SIGNALS:
7681 void currentWorkspaceChanged(Workspace*);
7782
7883protected:
79− ScreenInterface(QObject* parent = 0);
84+ Screen(QObject* parent = 0);
8085
8186 void connectToScreen(qtmir::Screen* screen);
82− void connectToScreen(ScreenInterface* screen);
87+ void connectToScreen(Screen* screen);
8388
8489protected:
8590 QPointer<qtmir::Screen> m_wrapped;
8691};
8792
8893
89−class Screen : public ScreenInterface
94+class ConcreteScreen : public Screen
9095{
9196 Q_OBJECT
9297public:
93− explicit Screen(qtmir::Screen*const wrapped);
98+ explicit ConcreteScreen(qtmir::Screen*const wrapped);
9499
95100 // From qtmir::Screen
96101 WorkspaceModel* workspaces() const override;
@@ -106,25 +111,25 @@ protected:
106111 QPointer<Workspace> m_currentWorspace;
107112};
108113
109−class ScreenProxy : public ScreenInterface
114+class ProxyScreen : public Screen
110115{
111116 Q_OBJECT
112117public:
113− explicit ScreenProxy(ScreenInterface*const screen);
118+ explicit ProxyScreen(Screen*const screen);
114119
115120 // From qtmir::Screen
116121 WorkspaceModel* workspaces() const override;
117122 Workspace *currentWorkspace() const override;
118123 void setCurrentWorkspace(Workspace* workspace) override;
119124
120− ScreenInterface* proxyObject() const { return m_original.data(); }
125+ Screen* proxyObject() const { return m_original.data(); }
121126
122127public Q_SLOTS:
123128 void addWorkspace();
124129
125130private:
126131 const QScopedPointer<WorkspaceModel> m_workspaces;
127− const QPointer<ScreenInterface> m_original;
132+ const QPointer<Screen> m_original;
128133 QPointer<Workspace> m_currentWorspace;
129134};
130135
plugins/WindowManager/ScreenAttached.cpp+7−5
@@ -22,7 +22,7 @@
2222#include <QScreen>
2323
2424ScreenAttached::ScreenAttached(QObject *owner)
25− : ScreenInterface(owner)
25+ : Screen(owner)
2626 , m_window(nullptr)
2727{
2828 if (auto item = qobject_cast<QQuickItem*>(owner)) {
@@ -75,8 +75,8 @@ void ScreenAttached::screenChanged(QScreen *qscreen)
7575{
7676 // Find a screen that matches.
7777 // 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()) {
78+ Screen* screen{nullptr};
79+ Q_FOREACH(auto s, ConcreteScreens::self()->list()) {
8080 if (s->qscreen() == qscreen) {
8181 screen = s;
8282 }
@@ -84,11 +84,11 @@ void ScreenAttached::screenChanged(QScreen *qscreen)
8484 screenChanged2(screen);
8585}
8686
87−void ScreenAttached::screenChanged2(ScreenInterface* screen)
87+void ScreenAttached::screenChanged2(Screen* screen)
8888{
8989 if (screen == m_screen) return;
9090
91− ScreenInterface* oldScreen = m_screen;
91+ Screen* oldScreen = m_screen;
9292 m_screen = screen;
9393
9494 if (oldScreen)
@@ -119,6 +119,8 @@ void ScreenAttached::screenChanged2(ScreenInterface* screen)
119119 Q_EMIT currentModeIndexChanged();
120120 if (!oldScreen || screen->physicalSize() != oldScreen->physicalSize())
121121 Q_EMIT physicalSizeChanged();
122+ if (!oldScreen || screen->currentWorkspace() != oldScreen->currentWorkspace())
123+ Q_EMIT currentWorkspaceChanged(currentWorkspace());
122124
123125 if (oldScreen) {
124126 QVector<qtmir::ScreenMode*> oldModes;
plugins/WindowManager/ScreenAttached.h+3−3
@@ -23,7 +23,7 @@
2323
2424class QQuickWindow;
2525
26−class ScreenAttached : public ScreenInterface
26+class ScreenAttached : public Screen
2727{
2828 Q_OBJECT
2929public:
@@ -36,10 +36,10 @@ public:
3636private Q_SLOTS:
3737 void windowChanged(QQuickWindow*);
3838 void screenChanged(QScreen*);
39− void screenChanged2(ScreenInterface* screen);
39+ void screenChanged2(Screen* screen);
4040
4141private:
42− QPointer<ScreenInterface> m_screen;
42+ QPointer<Screen> m_screen;
4343 QQuickWindow* m_window;
4444};
4545
plugins/WindowManager/ScreenWindow.cpp+2−2
@@ -30,12 +30,12 @@ ScreenWindow::~ScreenWindow()
3030{
3131}
3232
33−Screen *ScreenWindow::screenWrapper() const
33+ConcreteScreen *ScreenWindow::screenWrapper() const
3434{
3535 return m_screen.data();
3636}
3737
38−void ScreenWindow::setScreenWrapper(Screen *screen)
38+void ScreenWindow::setScreenWrapper(ConcreteScreen *screen)
3939{
4040 if (m_screen != screen) {
4141 m_screen = screen;
plugins/WindowManager/ScreenWindow.h+5−5
@@ -30,20 +30,20 @@ class ScreenAdapter;
3030class ScreenWindow : public QQuickWindow
3131{
3232 Q_OBJECT
33− Q_PROPERTY(Screen *screen READ screenWrapper WRITE setScreenWrapper NOTIFY screenWrapperChanged)
33+ Q_PROPERTY(ConcreteScreen *screen READ screenWrapper WRITE setScreenWrapper NOTIFY screenWrapperChanged)
3434 Q_PROPERTY(int winId READ winId CONSTANT)
3535public:
3636 explicit ScreenWindow(QQuickWindow *parent = 0);
3737 ~ScreenWindow();
3838
39− Screen *screenWrapper() const;
40− void setScreenWrapper(Screen *screen);
39+ ConcreteScreen *screenWrapper() const;
40+ void setScreenWrapper(ConcreteScreen *screen);
4141
4242Q_SIGNALS:
43− void screenWrapperChanged(Screen* screen);
43+ void screenWrapperChanged(ConcreteScreen* screen);
4444
4545private:
46− QPointer<Screen> m_screen;
46+ QPointer<ConcreteScreen> m_screen;
4747};
4848
4949#endif // UNITY_SCREENWINDOW_H
plugins/WindowManager/Screens.cpp+55−49
@@ -27,21 +27,11 @@
2727#include <QScreen>
2828#include <QWindow>
2929
30−Screens* Screens::m_self{nullptr};
30+ConcreteScreens* ConcreteScreens::m_self{nullptr};
3131
3232Screens::Screens(const QSharedPointer<qtmir::Screens>& model)
3333 : m_wrapped(model)
3434{
35− m_self = this;
36− connect(m_wrapped.data(), &qtmir::Screens::screenAdded, this, &Screens::onScreenAdded);
37− connect(m_wrapped.data(), &qtmir::Screens::screenRemoved, this, &Screens::onScreenRemoved);
38− connect(m_wrapped.data(), &qtmir::Screens::activeScreenChanged, this, &Screens::activeScreenChanged);
39−
40− Q_FOREACH(qtmir::Screen* screen, m_wrapped->screens()) {
41− auto screenWrapper(new Screen(screen));
42− QQmlEngine::setObjectOwnership(screenWrapper, QQmlEngine::CppOwnership);
43− m_screens.push_back(screenWrapper);
44− }
4535}
4636
4737Screens::~Screens()
@@ -50,12 +40,6 @@ Screens::~Screens()
5040 m_screens.clear();
5141}
5242
53−Screens::Screens(const Screens &other)
54− : QAbstractListModel(nullptr)
55− , m_wrapped(other.m_wrapped)
56−{
57−}
58−
5943QHash<int, QByteArray> Screens::roleNames() const
6044{
6145 QHash<int, QByteArray> roles;
@@ -95,47 +79,68 @@ QVariant Screens::activeScreen() const
9579 return QVariant();
9680}
9781
98−Screens *Screens::self()
82+void Screens::activateScreen(const QVariant& vindex)
9983{
100− return Screens::m_self;
84+ bool ok = false;
85+ int index = vindex.toInt(&ok);
86+ if (!ok || index < 0 || m_screens.count() <= index) return;
87+
88+ auto screen = m_screens.at(index);
89+ screen->setActive(true);
10190}
10291
103−ScreensProxy *Screens::createProxy()
92+
93+ConcreteScreens::ConcreteScreens(const QSharedPointer<qtmir::Screens> &model)
94+ : Screens(model)
10495{
105− return new ScreensProxy(this);
96+ m_self = this;
97+ connect(m_wrapped.data(), &qtmir::Screens::screenAdded, this, &ConcreteScreens::onScreenAdded);
98+ connect(m_wrapped.data(), &qtmir::Screens::screenRemoved, this, &ConcreteScreens::onScreenRemoved);
99+ connect(m_wrapped.data(), &qtmir::Screens::activeScreenChanged, this, &ConcreteScreens::activeScreenChanged);
100+
101+ Q_FOREACH(qtmir::Screen* screen, m_wrapped->screens()) {
102+ auto screenWrapper(new ConcreteScreen(screen));
103+ QQmlEngine::setObjectOwnership(screenWrapper, QQmlEngine::CppOwnership);
104+ m_screens.push_back(screenWrapper);
105+ }
106+}
107+
108+ConcreteScreens *ConcreteScreens::self()
109+{
110+ return ConcreteScreens::m_self;
106111}
107112
108−void Screens::sync(Screens *proxy)
113+ProxyScreens *ConcreteScreens::createProxy()
114+{
115+ return new ProxyScreens(this);
116+}
117+
118+void ConcreteScreens::sync(Screens *proxy)
109119{
110120 if (!proxy) return;
111121
122+ for (auto screen : m_screens) {
123+ screen->setSyncing(true);
124+ }
125+
112126 const auto& proxyList = proxy->list();
113127 for (int i = 0; i < m_screens.count() && i < proxyList.count(); ++i) {
114128 m_screens[i]->sync(proxyList[i]);
115129 }
116130
117− // need to clean up all the workspaces we unassigned.
118− WorkspaceManager::instance()->destroyFloatingWorkspaces();
119−}
120−
121−void Screens::activateScreen(const QVariant& vindex)
122−{
123− bool ok = false;
124− int index = vindex.toInt(&ok);
125− if (!ok || index < 0 || m_screens.count() <= index) return;
126−
127− auto screen = m_screens.at(index);
128− screen->setActive(true);
131+ for (auto screen : m_screens) {
132+ screen->setSyncing(false);
133+ }
129134}
130135
131−void Screens::onScreenAdded(qtmir::Screen *added)
136+void ConcreteScreens::onScreenAdded(qtmir::Screen *added)
132137{
133138 Q_FOREACH(auto screenWrapper, m_screens) {
134139 if (screenWrapper->wrapped() == added) return;
135140 }
136141
137142 beginInsertRows(QModelIndex(), count(), count());
138− auto screenWrapper(new Screen(added));
143+ auto screenWrapper(new ConcreteScreen(added));
139144 QQmlEngine::setObjectOwnership(screenWrapper, QQmlEngine::CppOwnership);
140145 m_screens.push_back(screenWrapper);
141146 endInsertRows();
@@ -143,10 +148,10 @@ void Screens::onScreenAdded(qtmir::Screen *added)
143148 Q_EMIT countChanged();
144149}
145150
146−void Screens::onScreenRemoved(qtmir::Screen *removed)
151+void ConcreteScreens::onScreenRemoved(qtmir::Screen *removed)
147152{
148153 int index = 0;
149− QMutableVectorIterator<ScreenInterface*> iter(m_screens);
154+ QMutableVectorIterator<Screen*> iter(m_screens);
150155 while(iter.hasNext()) {
151156 auto screenWrapper = iter.next();
152157 if (screenWrapper->wrapped() == removed) {
@@ -165,18 +170,19 @@ void Screens::onScreenRemoved(qtmir::Screen *removed)
165170 }
166171}
167172
168−ScreensProxy::ScreensProxy(Screens * const screens)
169− : Screens(*screens)
173+
174+ProxyScreens::ProxyScreens(Screens * const screens)
175+ : Screens(screens->m_wrapped)
170176 , m_original(screens)
171177{
172− connect(screens, &Screens::screenAdded, this, [this](ScreenInterface *added) {
178+ connect(screens, &Screens::screenAdded, this, [this](Screen *added) {
173179 Q_FOREACH(auto screen, m_screens) {
174− auto proxy = static_cast<ScreenProxy*>(screen);
180+ auto proxy = static_cast<ProxyScreen*>(screen);
175181 if (proxy->proxyObject() == added) return;
176182 }
177183
178184 beginInsertRows(QModelIndex(), count(), count());
179− auto screenWrapper(new ScreenProxy(added));
185+ auto screenWrapper(new ProxyScreen(added));
180186 QQmlEngine::setObjectOwnership(screenWrapper, QQmlEngine::CppOwnership);
181187 m_screens.push_back(screenWrapper);
182188 endInsertRows();
@@ -184,11 +190,11 @@ ScreensProxy::ScreensProxy(Screens * const screens)
184190 Q_EMIT countChanged();
185191 });
186192
187− connect(screens, &Screens::screenRemoved, this, [this](ScreenInterface *removed) {
193+ connect(screens, &Screens::screenRemoved, this, [this](Screen *removed) {
188194 int index = 0;
189− QMutableVectorIterator<ScreenInterface*> iter(m_screens);
195+ QMutableVectorIterator<Screen*> iter(m_screens);
190196 while(iter.hasNext()) {
191− auto proxy = static_cast<ScreenProxy*>(iter.next());
197+ auto proxy = static_cast<ProxyScreen*>(iter.next());
192198 if (proxy->proxyObject() == removed) {
193199
194200 beginRemoveRows(QModelIndex(), index, index);
@@ -205,9 +211,9 @@ ScreensProxy::ScreensProxy(Screens * const screens)
205211 }
206212 });
207213
208− Q_FOREACH(ScreenInterface* screen, screens->list()) {
209− auto screenWrapper(new ScreenProxy(screen));
214+ Q_FOREACH(Screen* screen, screens->list()) {
215+ auto screenWrapper(new ProxyScreen(screen));
210216 QQmlEngine::setObjectOwnership(screenWrapper, QQmlEngine::CppOwnership);
211− m_screens.push_back(new ScreenProxy(screen));
217+ m_screens.push_back(new ProxyScreen(screen));
212218 }
213219}
plugins/WindowManager/Screens.h+32−19
@@ -27,8 +27,8 @@ class Screen;
2727class Screens;
2828}
2929
30−class ScreenInterface;
31−class ScreensProxy;
30+class Screen;
31+class ProxyScreens;
3232
3333class Screens : public QAbstractListModel
3434{
@@ -41,12 +41,8 @@ public:
4141 ScreenRole = Qt::UserRole + 1
4242 };
4343
44− explicit Screens(const QSharedPointer<qtmir::Screens>& model);
4544 ~Screens();
4645
47− Q_INVOKABLE ScreensProxy *createProxy();
48− Q_INVOKABLE void sync(Screens *proxy);
49−
5046 /* QAbstractItemModel */
5147 QHash<int, QByteArray> roleNames() const override;
5248 QVariant data(const QModelIndex &index, int role = ScreenRole) const override;
@@ -55,9 +51,9 @@ public:
5551 int count() const;
5652 QVariant activeScreen() const;
5753
58− const QVector<ScreenInterface*>& list() const { return m_screens; }
54+ bool isSyncing() const { return m_syncing; }
5955
60− static Screens *self();
56+ const QVector<Screen*>& list() const { return m_screens; }
6157
6258public Q_SLOTS:
6359 void activateScreen(const QVariant& index);
@@ -66,25 +62,42 @@ Q_SIGNALS:
6662 void countChanged();
6763 void activeScreenChanged();
6864
69− void screenAdded(ScreenInterface* screen);
70− void screenRemoved(ScreenInterface* screen);
65+ void screenAdded(Screen* screen);
66+ void screenRemoved(Screen* screen);
67+
68+protected:
69+ Screens(const QSharedPointer<qtmir::Screens>& model);
70+
71+ QVector<Screen*> m_screens;
72+ const QSharedPointer<qtmir::Screens> m_wrapped;
73+ bool m_syncing;
74+
75+ friend class ProxyScreens;
76+};
77+
78+class ConcreteScreens : public Screens
79+{
80+ Q_OBJECT
81+public:
82+ explicit ConcreteScreens(const QSharedPointer<qtmir::Screens>& model);
83+
84+ Q_INVOKABLE ProxyScreens *createProxy();
85+ Q_INVOKABLE void sync(Screens *proxy);
7186
72−private Q_SLOTS:
87+ static ConcreteScreens *self();
88+
89+protected Q_SLOTS:
7390 void onScreenAdded(qtmir::Screen *screen);
7491 void onScreenRemoved(qtmir::Screen *screen);
7592
76−protected:
77− Screens(const Screens& other);
78−
79− QVector<ScreenInterface*> m_screens;
80− QSharedPointer<qtmir::Screens> m_wrapped;
81− static Screens* m_self;
93+private:
94+ static ConcreteScreens* m_self;
8295};
8396
84−class ScreensProxy : public Screens
97+class ProxyScreens : public Screens
8598{
8699public:
87− ScreensProxy(Screens*const screens);
100+ explicit ProxyScreens(Screens*const screens);
88101
89102private:
90103 const QPointer<Screens> m_original;
plugins/WindowManager/TopLevelWindowModel.cpp+5
@@ -50,6 +50,10 @@ TopLevelWindowModel::TopLevelWindowModel(Workspace* workspace)
5050 setSurfaceManager(WindowManagerObjects::instance()->surfaceManager());
5151}
5252
53+TopLevelWindowModel::~TopLevelWindowModel()
54+{
55+}
56+
5357void TopLevelWindowModel::setApplicationManager(unityapi::ApplicationManagerInterface* value)
5458{
5559 if (m_applicationManager == value) {
@@ -398,6 +402,7 @@ void TopLevelWindowModel::onSurfacesAddedToWorkspace(const std::shared_ptr<miral
398402void TopLevelWindowModel::onSurfacesAboutToBeRemovedFromWorkspace(const std::shared_ptr<miral::Workspace> &workspace,
399403 const QVector<unity::shell::application::MirSurfaceInterface *> surfaces)
400404{
405+ qDebug() << "SURFACE ABOUT TO BE REMOVED" << this;
401406 if (!m_workspace || workspace != m_workspace->workspace()) return;
402407
403408 int start = -1;
plugins/WindowManager/TopLevelWindowModel.h+1
@@ -94,6 +94,7 @@ public:
9494 };
9595
9696 TopLevelWindowModel(Workspace* workspace);
97+ ~TopLevelWindowModel();
9798
9899 // From QAbstractItemModel
99100 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
plugins/WindowManager/WindowManagerPlugin.cpp+16−5
@@ -30,6 +30,8 @@
3030#include <QtQml>
3131#include <qtmir/qtmir.h>
3232
33+namespace {
34+
3335static const QString notInstantiatable = QStringLiteral("Not instantiatable");
3436
3537static QObject *workspace_manager(QQmlEngine *engine, QJSEngine *scriptEngine)
@@ -41,7 +43,7 @@ static QObject *workspace_manager(QQmlEngine *engine, QJSEngine *scriptEngine)
4143QObject* screensSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
4244 Q_UNUSED(engine);
4345 Q_UNUSED(scriptEngine);
44− return new Screens(qtmir::get_screen_model());
46+ return ConcreteScreens::self();
4547}
4648QObject* objectsSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
4749 Q_UNUSED(engine);
@@ -49,17 +51,18 @@ QObject* objectsSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
4951 return WindowManagerObjects::instance();
5052}
5153
54+} // namspace
55+
5256void WindowManagerPlugin::registerTypes(const char *uri)
5357{
5458 qmlRegisterSingletonType<WorkspaceManager>(uri, 1, 0, "WorkspaceManager", workspace_manager);
5559 qmlRegisterUncreatableType<WorkspaceModel>(uri, 1, 0, "WorkspaceModel", notInstantiatable);
56− qmlRegisterSingletonType<Screens>(uri, 1, 0, "Screens", screensSingleton);
60+ qmlRegisterSingletonType<ConcreteScreens>(uri, 1, 0, "Screens", screensSingleton);
5761 qmlRegisterUncreatableType<qtmir::ScreenMode>(uri, 1, 0, "ScreenMode", notInstantiatable);
58− qmlRegisterUncreatableType<Workspace>(uri, 1, 0, "Workspace", notInstantiatable);
5962 qmlRegisterSingletonType<WindowManagerObjects>(uri, 1, 0, "WindowManagerObjects", objectsSingleton);
6063
61− qRegisterMetaType<Screen*>("Screen*");
62− qRegisterMetaType<ScreensProxy*>("ScreensProxy*");
64+ qRegisterMetaType<ConcreteScreen*>("ConcreteScreen*");
65+ qRegisterMetaType<ProxyScreens*>("ProxyScreens*");
6366 qRegisterMetaType<Workspace*>("Workspace*");
6467 qRegisterMetaType<TopLevelWindowModel*>("TopLevelWindowModel*");
6568
@@ -71,3 +74,11 @@ void WindowManagerPlugin::registerTypes(const char *uri)
7174
7275 qmlRegisterUncreatableType<WMScreen>(uri, 1, 0, "WMScreen", notInstantiatable);
7376}
77+
78+void WindowManagerPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
79+{
80+ WindowManagerPlugin::initializeEngine(engine, uri);
81+
82+ // Create Screens
83+ new ConcreteScreens(qtmir::get_screen_model());
84+}
plugins/WindowManager/WindowManagerPlugin.h+1
@@ -27,6 +27,7 @@ class WindowManagerPlugin : public QQmlExtensionPlugin
2727
2828public:
2929 void registerTypes(const char *uri) override;
30+ void initializeEngine(QQmlEngine *engine, const char *uri) override;
3031};
3132
3233#endif // WINDOWMANAGER_PLUGIN_H
plugins/WindowManager/Workspace.cpp+48−35
@@ -27,37 +27,18 @@ Workspace::Workspace(QObject *parent)
2727 : QObject(parent)
2828 , m_workspace(WMPolicyInterface::instance()->createWorkspace())
2929 , m_model(nullptr)
30− , m_windowModel(new TopLevelWindowModel(this))
31− , m_active(false)
3230{
3331 setObjectName((QString("Wks%1").arg(nextWorkspace++)));
34−
35− connect(WorkspaceManager::instance(), &WorkspaceManager::activeWorkspaceChanged, this, [this]() {
36− bool newActive = WorkspaceManager::instance()->activeWorkspace() == this;
37− if (newActive != m_active) {
38− m_active = newActive;
39− Q_EMIT activeChanged(m_active);
40−
41− if (m_active) {
42− WMPolicyInterface::instance()->setActiveWorkspace(m_workspace);
43− }
44− }
45− });
4632}
4733
4834Workspace::Workspace(const Workspace &other)
4935 : QObject(nullptr)
5036 , m_workspace(other.m_workspace)
5137 , m_model(nullptr)
52− , m_windowModel(other.m_windowModel)
53− , m_active(other.m_active)
5438{
5539 setObjectName(other.objectName());
5640
57− connect(&other, &Workspace::activeChanged, this, [this](bool active) {
58− m_active = active;
59− Q_EMIT activeChanged(m_active);
60− });
41+ connect(&other, &Workspace::activeChanged, this, &Workspace::activeChanged);
6142}
6243
6344Workspace::~Workspace()
@@ -67,11 +48,6 @@ Workspace::~Workspace()
6748 }
6849}
6950
70−void Workspace::activate()
71−{
72− WorkspaceManager::instance()->setActiveWorkspace(this);
73−}
74−
7551void Workspace::assign(WorkspaceModel *model, const QVariant& vIndex)
7652{
7753 if (m_model == model) return;
@@ -105,39 +81,76 @@ void Workspace::unassign()
10581 assign(nullptr);
10682}
10783
108−void Workspace::release()
84+bool Workspace::isAssigned() const
85+{
86+ return m_model != nullptr;
87+}
88+
89+
90+ConcreteWorkspace::ConcreteWorkspace(QObject *parent)
91+ : Workspace(parent)
92+ , m_active(false)
93+ , m_windowModel(new TopLevelWindowModel(this))
94+{
95+ connect(WorkspaceManager::instance(), &WorkspaceManager::activeWorkspaceChanged, this, [this](Workspace* activeWorkspace) {
96+ bool newActive = activeWorkspace == this;
97+ if (newActive != m_active) {
98+ m_active = newActive;
99+ Q_EMIT activeChanged(m_active);
100+
101+ if (m_active) {
102+ WMPolicyInterface::instance()->setActiveWorkspace(m_workspace);
103+ }
104+ }
105+ });
106+}
107+
108+ConcreteWorkspace::~ConcreteWorkspace()
109109{
110+ WorkspaceManager::instance()->destroyWorkspace(this);
110111 WMPolicyInterface::instance()->releaseWorkspace(m_workspace);
111− deleteLater();
112112}
113113
114−bool Workspace::isAssigned() const
114+TopLevelWindowModel *ConcreteWorkspace::windowModel() const
115115{
116− return m_model != nullptr;
116+ return m_windowModel.data();
117+}
118+
119+void ConcreteWorkspace::activate()
120+{
121+ WorkspaceManager::instance()->setActiveWorkspace(this);
117122}
118123
119−WorkspaceProxy::WorkspaceProxy(Workspace * const workspace)
124+
125+ProxyWorkspace::ProxyWorkspace(Workspace * const workspace)
120126 : Workspace(*workspace)
121127 , m_original(workspace)
122128{
123129}
124130
125−void WorkspaceProxy::assign(WorkspaceModel *model, const QVariant &index)
131+void ProxyWorkspace::assign(WorkspaceModel *model, const QVariant &index)
126132{
127133 Workspace::assign(model, index);
128134}
129135
130−void WorkspaceProxy::unassign()
136+void ProxyWorkspace::unassign()
131137{
132138 Workspace::unassign();
133139}
134140
135−bool WorkspaceProxy::isActive() const
141+bool ProxyWorkspace::isActive() const
136142{
137143 return m_original ? m_original->isActive() : false;
138144}
139145
140−void WorkspaceProxy::activate()
146+TopLevelWindowModel *ProxyWorkspace::windowModel() const
147+{
148+ return m_original ? m_original->windowModel() : nullptr;
149+}
150+
151+void ProxyWorkspace::activate()
141152{
142− if (m_original) m_original->activate();
153+ if (m_original) {
154+ m_original->activate();
155+ }
143156}
plugins/WindowManager/Workspace.h+25−13
@@ -20,6 +20,7 @@
2020#include <QObject>
2121#include <QVariant>
2222#include <QPointer>
23+#include <QSharedPointer>
2324
2425#include <memory>
2526#include <functional>
@@ -41,51 +42,62 @@ class Workspace : public QObject
4142{
4243 Q_OBJECT
4344 Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
44− Q_PROPERTY(TopLevelWindowModel* windowModel READ windowModel NOTIFY windowModelChanged)
45+ Q_PROPERTY(TopLevelWindowModel* windowModel READ windowModel CONSTANT)
4546public:
46− ~Workspace();
47+ virtual ~Workspace();
4748
4849 virtual void assign(WorkspaceModel* model, const QVariant& index = QVariant());
4950 virtual void unassign();
50− void release();
5151
52− virtual bool isActive() const { return m_active; }
52+ virtual bool isActive() const = 0;
53+ virtual TopLevelWindowModel *windowModel() const = 0;
5354
54− TopLevelWindowModel *windowModel() const { return m_windowModel; }
5555 std::shared_ptr<miral::Workspace> workspace() const { return m_workspace; }
5656 bool isAssigned() const;
5757
5858public Q_SLOTS:
59− virtual void activate();
59+ virtual void activate() = 0;
6060
6161Q_SIGNALS:
6262 void assigned();
6363 void unassigned();
6464
6565 void activeChanged(bool);
66− void windowModelChanged();
6766
6867protected:
69− Workspace(QObject *parent = 0);
68+ Workspace(QObject *parent = nullptr);
7069 Workspace(Workspace const& other);
7170
7271 std::shared_ptr<miral::Workspace> m_workspace;
7372 WorkspaceModel* m_model;
74− TopLevelWindowModel* m_windowModel;
75− bool m_active;
73+};
74+
75+class ConcreteWorkspace : public Workspace
76+{
77+public:
78+ explicit ConcreteWorkspace(QObject *parent = nullptr);
79+ ~ConcreteWorkspace();
7680
77− friend class WorkspaceManager;
81+ bool isActive() const override { return m_active; }
82+ TopLevelWindowModel *windowModel() const override;
83+ void activate() override;
84+
85+private:
86+ bool m_active;
87+ const QScopedPointer<TopLevelWindowModel> m_windowModel;
7888};
7989
80−class WorkspaceProxy : public Workspace
90+class ProxyWorkspace : public Workspace
8191{
8292 Q_OBJECT
8393public:
84− WorkspaceProxy(Workspace*const workspace);
94+ explicit ProxyWorkspace(Workspace*const workspace);
95+ ~ProxyWorkspace() = default;
8596
8697 Q_INVOKABLE void assign(WorkspaceModel* model, const QVariant& index = QVariant()) override;
8798
8899 bool isActive() const override;
100+ TopLevelWindowModel *windowModel() const override;
89101 void activate() override;
90102
91103 Workspace* proxyObject() const { return m_original.data(); }
plugins/WindowManager/WorkspaceManager.cpp+2−29
@@ -38,23 +38,12 @@ WorkspaceManager::WorkspaceManager()
3838
3939Workspace *WorkspaceManager::createWorkspace()
4040{
41− auto workspace = new Workspace(this);
41+ auto workspace = new ConcreteWorkspace(this);
4242 QQmlEngine::setObjectOwnership(workspace, QQmlEngine::CppOwnership);
4343 m_allWorkspaces.insert(workspace);
44− m_floatingWorkspaces.append(workspace);
45−
46− connect(workspace, &Workspace::assigned, this, [this, workspace]() {
47− m_floatingWorkspaces.removeOne(workspace);
48− Q_EMIT floatingWorkspacesChanged();
49− });
50− connect(workspace, &Workspace::unassigned, this, [this, workspace]() {
51− m_floatingWorkspaces.append(workspace);
52− Q_EMIT floatingWorkspacesChanged();
53− });
5444
5545 if (m_allWorkspaces.count() == 0 && m_activeWorkspace) {
5646 setActiveWorkspace(nullptr);
57− Q_EMIT activeWorkspaceChanged();
5847 } else if (m_allWorkspaces.count() == 1) {
5948 setActiveWorkspace(workspace);
6049 }
@@ -69,9 +58,7 @@ void WorkspaceManager::destroyWorkspace(Workspace *workspace)
6958 if (workspace->isAssigned()) {
7059 workspace->unassign();
7160 }
72− m_floatingWorkspaces.removeOne(workspace);
7361 m_allWorkspaces.remove(workspace);
74− Q_EMIT floatingWorkspacesChanged();
7562
7663 if (m_activeWorkspace == workspace) {
7764 Q_ASSERT(false); // Shouldn't happen, should have chosen something by now.
@@ -83,20 +70,6 @@ void WorkspaceManager::destroyWorkspace(Workspace *workspace)
8370 }
8471
8572 disconnect(workspace, 0, this, 0);
86− workspace->release();
87−}
88−
89−QQmlListProperty<Workspace> WorkspaceManager::floatingWorkspaces()
90−{
91− return QQmlListProperty<Workspace>(this, m_floatingWorkspaces);
92−}
93−
94−void WorkspaceManager::destroyFloatingWorkspaces()
95−{
96− QList<Workspace*> dpCpy(m_floatingWorkspaces);
97− Q_FOREACH(auto workspace, dpCpy) {
98− destroyWorkspace(workspace);
99− }
10073}
10174
10275void WorkspaceManager::moveSurfaceToWorkspace(unity::shell::application::MirSurfaceInterface *surface, Workspace *workspace)
@@ -124,7 +97,7 @@ void WorkspaceManager::setActiveWorkspace(Workspace *workspace)
12497{
12598 if (workspace != m_activeWorkspace) {
12699 m_activeWorkspace = workspace;
127− Q_EMIT activeWorkspaceChanged();
100+ Q_EMIT activeWorkspaceChanged(workspace);
128101 }
129102}
130103
plugins/WindowManager/WorkspaceManager.h+1−5
@@ -21,7 +21,6 @@
2121#include <QQmlListProperty>
2222
2323class Workspace;
24−class ScreensProxy;
2524
2625namespace unity {
2726 namespace shell {
@@ -46,7 +45,6 @@ public:
4645 Workspace* createWorkspace();
4746 void destroyWorkspace(Workspace* workspace);
4847
49− QQmlListProperty<Workspace> floatingWorkspaces();
5048 void destroyFloatingWorkspaces();
5149
5250 Q_INVOKABLE void moveSurfaceToWorkspace(unity::shell::application::MirSurfaceInterface* surface,
@@ -55,8 +53,7 @@ public:
5553 Q_INVOKABLE void moveWorkspaceContentToWorkspace(Workspace* to, Workspace* from);
5654
5755Q_SIGNALS:
58− void activeWorkspaceChanged();
59− void floatingWorkspacesChanged();
56+ void activeWorkspaceChanged(Workspace*);
6057
6158private:
6259 WorkspaceManager();
@@ -64,7 +61,6 @@ private:
6461 void setActiveWorkspace2(Workspace* workspace);
6562
6663 QSet<Workspace*> m_allWorkspaces;
67− QList<Workspace*> m_floatingWorkspaces;
6864 Workspace* m_activeWorkspace;
6965 unity::shell::application::SurfaceManagerInterface* m_surfaceManager;
7066};
plugins/WindowManager/WorkspaceModel.cpp+36−16
@@ -58,6 +58,15 @@ void WorkspaceModel::remove(Workspace *workspace)
5858
5959 endRemoveRows();
6060
61+ m_unassignedWorkspaces.insert(workspace);
62+ connect(workspace, &Workspace::assigned, this, [=]() {
63+ m_unassignedWorkspaces.remove(workspace);
64+ disconnect(workspace, &Workspace::assigned, this, 0);
65+ });
66+ connect(workspace, &QObject::destroyed, this, [=]() {
67+ m_unassignedWorkspaces.remove(workspace);
68+ });
69+
6170 Q_EMIT workspaceRemoved(workspace);
6271 Q_EMIT countChanged();
6372}
@@ -112,10 +121,15 @@ QVariant WorkspaceModel::data(const QModelIndex &index, int role) const
112121 }
113122}
114123
124+void WorkspaceModel::setSyncing(bool syncing)
125+{
126+ m_syncing = syncing;
127+}
128+
115129void WorkspaceModel::sync(WorkspaceModel *proxy)
116130{
131+ qDebug() << "SYNC" << this << proxy;
117132 if (!proxy) return;
118− m_syncing = proxy;
119133 const auto& proxyList = proxy->list();
120134
121135 // check for removals
@@ -125,7 +139,7 @@ void WorkspaceModel::sync(WorkspaceModel *proxy)
125139
126140 bool found = false;
127141 Q_FOREACH(auto p, proxyList) {
128− auto workspaceProxy = qobject_cast<WorkspaceProxy*>(p);
142+ auto workspaceProxy = qobject_cast<ProxyWorkspace*>(p);
129143 if (workspaceProxy->proxyObject() == workspace) {
130144 found = true;
131145 break;
@@ -142,7 +156,7 @@ void WorkspaceModel::sync(WorkspaceModel *proxy)
142156 // existing
143157 QSet<Workspace*> newWorkspaces;
144158 for (int i = 0; i < proxyList.count(); i++) {
145− auto workspaceProxy = qobject_cast<WorkspaceProxy*>(proxyList[i]);
159+ auto workspaceProxy = qobject_cast<ProxyWorkspace*>(proxyList[i]);
146160 auto workspace = workspaceProxy->proxyObject();
147161
148162 int oldIndex = this->indexOf(workspace);
@@ -159,7 +173,7 @@ void WorkspaceModel::sync(WorkspaceModel *proxy)
159173 if (rowCount() == 0) {
160174 Workspace* workspace = WorkspaceManager::instance()->createWorkspace();
161175 workspace->assign(this);
162− (new WorkspaceProxy(workspace))->assign(proxy);
176+ (new ProxyWorkspace(workspace))->assign(proxy);
163177 }
164178
165179 if (removedIndexWhichWasActive != -1) {
@@ -168,32 +182,38 @@ void WorkspaceModel::sync(WorkspaceModel *proxy)
168182
169183 WorkspaceManager::instance()->setActiveWorkspace(newActiveWorkspace);
170184 }
171− m_syncing = nullptr;
185+
186+ proxy->finishSync();
187+ finishSync();
172188}
173189
174−bool WorkspaceModel::isSyncingWith(WorkspaceModel *m)
190+void WorkspaceModel::finishSync()
175191{
176− return m_syncing == m;
192+ QSet<Workspace*> dpCpy(m_unassignedWorkspaces);
193+ Q_FOREACH(auto workspace, dpCpy) {
194+ delete workspace;
195+ }
196+ m_unassignedWorkspaces.clear();
177197}
178198
179−WorkspaceModelProxy::WorkspaceModelProxy(WorkspaceModel * const model)
199+ProxyWorkspaceModel::ProxyWorkspaceModel(WorkspaceModel * const model)
180200 : m_original(model)
181201{
182202 Q_FOREACH(auto workspace, model->list()) {
183− auto proxy = new WorkspaceProxy(workspace);
203+ auto proxy = new ProxyWorkspace(workspace);
184204 QQmlEngine::setObjectOwnership(proxy, QQmlEngine::CppOwnership);
185205 proxy->assign(this);
186206 }
187207 connect(m_original, &WorkspaceModel::workspaceInserted, this, [this](int index, Workspace* inserted) {
188− if (m_original->isSyncingWith(this)) return;
208+ if (m_original->isSyncing()) return;
189209
190− (new WorkspaceProxy(inserted))->assign(this, index);
210+ (new ProxyWorkspace(inserted))->assign(this, index);
191211 });
192212 connect(m_original, &WorkspaceModel::workspaceRemoved, this, [this](Workspace* removed) {
193− if (m_original->isSyncingWith(this)) return;
213+ if (m_original->isSyncing()) return;
194214
195215 for (int i = 0; i < rowCount(); i++) {
196− auto workspaceProxy = qobject_cast<WorkspaceProxy*>(get(i));
216+ auto workspaceProxy = qobject_cast<ProxyWorkspace*>(get(i));
197217 auto w = workspaceProxy->proxyObject();
198218 if (w == removed) {
199219 remove(workspaceProxy);
@@ -202,19 +222,19 @@ WorkspaceModelProxy::WorkspaceModelProxy(WorkspaceModel * const model)
202222 }
203223 });
204224 connect(m_original, &WorkspaceModel::workspaceMoved, this, [this](int from, int to) {
205− if (m_original->isSyncingWith(this)) return;
225+ if (m_original->isSyncing()) return;
206226
207227 move(from, to);
208228 });
209229}
210230
211−WorkspaceModelProxy::~WorkspaceModelProxy()
231+ProxyWorkspaceModel::~ProxyWorkspaceModel()
212232{
213233 qDeleteAll(m_workspaces.toList()); // make a copy so the list doesnt edit itself during delete.
214234 m_workspaces.clear();
215235}
216236
217−void WorkspaceModelProxy::move(int from, int to)
237+void ProxyWorkspaceModel::move(int from, int to)
218238{
219239 WorkspaceModel::move(from, to);
220240}
plugins/WindowManager/WorkspaceModel.h+10−6
@@ -24,7 +24,7 @@
2424Q_DECLARE_LOGGING_CATEGORY(WORKSPACES)
2525
2626class Workspace;
27−class WorkspaceModelProxy;
27+class ProxyWorkspaceModel;
2828
2929class WorkspaceModel : public QAbstractListModel
3030{
@@ -60,8 +60,11 @@ public:
6060
6161 const QVector<Workspace*>& list() const { return m_workspaces; }
6262
63+ void setSyncing(bool);
6364 void sync(WorkspaceModel* proxy);
64− bool isSyncingWith(WorkspaceModel*);
65+ void finishSync();
66+
67+ bool isSyncing() { return m_syncing; }
6568
6669Q_SIGNALS:
6770 void countChanged();
@@ -72,15 +75,16 @@ Q_SIGNALS:
7275
7376protected:
7477 QVector<Workspace*> m_workspaces;
75− WorkspaceModel* m_syncing;
78+ QSet<Workspace*> m_unassignedWorkspaces;
79+ bool m_syncing;
7680};
7781
78−class WorkspaceModelProxy : public WorkspaceModel
82+class ProxyWorkspaceModel : public WorkspaceModel
7983{
8084 Q_OBJECT
8185public:
82− WorkspaceModelProxy(WorkspaceModel*const model);
83− ~WorkspaceModelProxy();
86+ explicit ProxyWorkspaceModel(WorkspaceModel*const model);
87+ ~ProxyWorkspaceModel();
8488
8589 Q_INVOKABLE void move(int from, int to) override;
8690
tests/mocks/WindowManager/MockScreens.cpp+2−1
@@ -97,6 +97,7 @@ public:
9797 }
9898
9999 QScreen* qscreen() const override {
100+ qDebug() << "GET SCREEN" << qGuiApp->topLevelWindows();
100101 if (qGuiApp->topLevelWindows().count() > 0) {
101102 return qGuiApp->topLevelWindows()[0]->screen();
102103 }
@@ -196,7 +197,7 @@ QSharedPointer<MockScreens> MockScreens::instance()
196197
197198void MockScreens::connectWindow(ScreenWindow *w)
198199{
199− Screen* screen = w->screenWrapper();
200+ ConcreteScreen* screen = w->screenWrapper();
200201 if (!screen) return;
201202
202203 auto mockScreen = qobject_cast<MockScreen*>(screen->wrapped());
tests/mocks/WindowManager/MockScreens.h+1−1
@@ -27,7 +27,7 @@ namespace qtmir
2727class Screens;
2828}
2929
30−class Screen;
30+class ConcreteScreen;
3131class ScreenWindow;
3232
3333class MockScreens : public qtmir::Screens
tests/mocks/WindowManager/WindowManagerPlugin.cpp+6−5
@@ -42,7 +42,7 @@ static QObject *workspace_manager(QQmlEngine *engine, QJSEngine *scriptEngine)
4242QObject* screensSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
4343 Q_UNUSED(engine);
4444 Q_UNUSED(scriptEngine);
45− return new Screens(MockScreens::instance());
45+ return ConcreteScreens::self();
4646}
4747QObject* objectsSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
4848 Q_UNUSED(engine);
@@ -54,13 +54,12 @@ void WindowManagerPlugin::registerTypes(const char *uri)
5454{
5555 qmlRegisterSingletonType<WorkspaceManager>(uri, 1, 0, "WorkspaceManager", workspace_manager);
5656 qmlRegisterUncreatableType<WorkspaceModel>(uri, 1, 0, "WorkspaceModel", notInstantiatable);
57− qmlRegisterSingletonType<Screens>(uri, 1, 0, "Screens", screensSingleton);
57+ qmlRegisterSingletonType<ConcreteScreens>(uri, 1, 0, "Screens", screensSingleton);
5858 qmlRegisterUncreatableType<qtmir::ScreenMode>(uri, 1, 0, "ScreenMode", notInstantiatable);
59− qmlRegisterUncreatableType<Workspace>(uri, 1, 0, "Workspace", notInstantiatable);
6059 qmlRegisterSingletonType<WindowManagerObjects>(uri, 1, 0, "WindowManagerObjects", objectsSingleton);
6160
62− qRegisterMetaType<Screen*>("Screen*");
63− qRegisterMetaType<ScreensProxy*>("ScreensProxy*");
61+ qRegisterMetaType<ConcreteScreen*>("ConcreteScreen*");
62+ qRegisterMetaType<ProxyScreens*>("ProxyScreens*");
6463 qRegisterMetaType<Workspace*>("Workspace*");
6564 qRegisterMetaType<TopLevelWindowModel*>("TopLevelWindowModel*");
6665
@@ -79,4 +78,6 @@ void WindowManagerPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
7978
8079 // Make sure we've initialized the wm policy.
8180 WindowManagementPolicy::instance();
81+ // Create Screens
82+ new ConcreteScreens(MockScreens::instance());
8283}
tests/qmltests/Stage/tst_DesktopStage.qml+1−5
@@ -71,11 +71,7 @@ Item {
7171 id: appMenuData
7272 }
7373
74− TopLevelWindowModel {
75− id: topSurfaceList
76− applicationManager: ApplicationManager
77− surfaceManager: SurfaceManager
78− }
74+ readonly property var topSurfaceList: WorkspaceManager.activeWorkspace.windowModel
7975
8076 Loader {
8177 id: stageLoader