on xenial help sign in
more workspaces
commit925a0a9fe3a2c35977555c46307bf5b91007907c authorNick Dedekind <nick.dedekind@canonical.com> dateFri 24 Feb 2017, 10:21 (10 years ago) parent886352b
15 files changed+351−31
plugins/WindowManager/CMakeLists.txt+6 plugins/WindowManager/Screens.cpp+1−1 plugins/WindowManager/TopLevelWindowModel.cpp+3 plugins/WindowManager/WindowManagerPlugin.cpp+1 plugins/WindowManager/Workspace.cpp+37−16 plugins/WindowManager/Workspace.h+27−6 plugins/WindowManager/WorkspaceManager.cpp+37 plugins/WindowManager/WorkspaceManager.h+10−2 plugins/WindowManager/WorkspaceModel.h+5−1 src/libunity8-private/CMakeLists.txt+10 src/libunity8-private/windowmanagementpolicy.cpp+37 src/libunity8-private/windowmanagementpolicy.h+29 tests/mocks/WindowManager/CMakeLists.txt+6−5 tests/mocks/WindowManager/Workspace.cpp+80 tests/mocks/WindowManager/Workspace.h+62
plugins/WindowManager/CMakeLists.txt+6
@@ -3,6 +3,11 @@ include_directories(
33 ${QTMIRSERVER_INCLUDE_DIRS}
44)
55
6+include_directories(
7+ ${CMAKE_CURRENT_SOURCE_DIR}
8+ ${libunity8-private_SOURCE_DIR}
9+)
10+
611set(WINDOWMANAGER_SRC
712 TopLevelWindowModel.cpp
813 Window.cpp
@@ -24,6 +29,7 @@ add_library(windowmanager-qml SHARED ${WINDOWMANAGER_SRC})
2429
2530target_link_libraries(windowmanager-qml
2631 ${QTMIRSERVER_LDFLAGS}
32+ unity8-private
2733)
2834
2935qt5_use_modules(windowmanager-qml Qml Quick Gui)
plugins/WindowManager/Screens.cpp+1−1
@@ -36,7 +36,7 @@ Screens::Screens(QObject *parent)
3636
3737 connect(m_wrapped.data(), &qtmir::Screens::screenAdded, this, &Screens::onScreenAdded);
3838 connect(m_wrapped.data(), &qtmir::Screens::screenRemoved, this, &Screens::onScreenRemoved);
39− connect(qGuiApp, &QGuiApplication::focusWindowChanged, this, &Screens::activeScreenChanged);
39+ connect(m_wrapped.data(), &qtmir::Screens::activeScreenChanged, this, &Screens::activeScreenChanged);
4040
4141 Q_FOREACH(qtmir::Screen* screen, m_wrapped->screens()) {
4242 m_screenList.push_back(new Screen(screen));
plugins/WindowManager/TopLevelWindowModel.cpp+3
@@ -39,10 +39,12 @@ namespace unityapi = unity::shell::application;
3939
4040TopLevelWindowModel::TopLevelWindowModel()
4141{
42+ DEBUG_MSG << "\n\nPLOP\n\n";
4243}
4344
4445void TopLevelWindowModel::setApplicationManager(unityapi::ApplicationManagerInterface* value)
4546{
47+ qDebug() << "\n\nPLOP2\n\n";
4648 if (m_applicationManager == value) {
4749 return;
4850 }
@@ -90,6 +92,7 @@ void TopLevelWindowModel::setApplicationManager(unityapi::ApplicationManagerInte
9092
9193void TopLevelWindowModel::setSurfaceManager(unityapi::SurfaceManagerInterface *surfaceManager)
9294{
95+ qDebug() << "\n\nPLOP3\n\n";
9396 if (surfaceManager == m_surfaceManager) {
9497 return;
9598 }
plugins/WindowManager/WindowManagerPlugin.cpp+1
@@ -46,6 +46,7 @@ void WindowManagerPlugin::registerTypes(const char *uri)
4646 qmlRegisterUncreatableType<WorkspaceModel>(uri, 1, 0, "WorkspaceModel", "Not a creatable type");
4747 qmlRegisterSingletonType<Screens>(uri, 1, 0, "Screens", screensSingleton);
4848 qmlRegisterUncreatableType<qtmir::ScreenMode>(uri, 1, 0, "ScreenMode", "ScreenMode is not creatable.");
49+ qmlRegisterUncreatableType<Workspace>(uri, 1, 0, "Workspace", "Workspace is not creatable.");
4950
5051 qRegisterMetaType<Window*>("Window*");
5152 qRegisterMetaType<Workspace*>("Workspace*");
plugins/WindowManager/Workspace.cpp+37−16
@@ -16,12 +16,25 @@
1616
1717#include "Workspace.h"
1818#include "WorkspaceModel.h"
19+#include "WorkspaceManager.h"
20+#include "TopLevelWindowModel.h"
21+
22+#include "windowmanagementpolicy.h"
1923
2024Workspace::Workspace(QObject *parent)
2125 : QObject(parent)
26+ , m_workspace(WindowManagementPolicy::instance()->create_workspace())
27+ , m_windowModel(new TopLevelWindowModel)
2228 , m_model(nullptr)
29+ , m_active(false)
2330{
24−
31+ connect(WorkspaceManager::instance(), &WorkspaceManager::activeWorkspaceChanged, this, [this]() {
32+ bool newActive = WorkspaceManager::instance()->activeWorkspace() == this;
33+ if (newActive != m_active) {
34+ m_active = newActive;
35+ Q_EMIT activeChanged(m_active);
36+ }
37+ });
2538}
2639
2740Workspace::~Workspace()
@@ -29,35 +42,43 @@ Workspace::~Workspace()
2942 unassign();
3043}
3144
32−void Workspace::assign(WorkspaceModel *model)
45+void Workspace::assign(WorkspaceModel *model, const QVariant& vIndex)
3346{
34− bool wasAssinged = false;
47+ if (m_model == model) return;
48+
3549 if (m_model) {
3650 disconnect(model);
3751 m_model->remove(this);
38− wasAssinged = true;
3952 }
4053
41− m_model = model;
42− if (model) {
43− model->append(this);
54+ m_model = model ? model : WorkspaceManager::instance();
4455
45− connect(model, &QObject::destroyed, this, [this]() {
56+ if (m_model) {
57+ int index = m_model->rowCount();
58+ if (vIndex.isValid() && vIndex.canConvert(QVariant::Int)) {
59+ index = vIndex.toInt();
60+ }
61+ m_model->insert(index, this);
62+
63+ connect(m_model, &QObject::destroyed, this, [this]() {
64+ m_model->remove(this);
4665 m_model = nullptr;
47− Q_EMIT unassigned();
4866 });
4967 Q_EMIT assigned();
50− } else if (wasAssinged) {
51− Q_EMIT unassigned();
5268 }
5369}
5470
71+void Workspace::activate()
72+{
73+ WorkspaceManager::instance()->setActiveWorkspace(this);
74+}
75+
5576void Workspace::unassign()
5677{
57− if (m_model) {
58− m_model->remove(this);
59− m_model = nullptr;
78+ assign(nullptr);
79+}
6080
61− Q_EMIT unassigned();
62− }
81+TopLevelWindowModel *Workspace::windowModel() const
82+{
83+ return m_windowModel.data();
6384}
plugins/WindowManager/Workspace.h+27−6
@@ -14,31 +14,52 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−#ifndef WORKSPACE_H
18−#define WORKSPACE_H
17+#ifndef WINDOWMANAGER_WORKSPACE_H
18+#define WINDOWMANAGER_WORKSPACE_H
1919
2020#include <QObject>
21+#include <QVariant>
22+
23+#include <memory>
2124
2225class WorkspaceModel;
26+class TopLevelWindowModel;
27+
28+namespace miral { class Workspace; }
2329
2430class Workspace : public QObject
2531{
2632 Q_OBJECT
33+ Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
34+ Q_PROPERTY(TopLevelWindowModel* windowModel READ windowModel CONSTANT)
2735public:
28− explicit Workspace(QObject *parent = 0);
2936 ~Workspace();
3037
31− Q_INVOKABLE void assign(WorkspaceModel* model);
38+ Q_INVOKABLE void assign(WorkspaceModel* model, const QVariant& index = QVariant());
39+
40+ bool isActive() const { return m_active; }
41+
42+ TopLevelWindowModel *windowModel() const;
3243
33−public Q_SLOT:
44+public Q_SLOTS:
45+ void activate();
3446 void unassign();
3547
3648Q_SIGNALS:
3749 void assigned();
3850 void unassigned();
3951
52+ void activeChanged(bool);
53+
4054private:
55+ explicit Workspace(QObject *parent = 0);
56+
57+ std::shared_ptr<miral::Workspace> m_workspace;
58+ QScopedPointer<TopLevelWindowModel> m_windowModel;
4159 WorkspaceModel* m_model;
60+ bool m_active;
61+
62+ friend class WorkspaceManager;
4263};
4364
44−#endif // WORKSPACE_H
65+#endif // WINDOWMANAGER_WORKSPACE_H
plugins/WindowManager/WorkspaceManager.cpp+37
@@ -16,6 +16,7 @@
1616
1717#include "WorkspaceManager.h"
1818#include "Workspace.h"
19+#include "TopLevelWindowModel.h"
1920
2021// Qt
2122#include <QGuiApplication>
@@ -29,19 +30,55 @@ WorkspaceManager *WorkspaceManager::instance()
2930}
3031
3132WorkspaceManager::WorkspaceManager()
33+ : m_activeWorkspace(nullptr)
3234{
3335}
36+
3437Workspace *WorkspaceManager::createWorkspace()
3538{
3639 auto workspace = new Workspace(this);
3740 QQmlEngine::setObjectOwnership(workspace, QQmlEngine::CppOwnership);
3841 m_allWorkspaces.append(workspace);
3942 workspace->assign(this);
43+
44+ if (m_allWorkspaces.count() == 0 && m_activeWorkspace) {
45+ m_activeWorkspace = nullptr;
46+ Q_EMIT activeWorkspaceChanged();
47+ } else if (m_allWorkspaces.count() == 1) {
48+ m_activeWorkspace = workspace;
49+ Q_EMIT activeWorkspaceChanged();
50+ }
51+
4052 return workspace;
4153}
4254
4355void WorkspaceManager::destroyWorkspace(Workspace *workspace)
4456{
57+ if (!workspace) return;
58+
59+ int index = m_workspaces.indexOf(workspace);
60+ if (index > 0) {
61+ if (workspace == m_activeWorkspace) {
62+ int newIndex = qMax(index, m_allWorkspaces.count()-1);
63+ m_activeWorkspace = newIndex > 0 ? m_allWorkspaces[newIndex] : nullptr;
64+ Q_EMIT activeWorkspaceChanged();
65+ }
66+// if (m_activeWorkspace) {
67+// m_activeWorkspace->windowModel()->transferWindowsFrom(workspace->windowModel());
68+// }
69+ }
4570 workspace->deleteLater();
4671}
4772
73+Workspace *WorkspaceManager::activeWorkspace() const
74+{
75+ return m_activeWorkspace;
76+}
77+
78+void WorkspaceManager::setActiveWorkspace(Workspace *workspace)
79+{
80+ if (workspace != m_activeWorkspace) {
81+ m_activeWorkspace = workspace;
82+ Q_EMIT activeWorkspaceChanged();
83+ }
84+}
plugins/WindowManager/WorkspaceManager.h+10−2
@@ -24,18 +24,26 @@ class Workspace;
2424class WorkspaceManager : public WorkspaceModel
2525{
2626 Q_OBJECT
27+ Q_PROPERTY(Workspace* activeWorkspace READ activeWorkspace WRITE setActiveWorkspace NOTIFY activeWorkspaceChanged)
28+
2729public:
2830 static WorkspaceManager* instance();
2931
30−private:
31− WorkspaceManager();
32+ Workspace* activeWorkspace() const;
33+ void setActiveWorkspace(Workspace* workspace);
3234
3335public Q_SLOTS:
3436 Workspace* createWorkspace();
3537 void destroyWorkspace(Workspace* workspace);
3638
39+Q_SIGNALS:
40+ void activeWorkspaceChanged();
41+
3742private:
43+ WorkspaceManager();
44+
3845 QVector<Workspace*> m_allWorkspaces;
46+ Workspace* m_activeWorkspace;
3947};
4048
4149#endif // WORKSPACEMANAGER_H
plugins/WindowManager/WorkspaceModel.h+5−1
@@ -43,7 +43,7 @@ public:
4343 void append(Workspace* workspace);
4444 void insert(int index, Workspace* workspace);
4545 void remove(Workspace* workspace);
46− void move(int from, int to);
46+ Q_INVOKABLE void move(int from, int to);
4747
4848 // From QAbstractItemModel
4949 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
@@ -53,8 +53,12 @@ public:
5353 return roleNames;
5454 }
5555
56+ Workspace* activeWorkspace() const;
57+ void setActiveWorkspace(Workspace* workspace);
58+
5659Q_SIGNALS:
5760 void countChanged();
61+ void activeWorkspaceChanged();
5862
5963protected:
6064 QVector<Workspace*> m_workspaces;
src/libunity8-private/CMakeLists.txt+10
@@ -4,16 +4,26 @@ set(VERSION ${SOVERSION}.0.0)
44
55project(lib${LIB_NAME})
66
7+include_directories(
8+ SYSTEM
9+ ${QTMIRSERVER_INCLUDE_DIRS}
10+)
11+
712set(lib${LIB_NAME}_SRCS
813 abstractdbusservicemonitor.cpp
914 unitydbusobject.cpp
1015 unitydbusvirtualobject.cpp
16+ windowmanagementpolicy.cpp
1117 )
1218
1319add_library(${LIB_NAME} SHARED
1420 ${lib${LIB_NAME}_SRCS}
1521 )
1622
23+target_link_libraries(${LIB_NAME}
24+ ${QTMIRSERVER_LDFLAGS}
25+ )
26+
1727set_target_properties(${LIB_NAME} PROPERTIES
1828 VERSION ${VERSION}
1929 SOVERSION ${SOVERSION}
src/libunity8-private/windowmanagementpolicy.cppnew file+37
@@ -0,0 +1,37 @@
1+#include "windowmanagementpolicy.h"
2+
3+WindowManagementPolicy* WindowManagementPolicy::m_self = nullptr;
4+
5+WindowManagementPolicy::WindowManagementPolicy(const miral::WindowManagerTools &tools, qtmir::WindowManagementPolicyPrivate &dd)
6+ : qtmir::WindowManagementPolicy(tools, dd)
7+{
8+ m_self = this;
9+}
10+
11+WindowManagementPolicy *WindowManagementPolicy::instance()
12+{
13+ return m_self;
14+}
15+
16+void WindowManagementPolicy::advise_new_window(miral::WindowInfo const& window_info)
17+{
18+ qtmir::WindowManagementPolicy::advise_new_window(window_info);
19+
20+ auto const parent = window_info.parent();
21+
22+ if (!parent)
23+ tools.add_tree_to_workspace(window_info.window(), m_activeWorkspace);
24+}
25+
26+std::shared_ptr<miral::Workspace> WindowManagementPolicy::create_workspace()
27+{
28+ return tools.create_workspace();
29+}
30+
31+void WindowManagementPolicy::setActiveWorkspace(const std::shared_ptr<miral::Workspace> &workspace)
32+{
33+ if (workspace == m_activeWorkspace)
34+ return;
35+ m_activeWorkspace = workspace;
36+}
37+
src/libunity8-private/windowmanagementpolicy.hnew file+29
@@ -0,0 +1,29 @@
1+#ifndef UNITY_WINDOWMANAGEMENTPOLICY_H
2+#define UNITY_WINDOWMANAGEMENTPOLICY_H
3+
4+#include <QObject>
5+#include <qtmir/windowmanagementpolicy.h>
6+
7+class Q_DECL_EXPORT WindowManagementPolicy : public QObject,
8+ public qtmir::WindowManagementPolicy
9+{
10+ Q_OBJECT
11+public:
12+ WindowManagementPolicy(const miral::WindowManagerTools &tools, qtmir::WindowManagementPolicyPrivate& dd);
13+
14+ static WindowManagementPolicy *instance();
15+
16+ void advise_new_window(miral::WindowInfo const& window_info) override;
17+
18+
19+ std::shared_ptr<miral::Workspace> create_workspace();
20+
21+public Q_SLOTS:
22+ void setActiveWorkspace(const std::shared_ptr<miral::Workspace>& workspace);
23+
24+private:
25+ static WindowManagementPolicy* m_self;
26+ std::shared_ptr<miral::Workspace> m_activeWorkspace;
27+};
28+
29+#endif // UNITY_WINDOWMANAGEMENTPOLICY_H
tests/mocks/WindowManager/CMakeLists.txt+6−5
@@ -1,22 +1,23 @@
11include_directories(
2− ${CMAKE_SOURCE_DIR}/plugins/WindowManager
2+ SYSTEM
3+ ${QTMIRSERVER_INCLUDE_DIRS}
34)
45
56include_directories(
6− SYSTEM
7− ${QTMIRSERVER_INCLUDE_DIRS}
7+ ${CMAKE_SOURCE_DIR}/plugins/WindowManager
8+ ${libunity8-private_SOURCE_DIR}
89)
910
1011set(WINDOWMANAGER_SRC
1112 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/TopLevelWindowModel.cpp
1213 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Window.cpp
13− ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Workspace.cpp
1414 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/WorkspaceManager.cpp
1515 ${CMAKE_SOURCE_DIR}/plugins/WindowManager/WorkspaceModel.cpp
16− WindowManagerPlugin.cpp
1716 Screens.cpp
1817 Screen.cpp
1918 ScreenWindow.cpp
19+ Workspace.cpp
20+ WindowManagerPlugin.cpp
2021 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
2122 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
2223 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
tests/mocks/WindowManager/Workspace.cppnew file+80
@@ -0,0 +1,80 @@
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 "Workspace.h"
18+#include "WorkspaceModel.h"
19+#include "WorkspaceManager.h"
20+#include "TopLevelWindowModel.h"
21+
22+#include "windowmanagementpolicy.h"
23+
24+Workspace::Workspace(QObject *parent)
25+ : QObject(parent)
26+ , m_model(nullptr)
27+ , m_windowModel(new TopLevelWindowModel)
28+ , m_active(false)
29+{
30+ connect(WorkspaceManager::instance(), &WorkspaceManager::activeWorkspaceChanged, this, [this]() {
31+ bool newActive = WorkspaceManager::instance()->activeWorkspace() == this;
32+ if (newActive != m_active) {
33+ m_active = newActive;
34+ Q_EMIT activeChanged(m_active);
35+ }
36+ });
37+ connect(this, &Workspace::activeChanged, m_windowModel.data(), &TopLevelWindowModel::setActive);
38+}
39+
40+Workspace::~Workspace()
41+{
42+ unassign();
43+}
44+
45+void Workspace::assign(WorkspaceModel *model)
46+{
47+ if (m_model == model) return;
48+
49+ if (m_model) {
50+ disconnect(model);
51+ m_model->remove(this);
52+ }
53+
54+ m_model = model ? model : WorkspaceManager::instance();
55+
56+ if (m_model) {
57+ m_model->append(this);
58+
59+ connect(m_model, &QObject::destroyed, this, [this]() {
60+ m_model->remove(this);
61+ m_model = nullptr;
62+ });
63+ Q_EMIT assigned();
64+ }
65+}
66+
67+void Workspace::activate()
68+{
69+ WorkspaceManager::instance()->setActiveWorkspace(this);
70+}
71+
72+void Workspace::unassign()
73+{
74+ assign(nullptr);
75+}
76+
77+TopLevelWindowModel *Workspace::windowModel() const
78+{
79+ return m_windowModel.data();
80+}
tests/mocks/WindowManager/Workspace.hnew file+62
@@ -0,0 +1,62 @@
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+#ifndef WORKSPACE_H
18+#define WORKSPACE_H
19+
20+#include <QObject>
21+#include <memory>
22+
23+class WorkspaceModel;
24+class TopLevelWindowModel;
25+
26+namespace miral { class Workspace; }
27+
28+class Workspace : public QObject
29+{
30+ Q_OBJECT
31+ Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
32+ Q_PROPERTY(TopLevelWindowModel* windowModel READ windowModel CONSTANT)
33+public:
34+ ~Workspace();
35+
36+ Q_INVOKABLE void assign(WorkspaceModel* model);
37+
38+ bool isActive() const { return m_active; }
39+
40+ TopLevelWindowModel *windowModel() const;
41+
42+public Q_SLOT:
43+ void activate();
44+ void unassign();
45+
46+Q_SIGNALS:
47+ void assigned();
48+ void unassigned();
49+
50+ void activeChanged();
51+
52+private:
53+ explicit Workspace(QObject *parent = 0);
54+
55+ WorkspaceModel* m_model;
56+ QScopedPointer<TopLevelWindowModel> m_windowModel;
57+ bool m_active;
58+
59+ friend class WorkspaceManager;
60+};
61+
62+#endif // WORKSPACE_H