on xenial help sign in
merge prereq
1d9e43bMichael Zanetti
CMakeLists.txt+1
@@ -80,6 +80,7 @@ pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
80pkg_check_modules(GD3 REQUIRED gnome-desktop-3.0)
80pkg_check_modules(GD3 REQUIRED gnome-desktop-3.0)
81pkg_check_modules(UAL REQUIRED ubuntu-app-launch-2)
81pkg_check_modules(UAL REQUIRED ubuntu-app-launch-2)
82pkg_check_modules(UBUNTUGESTURES REQUIRED UbuntuGestures)
82pkg_check_modules(UBUNTUGESTURES REQUIRED UbuntuGestures)
83+pkg_check_modules(MIRAL REQUIRED miral)
83
84
84### Check UbuntuGestures private headers. No pkg-config (.pc) file is provided for them
85### Check UbuntuGestures private headers. No pkg-config (.pc) file is provided for them
85find_path(UBUNTUGESTUREPRIV
86find_path(UBUNTUGESTUREPRIV
plugins/WindowManager/TopLevelWindowModel.cpp+10−2
@@ -35,7 +35,7 @@
35#include <qtmir/mirserverapplication.h>
35#include <qtmir/mirserverapplication.h>
36#include <qtmir/windowmodelnotifier.h>
36#include <qtmir/windowmodelnotifier.h>
37
37
38−Q_LOGGING_CATEGORY(TOPLEVELWINDOWMODEL, "toplevelwindowmodel", QtInfoMsg)
38+Q_LOGGING_CATEGORY(TOPLEVELWINDOWMODEL, "toplevelwindowmodel")
39
39
40#define DEBUG_MSG qCDebug(TOPLEVELWINDOWMODEL).nospace().noquote() << __func__
40#define DEBUG_MSG qCDebug(TOPLEVELWINDOWMODEL).nospace().noquote() << __func__
41#define INFO_MSG qCInfo(TOPLEVELWINDOWMODEL).nospace().noquote() << __func__
41#define INFO_MSG qCInfo(TOPLEVELWINDOWMODEL).nospace().noquote() << __func__
@@ -136,6 +136,7 @@ void TopLevelWindowModel::setWorkspace(Workspace *workspace)
136
136
137 if (m_workspace) {
137 if (m_workspace) {
138 m_windowModel.clear();
138 m_windowModel.clear();
139+ m_allSurfaces.clear();
139 if (m_applicationManager) {
140 if (m_applicationManager) {
140 disconnect(m_applicationManager, 0, this, 0);
141 disconnect(m_applicationManager, 0, this, 0);
141 }
142 }
@@ -237,6 +238,7 @@ void TopLevelWindowModel::prependSurfaceHelper(unityapi::MirSurfaceInterface *su
237 Window *window = createWindow(surface);
238 Window *window = createWindow(surface);
238
239
239 m_windowModel.prepend(ModelEntry(window, application));
240 m_windowModel.prepend(ModelEntry(window, application));
241+ m_allSurfaces.insert(surface);
240 if (surface) {
242 if (surface) {
241 connectSurface(surface);
243 connectSurface(surface);
242 }
244 }
@@ -371,6 +373,7 @@ void TopLevelWindowModel::onSurfaceDestroyed(unityapi::MirSurfaceInterface *surf
371 auto window = m_windowModel[i].window;
373 auto window = m_windowModel[i].window;
372 window->setSurface(nullptr);
374 window->setSurface(nullptr);
373 window->setFocused(false);
375 window->setFocused(false);
376+ m_allSurfaces.remove(surface);
374 INFO_MSG << " Removed surface from entry. After: " << toString();
377 INFO_MSG << " Removed surface from entry. After: " << toString();
375 }
378 }
376}
379}
@@ -397,7 +400,7 @@ void TopLevelWindowModel::onSurfacesAddedToWorkspace(const std::shared_ptr<miral
397 if (workspace != m_workspace->workspace()) return;
400 if (workspace != m_workspace->workspace()) return;
398
401
399 Q_FOREACH(auto surface, surfaces) {
402 Q_FOREACH(auto surface, surfaces) {
400− DEBUG_MSG << "(" << surface << ")";
403+ if (m_allSurfaces.contains(surface)) continue;
401
404
402 if (surface->parentSurface()) {
405 if (surface->parentSurface()) {
403 // Wrap it in a Window so that we keep focusedWindow() up to date.
406 // Wrap it in a Window so that we keep focusedWindow() up to date.
@@ -444,6 +447,7 @@ void TopLevelWindowModel::removeAt(int index)
444 window->setFocused(false);
447 window->setFocused(false);
445
448
446 m_windowModel.removeAt(index);
449 m_windowModel.removeAt(index);
450+ m_allSurfaces.remove(window->surface());
447
451
448 if (m_modelState == RemovingState) {
452 if (m_modelState == RemovingState) {
449 endRemoveRows();
453 endRemoveRows();
@@ -765,7 +769,11 @@ void TopLevelWindowModel::activateTopMostWindowWithoutId(int forbiddenId)
765
769
766void TopLevelWindowModel::refreshWindows()
770void TopLevelWindowModel::refreshWindows()
767{
771{
772+ DEBUG_MSG << "()";
773+
768 m_windowModel.clear();
774 m_windowModel.clear();
775+ m_allSurfaces.clear();
776+
769 WindowManagementPolicy::instance()->forEachWindowInWorkspace(m_workspace->workspace(), [this](const miral::Window &window) {
777 WindowManagementPolicy::instance()->forEachWindowInWorkspace(m_workspace->workspace(), [this](const miral::Window &window) {
770 auto surface = m_surfaceManager->surfaceFor(window);
778 auto surface = m_surfaceManager->surfaceFor(window);
771 if (surface) {
779 if (surface) {
plugins/WindowManager/TopLevelWindowModel.h+3−1
@@ -250,10 +250,12 @@ private:
250 bool removeOnceSurfaceDestroyed{false};
250 bool removeOnceSurfaceDestroyed{false};
251 };
251 };
252
252
253− Workspace* m_workspace{nullptr};
254 QVector<ModelEntry> m_windowModel;
253 QVector<ModelEntry> m_windowModel;
255 Window* m_inputMethodWindow{nullptr};
254 Window* m_inputMethodWindow{nullptr};
256 Window* m_focusedWindow{nullptr};
255 Window* m_focusedWindow{nullptr};
256+ Workspace* m_workspace{nullptr};
257+ // track all the surfaces we've been told about.
258+ QSet<unity::shell::application::MirSurfaceInterface*> m_allSurfaces;
257
259
258 int m_nextId{1};
260 int m_nextId{1};
259 // Just something big enough that we don't risk running out of unused id numbers.
261 // Just something big enough that we don't risk running out of unused id numbers.
plugins/WindowManager/Workspace.cpp−1
@@ -94,7 +94,6 @@ void Workspace::assign(WorkspaceModel *model, const QVariant& vIndex)
94 m_model->insert(index, this);
94 m_model->insert(index, this);
95
95
96 connect(m_model, &QObject::destroyed, this, [this]() {
96 connect(m_model, &QObject::destroyed, this, [this]() {
97− m_model->remove(this);
98 m_model = nullptr;
97 m_model = nullptr;
99 Q_EMIT unassigned();
98 Q_EMIT unassigned();
100 });
99 });
plugins/WindowManager/WorkspaceModel.cpp+5
@@ -180,3 +180,8 @@ WorkspaceModelProxy::~WorkspaceModelProxy()
180 qDeleteAll(m_workspaces.toList()); // make a copy so the list doesnt edit itself during delete.
180 qDeleteAll(m_workspaces.toList()); // make a copy so the list doesnt edit itself during delete.
181 m_workspaces.clear();
181 m_workspaces.clear();
182}
182}
183+
184+void WorkspaceModelProxy::move(int from, int to)
185+{
186+ WorkspaceModel::move(from, to);
187+}
plugins/WindowManager/WorkspaceModel.h+4−1
@@ -45,7 +45,7 @@ public:
45 void append(Workspace *workspace);
45 void append(Workspace *workspace);
46 void insert(int index, Workspace *workspace);
46 void insert(int index, Workspace *workspace);
47 void remove(Workspace* workspace);
47 void remove(Workspace* workspace);
48− void move(int from, int to);
48+ virtual void move(int from, int to);
49
49
50 int indexOf(Workspace *workspace) const;
50 int indexOf(Workspace *workspace) const;
51 Workspace* get(int index) const;
51 Workspace* get(int index) const;
@@ -74,10 +74,13 @@ protected:
74
74
75class WorkspaceModelProxy : public WorkspaceModel
75class WorkspaceModelProxy : public WorkspaceModel
76{
76{
77+ Q_OBJECT
77public:
78public:
78 WorkspaceModelProxy(WorkspaceModel*const model);
79 WorkspaceModelProxy(WorkspaceModel*const model);
79 ~WorkspaceModelProxy();
80 ~WorkspaceModelProxy();
80
81
82+ Q_INVOKABLE void move(int from, int to) override;
83+
81private:
84private:
82 const QPointer<WorkspaceModel> m_original;
85 const QPointer<WorkspaceModel> m_original;
83};
86};
qml/OrientedShell.qml−1
@@ -34,7 +34,6 @@ Item {
34
34
35 property alias deviceConfiguration: _deviceConfiguration
35 property alias deviceConfiguration: _deviceConfiguration
36 property alias orientations: d.orientations
36 property alias orientations: d.orientations
37− property alias surfaceManager: shell.surfaceManager
38
37
39 onWidthChanged: calculateUsageMode();
38 onWidthChanged: calculateUsageMode();
40
39
src/libunity8-private/windowmanagementpolicy.cpp+7−6
@@ -41,8 +41,9 @@ void WindowManagementPolicy::advise_new_window(miral::WindowInfo const& window_i
41
41
42 auto const parent = window_info.parent();
42 auto const parent = window_info.parent();
43
43
44− if (!parent && m_activeWorkspace)
44+ auto activeWorkspace = m_activeWorkspace.lock();
45+ if (!parent && activeWorkspace)
45− tools.add_tree_to_workspace(window_info.window(), m_activeWorkspace);
46+ tools.add_tree_to_workspace(window_info.window(), activeWorkspace);
46}
47}
47
48
48std::shared_ptr<miral::Workspace> WindowManagementPolicy::createWorkspace()
49std::shared_ptr<miral::Workspace> WindowManagementPolicy::createWorkspace()
@@ -50,8 +51,8 @@ std::shared_ptr<miral::Workspace> WindowManagementPolicy::createWorkspace()
50 auto workspace = tools.create_workspace();
51 auto workspace = tools.create_workspace();
51 m_workspaces.insert(workspace);
52 m_workspaces.insert(workspace);
52
53
53− if (m_activeWorkspace == m_dummyWorkspace) {
54+ if (m_activeWorkspace.lock() == m_dummyWorkspace) {
54− tools.move_workspace_content_to_workspace(workspace, m_dummyWorkspace);
55+ moveWorkspaceContentToWorkspace(workspace, m_dummyWorkspace);
55 m_activeWorkspace = workspace;
56 m_activeWorkspace = workspace;
56 }
57 }
57 return workspace;
58 return workspace;
@@ -64,7 +65,7 @@ void WindowManagementPolicy::releaseWorkspace(const std::shared_ptr<miral::Works
64
65
65 if (m_workspaces.size() == 0) {
66 if (m_workspaces.size() == 0) {
66 m_activeWorkspace = m_dummyWorkspace;
67 m_activeWorkspace = m_dummyWorkspace;
67− tools.move_workspace_content_to_workspace(m_dummyWorkspace, workspace);
68+ moveWorkspaceContentToWorkspace(m_dummyWorkspace, workspace);
68 }
69 }
69}
70}
70
71
@@ -80,7 +81,7 @@ void WindowManagementPolicy::moveWorkspaceContentToWorkspace(const std::shared_p
80
81
81void WindowManagementPolicy::setActiveWorkspace(const std::shared_ptr<miral::Workspace> &workspace)
82void WindowManagementPolicy::setActiveWorkspace(const std::shared_ptr<miral::Workspace> &workspace)
82{
83{
83− if (workspace == m_activeWorkspace)
84+ if (m_activeWorkspace.lock() == workspace)
84 return;
85 return;
85 m_activeWorkspace = workspace ? workspace : m_dummyWorkspace;
86 m_activeWorkspace = workspace ? workspace : m_dummyWorkspace;
86}
87}
src/libunity8-private/windowmanagementpolicy.h+2−6
@@ -17,15 +17,12 @@
17#ifndef UNITY_WINDOWMANAGEMENTPOLICY_H
17#ifndef UNITY_WINDOWMANAGEMENTPOLICY_H
18#define UNITY_WINDOWMANAGEMENTPOLICY_H
18#define UNITY_WINDOWMANAGEMENTPOLICY_H
19
19
20−#include <QObject>
21#include <qtmir/windowmanagementpolicy.h>
20#include <qtmir/windowmanagementpolicy.h>
22
21
23#include <unordered_set>
22#include <unordered_set>
24
23
25−class Q_DECL_EXPORT WindowManagementPolicy : public QObject,
24+class Q_DECL_EXPORT WindowManagementPolicy : public qtmir::WindowManagementPolicy
26− public qtmir::WindowManagementPolicy
27{
25{
28− Q_OBJECT
29public:
26public:
30 WindowManagementPolicy(const miral::WindowManagerTools &tools, qtmir::WindowManagementPolicyPrivate& dd);
27 WindowManagementPolicy(const miral::WindowManagerTools &tools, qtmir::WindowManagementPolicyPrivate& dd);
31
28
@@ -43,12 +40,11 @@ public:
43 void moveWorkspaceContentToWorkspace(const std::shared_ptr<miral::Workspace> &toWorkspace,
40 void moveWorkspaceContentToWorkspace(const std::shared_ptr<miral::Workspace> &toWorkspace,
44 const std::shared_ptr<miral::Workspace> &fromWorkspace);
41 const std::shared_ptr<miral::Workspace> &fromWorkspace);
45
42
46−public Q_SLOTS:
47 void setActiveWorkspace(const std::shared_ptr<miral::Workspace>& workspace);
43 void setActiveWorkspace(const std::shared_ptr<miral::Workspace>& workspace);
48
44
49private:
45private:
50 static WindowManagementPolicy* m_self;
46 static WindowManagementPolicy* m_self;
51− std::shared_ptr<miral::Workspace> m_activeWorkspace;
47+ std::weak_ptr<miral::Workspace> m_activeWorkspace;
52
48
53 std::unordered_set<std::shared_ptr<miral::Workspace>> m_workspaces;
49 std::unordered_set<std::shared_ptr<miral::Workspace>> m_workspaces;
54 const std::shared_ptr<miral::Workspace> m_dummyWorkspace;
50 const std::shared_ptr<miral::Workspace> m_dummyWorkspace;
tests/mocks/Unity/Application/CMakeLists.txt+25−1
@@ -1,3 +1,11 @@
1+pkg_check_modules(MIRTEST mirtest>=0.26 REQUIRED)
2+
3+include_directories(
4+ SYSTEM
5+ ${MIRTEST_INCLUDE_DIRS}
6+ ${MIRAL_INCLUDE_DIRS}
7+)
8+
1set(FakeUnityApplicationQml_SOURCES
9set(FakeUnityApplicationQml_SOURCES
2 plugin.cpp
10 plugin.cpp
3 ApplicationInfo.cpp
11 ApplicationInfo.cpp
@@ -19,11 +27,27 @@ set(FakeUnityApplicationQml_SOURCES
19 resources/surfaces.qrc
27 resources/surfaces.qrc
20)
28)
21
29
22−add_library(FakeUnityApplicationQml MODULE ${FakeUnityApplicationQml_SOURCES})
30+add_library(FakeUnityApplicationQml MODULE
31+ ${FakeUnityApplicationQml_SOURCES}
32+)
33+
34+#add_dependencies(FakeUnityApplicationQml windowmanagementpolicy)
35+
36+target_link_libraries(FakeUnityApplicationQml
37+ ${MIRTEST_LDFLAGS}
38+ ${MIRAL_LDFLAGS}
39+ mockwindowmanagmentpolicy
40+)
23
41
24add_library(NonMirUnityApplicationQml MODULE ${FakeUnityApplicationQml_SOURCES})
42add_library(NonMirUnityApplicationQml MODULE ${FakeUnityApplicationQml_SOURCES})
25set_target_properties(NonMirUnityApplicationQml PROPERTIES OUTPUT_NAME FakeUnityApplicationQml)
43set_target_properties(NonMirUnityApplicationQml PROPERTIES OUTPUT_NAME FakeUnityApplicationQml)
26
44
45+target_link_libraries(NonMirUnityApplicationQml
46+ ${MIRTEST_LDFLAGS}
47+ ${MIRAL_LDFLAGS}
48+ mockwindowmanagmentpolicy
49+)
50+
27qt5_use_modules(FakeUnityApplicationQml Core Quick DBus)
51qt5_use_modules(FakeUnityApplicationQml Core Quick DBus)
28qt5_use_modules(NonMirUnityApplicationQml Core Quick DBus)
52qt5_use_modules(NonMirUnityApplicationQml Core Quick DBus)
29
53
tests/mocks/Unity/Application/SurfaceManager.cpp+59−6
@@ -18,8 +18,10 @@
18
18
19#include "ApplicationInfo.h"
19#include "ApplicationInfo.h"
20#include "VirtualKeyboard.h"
20#include "VirtualKeyboard.h"
21+#include "../../WindowManager/windowmanagementpolicy.h"
21
22
22#include <paths.h>
23#include <paths.h>
24+#include <mirtest/mir/test/doubles/stub_surface.h>
23
25
24#define SURFACEMANAGER_DEBUG 1
26#define SURFACEMANAGER_DEBUG 1
25
27
@@ -31,6 +33,12 @@
31
33
32namespace unityapi = unity::shell::application;
34namespace unityapi = unity::shell::application;
33
35
36+uint qHash(const WindowWrapper &key, uint)
37+{
38+ std::shared_ptr<mir::scene::Surface> surface = key.window;
39+ return (quintptr)surface.get();
40+}
41+
34SurfaceManager *SurfaceManager::m_instance = nullptr;
42SurfaceManager *SurfaceManager::m_instance = nullptr;
35
43
36SurfaceManager *SurfaceManager::instance()
44SurfaceManager *SurfaceManager::instance()
@@ -38,17 +46,27 @@ SurfaceManager *SurfaceManager::instance()
38 return m_instance;
46 return m_instance;
39}
47}
40
48
41−MirSurfaceInterface *SurfaceManager::surfaceFor(const miral::Window&)
42−{
43− return nullptr;
44−}
45−
46SurfaceManager::SurfaceManager(QObject *)
49SurfaceManager::SurfaceManager(QObject *)
47{
50{
48 DEBUG_MSG("");
51 DEBUG_MSG("");
49
52
50 Q_ASSERT(m_instance == nullptr);
53 Q_ASSERT(m_instance == nullptr);
51 m_instance = this;
54 m_instance = this;
55+
56+ connect(WindowManagementPolicy::instance(), &WindowManagementPolicy::windowAdded,
57+ this, [this](const miral::Window& window) {
58+ Q_EMIT surfaceCreated(surfaceFor(window));
59+ });
60+
61+ connect(WindowManagementPolicy::instance(), &WindowManagementPolicy::windowsAddedToWorkspace,
62+ this, [this](const std::shared_ptr<miral::Workspace> &workspace, const std::vector<miral::Window> &windows) {
63+ Q_EMIT surfacesAddedToWorkspace(workspace, find(windows));
64+ });
65+
66+ connect(WindowManagementPolicy::instance(), &WindowManagementPolicy::windowsAboutToBeRemovedFromWorkspace,
67+ this, [this](const std::shared_ptr<miral::Workspace> &workspace, const std::vector<miral::Window> &windows) {
68+ Q_EMIT surfacesAboutToBeRemovedFromWorkspace(workspace, find(windows));
69+ });
52}
70}
53
71
54SurfaceManager::~SurfaceManager()
72SurfaceManager::~SurfaceManager()
@@ -63,6 +81,29 @@ SurfaceManager::~SurfaceManager()
63 m_instance = nullptr;
81 m_instance = nullptr;
64}
82}
65
83
84+
85+
86+QVector<MirSurfaceInterface*> SurfaceManager::find(const std::vector<miral::Window> &windows) const
87+{
88+ QVector<unityapi::MirSurfaceInterface*> surfaces;
89+ for (size_t i = 0; i < windows.size(); i++) {
90+ auto mirSurface = surfaceFor(windows[i]);
91+ if (mirSurface) {
92+ surfaces.push_back(mirSurface);
93+ }
94+ }
95+ return surfaces;
96+}
97+
98+MirSurfaceInterface *SurfaceManager::surfaceFor(const miral::Window& window) const
99+{
100+ auto iter = m_windowToSurface.find({window});
101+ if (iter != m_windowToSurface.end()) {
102+ return *iter;
103+ }
104+ return nullptr;
105+}
106+
66MirSurface *SurfaceManager::createSurface(const QString& name,
107MirSurface *SurfaceManager::createSurface(const QString& name,
67 Mir::Type type,
108 Mir::Type type,
68 Mir::State state,
109 Mir::State state,
@@ -80,7 +121,12 @@ MirSurface *SurfaceManager::createSurface(const QString& name,
80
121
81void SurfaceManager::registerSurface(MirSurface *surface)
122void SurfaceManager::registerSurface(MirSurface *surface)
82{
123{
124+ auto fakeSurface = std::make_shared<mir::test::doubles::StubSurface>();
125+ WindowWrapper window{miral::Window(nullptr, fakeSurface), fakeSurface};
126+
83 m_surfaces.prepend(surface);
127 m_surfaces.prepend(surface);
128+ m_windowToSurface.insert(window, surface);
129+ m_surfaceToWindow.insert(surface, window);
84
130
85 if (!surface->parentSurface()) {
131 if (!surface->parentSurface()) {
86 surface->setMinimumWidth(m_newSurfaceMinimumWidth);
132 surface->setMinimumWidth(m_newSurfaceMinimumWidth);
@@ -97,6 +143,8 @@ void SurfaceManager::registerSurface(MirSurface *surface)
97
143
98 const QString persistentId = surface->persistentId();
144 const QString persistentId = surface->persistentId();
99 connect(surface, &QObject::destroyed, this, [=]() {
145 connect(surface, &QObject::destroyed, this, [=]() {
146+ WindowWrapper key = m_surfaceToWindow.take(surface);
147+ m_windowToSurface.remove(key);
100 this->onSurfaceDestroyed(surface, persistentId);
148 this->onSurfaceDestroyed(surface, persistentId);
101 });
149 });
102
150
@@ -104,7 +152,12 @@ void SurfaceManager::registerSurface(MirSurface *surface)
104
152
105void SurfaceManager::notifySurfaceCreated(unityapi::MirSurfaceInterface *surface)
153void SurfaceManager::notifySurfaceCreated(unityapi::MirSurfaceInterface *surface)
106{
154{
155+ if (Q_UNLIKELY(!m_surfaceToWindow.contains(surface))) {
107− Q_EMIT surfaceCreated(surface);
156+ Q_EMIT surfaceCreated(surface);
157+ return;
158+ }
159+
160+ WindowManagementPolicy::instance()->addWindow(m_surfaceToWindow[surface].window);
108}
161}
109
162
110void SurfaceManager::setNewSurfaceMinimumWidth(int value)
163void SurfaceManager::setNewSurfaceMinimumWidth(int value)
tests/mocks/Unity/Application/SurfaceManager.h+13−1
@@ -20,12 +20,20 @@
20#include <QObject>
20#include <QObject>
21
21
22#include <unity/shell/application/SurfaceManagerInterface.h>
22#include <unity/shell/application/SurfaceManagerInterface.h>
23+#include <miral/window.h>
23
24
24#include "MirSurface.h"
25#include "MirSurface.h"
25#include "VirtualKeyboard.h"
26#include "VirtualKeyboard.h"
26
27
27class ApplicationInfo;
28class ApplicationInfo;
28
29
30+struct WindowWrapper {
31+ miral::Window window;
32+ std::shared_ptr<mir::scene::Surface> session{nullptr}; // Keeps the window surface alive.
33+ bool operator==(const WindowWrapper& other) const { return window==other.window; }
34+};
35+uint qHash(const WindowWrapper &key, uint seed = 0);
36+
29class SurfaceManager : public unity::shell::application::SurfaceManagerInterface
37class SurfaceManager : public unity::shell::application::SurfaceManagerInterface
30{
38{
31 Q_OBJECT
39 Q_OBJECT
@@ -42,7 +50,7 @@ public:
42
50
43 static SurfaceManager *instance();
51 static SurfaceManager *instance();
44
52
45− unity::shell::application::MirSurfaceInterface *surfaceFor(const miral::Window& window) override;
53+ unity::shell::application::MirSurfaceInterface *surfaceFor(const miral::Window& window) const override;
46
54
47 // SurfaceManagerInterface
55 // SurfaceManagerInterface
48 void raise(unity::shell::application::MirSurfaceInterface *surface) override;
56 void raise(unity::shell::application::MirSurfaceInterface *surface) override;
@@ -97,6 +105,7 @@ private:
97 void doRaise(unity::shell::application::MirSurfaceInterface *surface);
105 void doRaise(unity::shell::application::MirSurfaceInterface *surface);
98 void focusFirstAvailableSurface();
106 void focusFirstAvailableSurface();
99 void registerSurface(MirSurface *surface);
107 void registerSurface(MirSurface *surface);
108+ QVector<unity::shell::application::MirSurfaceInterface*> find(const std::vector<miral::Window> &windows) const;
100
109
101 static SurfaceManager *m_instance;
110 static SurfaceManager *m_instance;
102
111
@@ -112,6 +121,9 @@ private:
112
121
113 QList<MirSurface*> m_surfaces;
122 QList<MirSurface*> m_surfaces;
114
123
124+ QHash<WindowWrapper, unity::shell::application::MirSurfaceInterface*> m_windowToSurface;
125+ QHash<unity::shell::application::MirSurfaceInterface*, WindowWrapper> m_surfaceToWindow;
126+
115 VirtualKeyboard *m_virtualKeyboard{nullptr};
127 VirtualKeyboard *m_virtualKeyboard{nullptr};
116};
128};
117
129
tests/mocks/WindowManager/CMakeLists.txt+9−1
@@ -9,6 +9,14 @@ include_directories(
9 ${CMAKE_SOURCE_DIR}/plugins/WindowManager
9 ${CMAKE_SOURCE_DIR}/plugins/WindowManager
10)
10)
11
11
12+add_library(mockwindowmanagmentpolicy SHARED
13+ windowmanagementpolicy.cpp
14+)
15+target_link_libraries(mockwindowmanagmentpolicy
16+ ${MIRAL_LDFLAGS}
17+)
18+qt5_use_modules(mockwindowmanagmentpolicy Core)
19+
12set(WINDOWMANAGER_SRC
20set(WINDOWMANAGER_SRC
13 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Screen.cpp
21 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Screen.cpp
14 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Screens.cpp
22 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Screens.cpp
@@ -20,7 +28,6 @@ set(WINDOWMANAGER_SRC
20 MockScreens.cpp
28 MockScreens.cpp
21 ScreenWindow.cpp
29 ScreenWindow.cpp
22 WindowManagerPlugin.cpp
30 WindowManagerPlugin.cpp
23− windowmanagementpolicy.h
24 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
31 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
25 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
32 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
26 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
33 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
@@ -32,6 +39,7 @@ add_library(MockWindowManager-qml SHARED ${WINDOWMANAGER_SRC})
32
39
33target_link_libraries(MockWindowManager-qml
40target_link_libraries(MockWindowManager-qml
34 ${QTMIRSERVER_LDFLAGS}
41 ${QTMIRSERVER_LDFLAGS}
42+ mockwindowmanagmentpolicy
35)
43)
36
44
37qt5_use_modules(MockWindowManager-qml Qml Quick Gui)
45qt5_use_modules(MockWindowManager-qml Qml Quick Gui)
tests/mocks/WindowManager/windowmanagementpolicy.cppnew file+98
@@ -0,0 +1,98 @@
1+/*
2+ * Copyright (C) 2017 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "windowmanagementpolicy.h"
18+
19+WindowManagementPolicy *WindowManagementPolicy::instance()
20+{
21+ static WindowManagementPolicy* inst(new WindowManagementPolicy());
22+ return inst;
23+}
24+
25+WindowManagementPolicy::WindowManagementPolicy()
26+ : m_dummyWorkspace(std::shared_ptr<miral::Workspace>())
27+{
28+ m_activeWorkspace = m_dummyWorkspace;
29+}
30+
31+std::shared_ptr<miral::Workspace> WindowManagementPolicy::createWorkspace()
32+{
33+ auto workspace = std::make_shared<miral::Workspace>();
34+ m_workspaces.insert(workspace);
35+
36+ if (m_activeWorkspace.lock() == m_dummyWorkspace) {
37+ moveWorkspaceContentToWorkspace(workspace, m_dummyWorkspace);
38+ m_activeWorkspace = workspace;
39+ }
40+ return workspace;
41+}
42+
43+void WindowManagementPolicy::releaseWorkspace(const std::shared_ptr<miral::Workspace> &workspace)
44+{
45+ auto iter = m_workspaces.find(workspace);
46+ if (iter != m_workspaces.end()) m_workspaces.erase(iter);
47+
48+ if (m_workspaces.size() == 0) {
49+ m_activeWorkspace = m_dummyWorkspace;
50+ moveWorkspaceContentToWorkspace(m_dummyWorkspace, workspace);
51+ }
52+}
53+
54+void WindowManagementPolicy::forEachWindowInWorkspace(const std::shared_ptr<miral::Workspace> &workspace, const std::function<void (const miral::Window &)> &callback)
55+{
56+ QMultiMap<miral::Workspace*, miral::Window>::iterator i = m_windows.find(workspace.get());
57+ while (i != m_windows.end() && i.key() == workspace.get()) {
58+ callback(i.value());
59+ ++i;
60+ }
61+}
62+
63+void WindowManagementPolicy::moveWorkspaceContentToWorkspace(const std::shared_ptr<miral::Workspace> &to, const std::shared_ptr<miral::Workspace> &from)
64+{
65+ std::vector<miral::Window> windows;
66+
67+ QMultiMap<miral::Workspace*, miral::Window>::iterator i = m_windows.find(from.get());
68+ while (i != m_windows.end() && i.key() == from.get()) {
69+ windows.push_back(i.value());
70+ ++i;
71+ }
72+ Q_EMIT windowsAboutToBeRemovedFromWorkspace(from, windows);
73+ m_windows.remove(from.get());
74+
75+ Q_FOREACH(miral::Window window, windows) {
76+ m_windows.insert(to.get(), window);
77+ }
78+ Q_EMIT windowsAddedToWorkspace(to, windows);
79+}
80+
81+void WindowManagementPolicy::addWindow(const miral::Window &window)
82+{
83+ Q_EMIT windowAdded(window);
84+
85+ auto activeWorkspace = m_activeWorkspace.lock();
86+ if (activeWorkspace) {
87+ m_windows.insert(activeWorkspace.get(), window);
88+
89+ Q_EMIT windowsAddedToWorkspace(activeWorkspace, {window});
90+ }
91+}
92+
93+void WindowManagementPolicy::setActiveWorkspace(const std::shared_ptr<miral::Workspace> &workspace)
94+{
95+ if (m_activeWorkspace.lock() == workspace)
96+ return;
97+ m_activeWorkspace = workspace ? workspace : m_dummyWorkspace;
98+}
tests/mocks/WindowManager/windowmanagementpolicy.h+30−18
@@ -18,37 +18,49 @@
18#define MOCKWINDOMANAGEMENTPOLICY_H
18#define MOCKWINDOMANAGEMENTPOLICY_H
19
19
20#include <QObject>
20#include <QObject>
21+#include <QMultiMap>
22+#include <QVector>
23+
24+#include <miral/window.h>
25+#include <memory>
26+#include <unordered_set>
21
27
22namespace miral {
28namespace miral {
23−class Window;
24class Workspace {};
29class Workspace {};
25}
30}
26
31
27// A Fake window management policy for the mock.
32// A Fake window management policy for the mock.
28−class WindowManagementPolicy : public QObject
33+class Q_DECL_EXPORT WindowManagementPolicy : public QObject
29{
34{
30 Q_OBJECT
35 Q_OBJECT
31public:
36public:
32− WindowManagementPolicy() {}
37+ WindowManagementPolicy();
33
38
34− static WindowManagementPolicy *instance() {
39+ static WindowManagementPolicy *instance();
35− static WindowManagementPolicy* inst(new WindowManagementPolicy());
36− return inst;
37− }
38
40
39− std::shared_ptr<miral::Workspace> createWorkspace() { return std::make_shared<miral::Workspace>(); }
41+ std::shared_ptr<miral::Workspace> createWorkspace();
40− void releaseWorkspace(const std::shared_ptr<miral::Workspace>&) {}
42+ void releaseWorkspace(const std::shared_ptr<miral::Workspace>& workspace);
41
43
42− void forEachWindowInWorkspace(
43− std::shared_ptr<miral::Workspace> const&,
44+ void forEachWindowInWorkspace(std::shared_ptr<miral::Workspace> const& workspace,
44− std::function<void(miral::Window const&)> const&) {}
45+ std::function<void(miral::Window const&)> const& callback);
45
46
46− void moveWorkspaceContentToWorkspace(const std::shared_ptr<miral::Workspace>&,
47+ void moveWorkspaceContentToWorkspace(const std::shared_ptr<miral::Workspace>& to,
47− const std::shared_ptr<miral::Workspace>&)
48+ const std::shared_ptr<miral::Workspace>& from);
48− {}
49
49
50−public Q_SLOTS:
50+ void addWindow(const miral::Window& window);
51+
51− void setActiveWorkspace(const std::shared_ptr<miral::Workspace>&) {}
52+ void setActiveWorkspace(const std::shared_ptr<miral::Workspace>& workspace);
52−};
53
53
54+Q_SIGNALS:
55+ void windowAdded(const miral::Window& window);
56+ void windowsAddedToWorkspace(const std::shared_ptr<miral::Workspace> &workspace, const std::vector<miral::Window> &windows);
57+ void windowsAboutToBeRemovedFromWorkspace(const std::shared_ptr<miral::Workspace> &workspace, const std::vector<miral::Window> &windows);
58+
59+private:
60+ std::weak_ptr<miral::Workspace> m_activeWorkspace;
61+ std::shared_ptr<miral::Workspace> m_dummyWorkspace;
62+ std::unordered_set<std::shared_ptr<miral::Workspace>> m_workspaces;
63+
64+ QMultiMap<miral::Workspace*, miral::Window> m_windows;
65+};
54#endif // UNITY_WINDOWMANAGEMENTPOLICY_H
66#endif // UNITY_WINDOWMANAGEMENTPOLICY_H