Merge lp:~unity-team/unity8/workspace-backend into lp:unity8
- workspace-backend
- Merge into trunk
Status: | Needs review |
---|---|
Proposed branch: | lp:~unity-team/unity8/workspace-backend |
Merge into: | lp:unity8 |
Prerequisite: | lp:~nick-dedekind/unity8/multi-monitor |
Diff against target: |
6781 lines (+4202/-755) 94 files modified
CMakeLists.txt (+5/-1) debian/control (+6/-0) plugins/WindowManager/CMakeLists.txt (+28/-7) plugins/WindowManager/Screen.cpp (+316/-0) plugins/WindowManager/Screen.h (+154/-0) plugins/WindowManager/ScreenAttached.cpp (+164/-0) plugins/WindowManager/ScreenAttached.h (+56/-0) plugins/WindowManager/ScreenWindow.cpp (+45/-0) plugins/WindowManager/ScreenWindow.h (+49/-0) plugins/WindowManager/Screens.cpp (+235/-0) plugins/WindowManager/Screens.h (+111/-0) plugins/WindowManager/ScreensConfiguration.cpp (+94/-0) plugins/WindowManager/ScreensConfiguration.h (+32/-0) plugins/WindowManager/TopLevelWindowModel.cpp (+211/-79) plugins/WindowManager/TopLevelWindowModel.h (+20/-24) plugins/WindowManager/WindowManagerObjects.cpp (+47/-0) plugins/WindowManager/WindowManagerObjects.h (+66/-0) plugins/WindowManager/WindowManagerPlugin.cpp (+57/-2) plugins/WindowManager/WindowManagerPlugin.h (+1/-0) plugins/WindowManager/Workspace.cpp (+178/-0) plugins/WindowManager/Workspace.h (+122/-0) plugins/WindowManager/WorkspaceManager.cpp (+106/-0) plugins/WindowManager/WorkspaceManager.h (+69/-0) plugins/WindowManager/WorkspaceModel.cpp (+254/-0) plugins/WindowManager/WorkspaceModel.h (+102/-0) qml/ApplicationMenus/MenuItem.qml (+0/-2) qml/ApplicationMenus/MenuPopup.qml (+0/-1) qml/Components/VirtualTouchPad.qml (+1/-1) qml/ErrorApplication.qml (+1/-1) qml/OrientedShell.qml (+1/-2) qml/Shell.qml (+10/-12) qml/ShellApplication.qml (+12/-4) qml/ShellScreen.qml (+1/-3) src/CMakeLists.txt (+12/-2) src/DisplayConfigurationStorage.cpp (+90/-0) src/DisplayConfigurationStorage.h (+15/-0) src/UnityApplication.cpp (+19/-13) src/UnityApplication.h (+9/-7) src/UnityCommandLineParser.cpp (+8/-0) src/UnityCommandLineParser.h (+3/-0) src/WindowManagementPolicy.cpp (+69/-0) src/WindowManagementPolicy.h (+47/-0) src/libunity8-private/CMakeLists.txt (+1/-0) src/libunity8-private/wmpolicyinterface.cpp (+24/-0) src/libunity8-private/wmpolicyinterface.h (+46/-0) src/main.cpp (+4/-8) tests/CMakeLists.txt (+1/-0) tests/mocks/CMakeLists.txt (+1/-0) tests/mocks/Unity/Application/CMakeLists.txt (+26/-1) tests/mocks/Unity/Application/SurfaceManager.cpp (+117/-10) tests/mocks/Unity/Application/SurfaceManager.h (+23/-3) tests/mocks/Unity/Application/plugin.cpp (+7/-1) tests/mocks/Unity/CMakeLists.txt (+0/-1) tests/mocks/Unity/Screens/CMakeLists.txt (+0/-15) tests/mocks/Unity/Screens/plugin.cpp (+0/-42) tests/mocks/Unity/Screens/plugin.h (+0/-25) tests/mocks/Unity/Screens/qmldir (+0/-2) tests/mocks/Unity/Screens/screens.cpp (+0/-114) tests/mocks/Unity/Screens/screens.h (+0/-162) tests/mocks/Unity/Screens/screenwindow.cpp (+0/-35) tests/mocks/Unity/Screens/screenwindow.h (+0/-42) tests/mocks/WindowManager/CMakeLists.txt (+61/-0) tests/mocks/WindowManager/MockScreenWindow.cpp (+34/-0) tests/mocks/WindowManager/MockScreenWindow.h (+30/-0) tests/mocks/WindowManager/MockScreens.cpp (+227/-0) tests/mocks/WindowManager/MockScreens.h (+54/-0) tests/mocks/WindowManager/MockScreensConfiguration.cpp (+47/-0) tests/mocks/WindowManager/WindowManagementPolicy.cpp (+128/-0) tests/mocks/WindowManager/WindowManagementPolicy.h (+75/-0) tests/mocks/WindowManager/WindowManagerPlugin.cpp (+89/-0) tests/mocks/WindowManager/WindowManagerPlugin.h (+33/-0) tests/mocks/WindowManager/qmldir (+2/-0) tests/plugins/WindowManager/CMakeLists.txt (+5/-1) tests/plugins/WindowManager/UnityApplicationMocks.h (+25/-0) tests/plugins/WindowManager/tst_TopLevelWindowModel.cpp (+20/-8) tests/qmltests/ApplicationMenuDataLoader.qml (+3/-6) tests/qmltests/ApplicationMenus/tst_MenuBar.qml (+0/-2) tests/qmltests/CMakeLists.txt (+1/-0) tests/qmltests/Panel/tst_ActiveCallHint.qml (+0/-2) tests/qmltests/Panel/tst_Panel.qml (+0/-2) tests/qmltests/Stage/tst_ApplicationWindow.qml (+0/-2) tests/qmltests/Stage/tst_DecoratedWindow.qml (+0/-2) tests/qmltests/Stage/tst_DesktopStage.qml (+1/-7) tests/qmltests/Stage/tst_PhoneStage.qml (+5/-7) tests/qmltests/Stage/tst_SurfaceContainer.qml (+0/-2) tests/qmltests/Stage/tst_TabletStage.qml (+43/-43) tests/qmltests/Stage/tst_WindowDecoration.qml (+0/-2) tests/qmltests/Tutorial/tst_Tutorial.qml (+3/-13) tests/qmltests/tst_OrientedShell.qml (+2/-10) tests/qmltests/tst_Shell.qml (+4/-16) tests/qmltests/tst_ShellApplication.qml (+218/-0) tests/qmltests/tst_ShellWithPin.qml (+1/-7) tests/utils/modules/Unity/Test/StageTestCase.qml (+1/-1) tests/utils/modules/Unity/Test/UnityTestCase.qml (+14/-0) |
To merge this branch: | bzr merge lp:~unity-team/unity8/workspace-backend |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity8 CI Bot | continuous-integration | Needs Fixing | |
Unity Team | Pending | ||
Review via email: mp+318090@code.launchpad.net |
This proposal supersedes a proposal from 2017-02-23.
Commit message
WIP - just putting to Needs Review to get Jenkins' opinion
Description of the change
Prereq-archive: ppa:ci-
WIP
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
- 2837. By Nick Dedekind
-
merged with parent
- 2838. By Nick Dedekind
-
fixed surfacelist in test
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2838
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 2839. By Michael Zanetti
-
install libmockwindowma
nagmentpolicy, needed for installed tests
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2839
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 2840. By Michael Zanetti
-
add Windowmanager mock dir to LD_LIBRARY_PATH
- 2841. By Michael Zanetti
-
fix panel tests
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2840
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2841
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 2842. By Nick Dedekind
-
merged parent
- 2843. By Nick Dedekind
-
more test fixes
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2843
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 2844. By Nick Dedekind
-
Mock fixes & test fixes
- 2845. By Nick Dedekind
-
fixed GlobalShortcut test
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2845
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2845
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 2846. By Nick Dedekind
-
merged with trunk
- 2847. By Nick Dedekind
-
Added Mouse and KB controls
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2846
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2847
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 2848. By Nick Dedekind
-
Dont allow proxy to be used as current workspace
- 2849. By Nick Dedekind
-
Fixed wm policy init
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2848
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 2850. By Nick Dedekind
-
fixed sync end
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2850
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 2851. By Nick Dedekind
-
display id
- 2852. By Nick Dedekind
-
ScreenConfig
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2851
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2852
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 2853. By Nick Dedekind
-
display config storage
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2853
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 2854. By Nick Dedekind
-
mock screen active
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2854
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 2855. By Nick Dedekind
-
isSameAs
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2855
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unmerged revisions
- 2855. By Nick Dedekind
-
isSameAs
- 2854. By Nick Dedekind
-
mock screen active
- 2853. By Nick Dedekind
-
display config storage
- 2852. By Nick Dedekind
-
ScreenConfig
- 2851. By Nick Dedekind
-
display id
- 2850. By Nick Dedekind
-
fixed sync end
- 2849. By Nick Dedekind
-
Fixed wm policy init
- 2848. By Nick Dedekind
-
Dont allow proxy to be used as current workspace
- 2847. By Nick Dedekind
-
Added Mouse and KB controls
- 2846. By Nick Dedekind
-
merged with trunk
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2017-03-28 21:45:31 +0000 |
3 | +++ CMakeLists.txt 2017-04-05 11:48:54 +0000 |
4 | @@ -72,6 +72,7 @@ |
5 | find_package(Qt5Test 5.6 REQUIRED) |
6 | |
7 | pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=27) |
8 | +pkg_check_modules(QTMIRSERVER REQUIRED qtmirserver>=0.6.0) |
9 | pkg_check_modules(GEONAMES REQUIRED geonames>=0.2) |
10 | pkg_check_modules(GIO REQUIRED gio-2.0>=2.32) |
11 | pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32) |
12 | @@ -84,6 +85,7 @@ |
13 | libqtdbustest-1 |
14 | libqtdbusmock-1 |
15 | ) |
16 | +pkg_check_modules(MIRAL REQUIRED miral) |
17 | |
18 | ### Check UbuntuGestures private headers. No pkg-config (.pc) file is provided for them |
19 | find_path(UBUNTUGESTUREPRIV |
20 | @@ -118,7 +120,9 @@ |
21 | message(FATAL_ERROR "Could not determine plugin import dir.") |
22 | endif() |
23 | |
24 | -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-permissive -pedantic -Wall -Wextra") |
25 | +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-permissive -pedantic -Wall -Wextra") |
26 | + |
27 | +set (CMAKE_CXX_STANDARD 14) |
28 | |
29 | if ("${CMAKE_BUILD_TYPE}" STREQUAL "release" OR "${CMAKE_BUILD_TYPE}" STREQUAL "relwithdebinfo") |
30 | option(Werror "Treat warnings as errors" ON) |
31 | |
32 | === modified file 'debian/control' |
33 | --- debian/control 2017-04-05 11:48:53 +0000 |
34 | +++ debian/control 2017-04-05 11:48:54 +0000 |
35 | @@ -33,6 +33,7 @@ |
36 | libqtdbustest1-dev, |
37 | libqt5svg5-dev, |
38 | libqt5xmlpatterns5-dev, |
39 | + libqtmirserver-dev (>= 0.6.0), |
40 | libsystemsettings-dev, |
41 | libubuntu-app-launch3-dev, |
42 | libubuntu-download-manager-common-dev, |
43 | @@ -47,6 +48,7 @@ |
44 | libxcb1-dev[!arm64 !armhf], |
45 | libxi-dev[!arm64 !armhf], |
46 | # End of X11 libs |
47 | + mirtest-dev, |
48 | pkg-config, |
49 | python3-all:any, |
50 | python3-setuptools, |
51 | @@ -73,6 +75,9 @@ |
52 | qtdeclarative5-ubuntu-settings-components (>= 0.11), |
53 | ttf-ubuntu-font-family, |
54 | xvfb, |
55 | +# mirtest pkgconfig requires these, but doesn't have a deb dependency. Bug lp:1633537 |
56 | + libboost-filesystem-dev, |
57 | + libboost-system-dev, |
58 | Standards-Version: 3.9.4 |
59 | Homepage: http://launchpad.net/unity |
60 | # If you aren't a member of ~unity-team but need to upload |
61 | @@ -134,6 +139,7 @@ |
62 | qml-module-ubuntu-web, |
63 | qtdeclarative5-qtmir-plugin (>= 0.4.8), |
64 | qtdeclarative5-ubuntu-telephony0.1, |
65 | + qtmir-desktop (>= 0.6.0) | qtmir-android (>= 0.6.0), |
66 | ubuntu-system-settings (>= 0.4), |
67 | unity-launcher-impl-12, |
68 | unity8-common (= ${source:Version}), |
69 | |
70 | === modified file 'plugins/WindowManager/CMakeLists.txt' |
71 | --- plugins/WindowManager/CMakeLists.txt 2017-03-24 14:04:50 +0000 |
72 | +++ plugins/WindowManager/CMakeLists.txt 2017-04-05 11:48:54 +0000 |
73 | @@ -1,25 +1,46 @@ |
74 | +include_directories( |
75 | + SYSTEM |
76 | + ${QTMIRSERVER_INCLUDE_DIRS} |
77 | + ${Qt5Gui_PRIVATE_INCLUDE_DIRS} |
78 | +) |
79 | + |
80 | +include_directories( |
81 | + ${CMAKE_CURRENT_SOURCE_DIR} |
82 | + ${libunity8-private_SOURCE_DIR} |
83 | +) |
84 | + |
85 | set(WINDOWMANAGER_SRC |
86 | AvailableDesktopArea.cpp |
87 | TopLevelWindowModel.cpp |
88 | Window.cpp |
89 | WindowManagerPlugin.cpp |
90 | WindowMargins.cpp |
91 | + Screen.cpp |
92 | + ScreenAttached.cpp |
93 | + Screens.cpp |
94 | + ScreensConfiguration.cpp |
95 | + ScreenWindow.cpp |
96 | + WindowManagerObjects.cpp |
97 | + Workspace.cpp |
98 | + WorkspaceManager.cpp |
99 | + WorkspaceModel.cpp |
100 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h |
101 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h |
102 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h |
103 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h |
104 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceListInterface.h |
105 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/SurfaceManagerInterface.h |
106 | - ) |
107 | +) |
108 | |
109 | add_definitions(-DWINDOWMANAGERQML_LIBRARY) |
110 | |
111 | -include_directories( |
112 | - SYSTEM |
113 | - ${Qt5Gui_PRIVATE_INCLUDE_DIRS} |
114 | -) |
115 | - |
116 | add_library(windowmanager-qml SHARED ${WINDOWMANAGER_SRC}) |
117 | |
118 | +target_link_libraries(windowmanager-qml |
119 | + ${QTMIRSERVER_LDFLAGS} |
120 | + unity8-private |
121 | +) |
122 | + |
123 | qt5_use_modules(windowmanager-qml Qml Quick Gui) |
124 | |
125 | -add_unity8_plugin(WindowManager 0.1 WindowManager TARGETS windowmanager-qml) |
126 | +add_unity8_plugin(WindowManager 1.0 WindowManager TARGETS windowmanager-qml) |
127 | |
128 | === added file 'plugins/WindowManager/Screen.cpp' |
129 | --- plugins/WindowManager/Screen.cpp 1970-01-01 00:00:00 +0000 |
130 | +++ plugins/WindowManager/Screen.cpp 2017-04-05 11:48:54 +0000 |
131 | @@ -0,0 +1,316 @@ |
132 | +/* |
133 | + * Copyright (C) 2017 Canonical, Ltd. |
134 | + * |
135 | + * This program is free software: you can redistribute it and/or modify it under |
136 | + * the terms of the GNU Lesser General Public License version 3, as published by |
137 | + * the Free Software Foundation. |
138 | + * |
139 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
140 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
141 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
142 | + * Lesser General Public License for more details. |
143 | + * |
144 | + * You should have received a copy of the GNU Lesser General Public License |
145 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
146 | + */ |
147 | + |
148 | +#include "Screen.h" |
149 | +#include "Screens.h" |
150 | +#include "WorkspaceManager.h" |
151 | +#include "Workspace.h" |
152 | + |
153 | +Screen::Screen(QObject *parent) |
154 | + : QObject(parent) |
155 | +{ |
156 | +} |
157 | + |
158 | +void Screen::connectToScreen(qtmir::Screen *screen) |
159 | +{ |
160 | + m_wrapped = screen; |
161 | + connect(screen, &qtmir::Screen::usedChanged, this, &Screen::usedChanged); |
162 | + connect(screen, &qtmir::Screen::nameChanged, this, &Screen::nameChanged); |
163 | + connect(screen, &qtmir::Screen::outputTypeChanged, this, &Screen::outputTypeChanged); |
164 | + connect(screen, &qtmir::Screen::outputTypeChanged, this, &Screen::outputTypeNameChanged); |
165 | + connect(screen, &qtmir::Screen::scaleChanged, this, &Screen::scaleChanged); |
166 | + connect(screen, &qtmir::Screen::formFactorChanged, this, &Screen::formFactorChanged); |
167 | + connect(screen, &qtmir::Screen::physicalSizeChanged, this, &Screen::physicalSizeChanged); |
168 | + connect(screen, &qtmir::Screen::positionChanged, this, &Screen::positionChanged); |
169 | + connect(screen, &qtmir::Screen::activeChanged, this, &Screen::activeChanged); |
170 | + connect(screen, &qtmir::Screen::currentModeIndexChanged, this, &Screen::currentModeIndexChanged); |
171 | + connect(screen, &qtmir::Screen::availableModesChanged, this, &Screen::availableModesChanged); |
172 | +} |
173 | + |
174 | +void Screen::connectToScreen(Screen *screen) |
175 | +{ |
176 | + connectToScreen(screen->wrapped()); |
177 | + connect(screen, &Screen::currentWorkspaceChanged, this, &Screen::currentWorkspaceChanged); |
178 | +} |
179 | + |
180 | +void Screen::setCurrentWorkspace2(Workspace *workspace) |
181 | +{ |
182 | + // Make sure we use the correct concrete class. Don't want to use a Proxy. |
183 | + workspace->setCurrentOn(this); |
184 | +} |
185 | + |
186 | +bool Screen::used() const |
187 | +{ |
188 | + if (!m_wrapped) return false; |
189 | + return m_wrapped->used(); |
190 | +} |
191 | + |
192 | +QString Screen::name() const |
193 | +{ |
194 | + if (!m_wrapped) return QString(); |
195 | + return m_wrapped->name(); |
196 | +} |
197 | + |
198 | +float Screen::scale() const |
199 | +{ |
200 | + if (!m_wrapped) return 1.0; |
201 | + return m_wrapped->scale(); |
202 | +} |
203 | + |
204 | +QSizeF Screen::physicalSize() const |
205 | +{ |
206 | + if (!m_wrapped) return QSizeF(); |
207 | + return m_wrapped->physicalSize(); |
208 | +} |
209 | + |
210 | +qtmir::FormFactor Screen::formFactor() const |
211 | +{ |
212 | + if (!m_wrapped) return qtmir::FormFactorUnknown; |
213 | + return m_wrapped->formFactor(); |
214 | +} |
215 | + |
216 | +qtmir::OutputTypes Screen::outputType() const |
217 | +{ |
218 | + if (!m_wrapped) return qtmir::Unknown; |
219 | + return m_wrapped->outputType(); |
220 | +} |
221 | + |
222 | +MirPowerMode Screen::powerMode() const |
223 | +{ |
224 | + if (!m_wrapped) return mir_power_mode_on; |
225 | + return m_wrapped->powerMode(); |
226 | +} |
227 | + |
228 | +Qt::ScreenOrientation Screen::orientation() const |
229 | +{ |
230 | + if (!m_wrapped) return Qt::PrimaryOrientation; |
231 | + return m_wrapped->orientation(); |
232 | +} |
233 | + |
234 | +QPoint Screen::position() const |
235 | +{ |
236 | + if (!m_wrapped) return QPoint(); |
237 | + return m_wrapped->position(); |
238 | +} |
239 | + |
240 | +QQmlListProperty<qtmir::ScreenMode> Screen::availableModes() |
241 | +{ |
242 | + if (!m_wrapped) return QQmlListProperty<qtmir::ScreenMode>(); |
243 | + return m_wrapped->availableModes(); |
244 | +} |
245 | + |
246 | +uint Screen::currentModeIndex() const |
247 | +{ |
248 | + if (!m_wrapped) return -1; |
249 | + return m_wrapped->currentModeIndex(); |
250 | +} |
251 | + |
252 | +bool Screen::isActive() const |
253 | +{ |
254 | + if (!m_wrapped) return false; |
255 | + return m_wrapped->isActive(); |
256 | +} |
257 | + |
258 | +void Screen::activate() |
259 | +{ |
260 | + setActive(true); |
261 | +} |
262 | + |
263 | +void Screen::setActive(bool active) |
264 | +{ |
265 | + if (!m_wrapped) return; |
266 | + m_wrapped->setActive(active); |
267 | +} |
268 | + |
269 | +QScreen *Screen::qscreen() const |
270 | +{ |
271 | + if (!m_wrapped) return nullptr; |
272 | + return m_wrapped->qscreen(); |
273 | +} |
274 | + |
275 | +ScreenConfig *Screen::beginConfiguration() const |
276 | +{ |
277 | + if (!m_wrapped) return nullptr; |
278 | + return new ScreenConfig(m_wrapped->beginConfiguration()); |
279 | +} |
280 | + |
281 | +bool Screen::applyConfiguration(ScreenConfig *configuration) |
282 | +{ |
283 | + if (!m_wrapped) return false; |
284 | + return m_wrapped->applyConfiguration(configuration->m_config); |
285 | +} |
286 | + |
287 | +QString Screen::outputTypeName() const |
288 | +{ |
289 | + switch (m_wrapped->outputType()) { |
290 | + case qtmir::Unknown: |
291 | + return tr("Unknown"); |
292 | + case qtmir::VGA: |
293 | + return tr("VGA"); |
294 | + case qtmir::DVII: |
295 | + case qtmir::DVID: |
296 | + case qtmir::DVIA: |
297 | + return tr("DVI"); |
298 | + case qtmir::Composite: |
299 | + return tr("Composite"); |
300 | + case qtmir::SVideo: |
301 | + return tr("S-Video"); |
302 | + case qtmir::LVDS: |
303 | + case qtmir::NinePinDIN: |
304 | + case qtmir::EDP: |
305 | + return tr("Internal"); |
306 | + case qtmir::Component: |
307 | + return tr("Component"); |
308 | + case qtmir::DisplayPort: |
309 | + return tr("DisplayPort"); |
310 | + case qtmir::HDMIA: |
311 | + case qtmir::HDMIB: |
312 | + return tr("HDMI"); |
313 | + case qtmir::TV: |
314 | + return tr("TV"); |
315 | + } |
316 | + return QString(); |
317 | +} |
318 | + |
319 | +bool Screen::isSameAs(Screen *screen) const |
320 | +{ |
321 | + if (!screen) return false; |
322 | + if (screen == this) return true; |
323 | + return wrapped() == screen->wrapped(); |
324 | +} |
325 | + |
326 | +void Screen::sync(Screen *proxy) |
327 | +{ |
328 | + if (!proxy) return; |
329 | + workspaces()->sync(proxy->workspaces()); |
330 | +} |
331 | + |
332 | +ConcreteScreen::ConcreteScreen(qtmir::Screen* wrapped) |
333 | + : m_workspaces(new WorkspaceModel) |
334 | +{ |
335 | + connectToScreen(wrapped); |
336 | + |
337 | + // Connect the active workspace to activate the screen. |
338 | + connect(m_workspaces.data(), &WorkspaceModel::workspaceInserted, this, [this](int, Workspace* workspace) { |
339 | + connect(workspace, &Workspace::activeChanged, this, [this, workspace](bool active) { |
340 | + if (active) { |
341 | + setCurrentWorkspace(workspace); |
342 | + activate(); |
343 | + } |
344 | + }); |
345 | + if (workspace->isActive()) { |
346 | + activate(); |
347 | + setCurrentWorkspace(workspace); |
348 | + } |
349 | + if (!m_currentWorspace) { |
350 | + setCurrentWorkspace(workspace); |
351 | + } |
352 | + }); |
353 | + connect(m_workspaces.data(), &WorkspaceModel::workspaceRemoved, this, [this](Workspace* workspace) { |
354 | + disconnect(workspace, &Workspace::activeChanged, this, 0); |
355 | + if (workspace == m_currentWorspace) { |
356 | + resetCurrentWorkspace(); |
357 | + } |
358 | + }); |
359 | + connect(this, &ConcreteScreen::activeChanged, this, [this](bool active) { |
360 | + if (active && m_currentWorspace) { |
361 | + m_currentWorspace->activate(); |
362 | + } |
363 | + }); |
364 | +} |
365 | + |
366 | +void ConcreteScreen::resetCurrentWorkspace() |
367 | +{ |
368 | + auto newCurrent = m_workspaces->rowCount() > 0 ? m_workspaces->get(0) : nullptr; |
369 | + if (m_currentWorspace != newCurrent) { |
370 | + m_currentWorspace = newCurrent; |
371 | + Q_EMIT currentWorkspaceChanged(newCurrent); |
372 | + } |
373 | +} |
374 | + |
375 | + |
376 | +WorkspaceModel *ConcreteScreen::workspaces() const |
377 | +{ |
378 | + return m_workspaces.data(); |
379 | +} |
380 | + |
381 | +Workspace *ConcreteScreen::currentWorkspace() const |
382 | +{ |
383 | + return m_currentWorspace.data(); |
384 | +} |
385 | + |
386 | +void ConcreteScreen::setCurrentWorkspace(Workspace *workspace) |
387 | +{ |
388 | + if (m_currentWorspace != workspace) { |
389 | + m_currentWorspace = workspace; |
390 | + Q_EMIT currentWorkspaceChanged(workspace); |
391 | + } |
392 | +} |
393 | + |
394 | +ProxyScreen::ProxyScreen(Screen *const screen, ProxyScreens* screens) |
395 | + : m_workspaces(new ProxyWorkspaceModel(screen->workspaces(), this)) |
396 | + , m_original(screen) |
397 | + , m_screens(screens) |
398 | +{ |
399 | + connectToScreen(screen); |
400 | + |
401 | + auto updateCurrentWorkspaceFn = [this](Workspace* realWorkspace) { |
402 | + Q_FOREACH(Workspace* workspace, m_workspaces->list()) { |
403 | + auto p = qobject_cast<ProxyWorkspace*>(workspace); |
404 | + if (p && p->proxyObject() == realWorkspace) { |
405 | + if (m_currentWorspace != p) { |
406 | + m_currentWorspace = p; |
407 | + Q_EMIT currentWorkspaceChanged(p); |
408 | + } |
409 | + } |
410 | + } |
411 | + }; |
412 | + connect(screen, &Screen::currentWorkspaceChanged, this, updateCurrentWorkspaceFn); |
413 | + updateCurrentWorkspaceFn(screen->currentWorkspace()); |
414 | +} |
415 | + |
416 | +WorkspaceModel *ProxyScreen::workspaces() const |
417 | +{ |
418 | + return m_workspaces.data(); |
419 | +} |
420 | + |
421 | +Workspace *ProxyScreen::currentWorkspace() const |
422 | +{ |
423 | + return m_currentWorspace.data(); |
424 | +} |
425 | + |
426 | +void ProxyScreen::setCurrentWorkspace(Workspace *workspace) |
427 | +{ |
428 | + auto p = qobject_cast<ProxyWorkspace*>(workspace); |
429 | + if (p) { |
430 | + m_original->setCurrentWorkspace(p->proxyObject()); |
431 | + } |
432 | +} |
433 | + |
434 | +bool ProxyScreen::isSyncing() const |
435 | +{ |
436 | + return m_screens->isSyncing(); |
437 | +} |
438 | + |
439 | +ScreenConfig::ScreenConfig(qtmir::ScreenConfiguration *config) |
440 | + : m_config(config) |
441 | +{ |
442 | +} |
443 | + |
444 | +ScreenConfig::~ScreenConfig() |
445 | +{ |
446 | + delete m_config; |
447 | +} |
448 | |
449 | === added file 'plugins/WindowManager/Screen.h' |
450 | --- plugins/WindowManager/Screen.h 1970-01-01 00:00:00 +0000 |
451 | +++ plugins/WindowManager/Screen.h 2017-04-05 11:48:54 +0000 |
452 | @@ -0,0 +1,154 @@ |
453 | +#ifndef SCREEN_H |
454 | +#define SCREEN_H |
455 | + |
456 | +#include <qtmir/screen.h> |
457 | +#include <QScopedPointer> |
458 | +#include <QPointer> |
459 | + |
460 | +#include "WorkspaceModel.h" |
461 | + |
462 | +class ProxyScreen; |
463 | +class ProxyScreens; |
464 | +class ScreenConfig; |
465 | + |
466 | +class Screen: public QObject |
467 | +{ |
468 | + Q_OBJECT |
469 | + |
470 | + Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged) |
471 | + |
472 | + Q_PROPERTY(bool used READ used NOTIFY usedChanged) |
473 | + Q_PROPERTY(QString name READ name NOTIFY nameChanged) |
474 | + Q_PROPERTY(qtmir::OutputTypes outputType READ outputType NOTIFY outputTypeChanged) |
475 | + Q_PROPERTY(float scale READ scale NOTIFY scaleChanged) |
476 | + Q_PROPERTY(qtmir::FormFactor formFactor READ formFactor NOTIFY formFactorChanged) |
477 | + Q_PROPERTY(MirPowerMode powerMode READ powerMode NOTIFY powerModeChanged) |
478 | + Q_PROPERTY(Qt::ScreenOrientation orientation READ orientation NOTIFY orientationChanged) |
479 | + Q_PROPERTY(QPoint position READ position NOTIFY positionChanged) |
480 | + Q_PROPERTY(uint currentModeIndex READ currentModeIndex NOTIFY currentModeIndexChanged) |
481 | + Q_PROPERTY(QQmlListProperty<qtmir::ScreenMode> availableModes READ availableModes NOTIFY availableModesChanged) |
482 | + Q_PROPERTY(QSizeF physicalSize READ physicalSize NOTIFY physicalSizeChanged) |
483 | + Q_PROPERTY(QString outputTypeName READ outputTypeName NOTIFY outputTypeChanged) |
484 | + Q_PROPERTY(WorkspaceModel* workspaces READ workspaces CONSTANT) |
485 | + Q_PROPERTY(Workspace* currentWorkspace READ currentWorkspace WRITE setCurrentWorkspace2 NOTIFY currentWorkspaceChanged) |
486 | +public: |
487 | + bool used() const; |
488 | + QString name() const; |
489 | + float scale() const; |
490 | + QSizeF physicalSize() const; |
491 | + qtmir::FormFactor formFactor() const; |
492 | + qtmir::OutputTypes outputType() const; |
493 | + MirPowerMode powerMode() const; |
494 | + Qt::ScreenOrientation orientation() const; |
495 | + QPoint position() const; |
496 | + QQmlListProperty<qtmir::ScreenMode> availableModes(); |
497 | + uint currentModeIndex() const; |
498 | + bool isActive() const; |
499 | + void setActive(bool active); |
500 | + QScreen* qscreen() const; |
501 | + QString outputTypeName() const; |
502 | + |
503 | + Q_INVOKABLE bool isSameAs(Screen*) const; |
504 | + |
505 | + Q_INVOKABLE ScreenConfig *beginConfiguration() const; |
506 | + Q_INVOKABLE bool applyConfiguration(ScreenConfig *configuration); |
507 | + |
508 | + virtual WorkspaceModel* workspaces() const = 0; |
509 | + virtual Workspace *currentWorkspace() const = 0; |
510 | + virtual void setCurrentWorkspace(Workspace* workspace) = 0; |
511 | + |
512 | + void sync(Screen* proxy); |
513 | + |
514 | + qtmir::Screen* wrapped() const { return m_wrapped; } |
515 | + |
516 | +public Q_SLOTS: |
517 | + void activate(); |
518 | + |
519 | +Q_SIGNALS: |
520 | + void usedChanged(); |
521 | + void nameChanged(); |
522 | + void outputTypeChanged(); |
523 | + void outputTypeNameChanged(); |
524 | + void scaleChanged(); |
525 | + void formFactorChanged(); |
526 | + void powerModeChanged(); |
527 | + void orientationChanged(); |
528 | + void positionChanged(); |
529 | + void currentModeIndexChanged(); |
530 | + void physicalSizeChanged(); |
531 | + void availableModesChanged(); |
532 | + void activeChanged(bool active); |
533 | + void currentWorkspaceChanged(Workspace*); |
534 | + |
535 | +protected: |
536 | + Screen(QObject* parent = 0); |
537 | + |
538 | + void connectToScreen(qtmir::Screen* screen); |
539 | + void connectToScreen(Screen* screen); |
540 | + |
541 | +private: |
542 | + void setCurrentWorkspace2(Workspace* workspace); |
543 | + |
544 | +protected: |
545 | + QPointer<qtmir::Screen> m_wrapped; |
546 | +}; |
547 | + |
548 | + |
549 | +class ConcreteScreen : public Screen |
550 | +{ |
551 | + Q_OBJECT |
552 | +public: |
553 | + explicit ConcreteScreen(qtmir::Screen*const wrapped); |
554 | + |
555 | + // From qtmir::Screen |
556 | + WorkspaceModel* workspaces() const override; |
557 | + Workspace *currentWorkspace() const override; |
558 | + void setCurrentWorkspace(Workspace* workspace) override; |
559 | + |
560 | +protected: |
561 | + void resetCurrentWorkspace(); |
562 | + |
563 | + const QScopedPointer<WorkspaceModel> m_workspaces; |
564 | + QPointer<Workspace> m_currentWorspace; |
565 | +}; |
566 | + |
567 | +class ProxyScreen : public Screen |
568 | +{ |
569 | + Q_OBJECT |
570 | +public: |
571 | + explicit ProxyScreen(Screen*const screen, ProxyScreens* screens); |
572 | + |
573 | + // From qtmir::Screen |
574 | + WorkspaceModel* workspaces() const override; |
575 | + Workspace *currentWorkspace() const override; |
576 | + void setCurrentWorkspace(Workspace* workspace) override; |
577 | + |
578 | + Screen* proxyObject() const { return m_original.data(); } |
579 | + |
580 | + bool isSyncing() const; |
581 | + |
582 | +private: |
583 | + const QScopedPointer<WorkspaceModel> m_workspaces; |
584 | + const QPointer<Screen> m_original; |
585 | + const ProxyScreens* m_screens; |
586 | + QPointer<Workspace> m_currentWorspace; |
587 | +}; |
588 | + |
589 | +class ScreenConfig: public QObject |
590 | +{ |
591 | + Q_OBJECT |
592 | + Q_PRIVATE_PROPERTY(m_config, bool valid MEMBER used CONSTANT) |
593 | + Q_PRIVATE_PROPERTY(m_config, bool used MEMBER used) |
594 | + Q_PRIVATE_PROPERTY(m_config, float scale MEMBER scale) |
595 | + Q_PRIVATE_PROPERTY(m_config, qtmir::FormFactor formFactor MEMBER formFactor) |
596 | + Q_PRIVATE_PROPERTY(m_config, uint currentModeIndex MEMBER currentModeIndex) |
597 | + Q_PRIVATE_PROPERTY(m_config, QPoint position MEMBER topLeft) |
598 | + |
599 | +public: |
600 | + ScreenConfig(qtmir::ScreenConfiguration*); |
601 | + ~ScreenConfig(); |
602 | + |
603 | + qtmir::ScreenConfiguration* m_config; |
604 | +}; |
605 | + |
606 | +#endif // SCREEN_H |
607 | |
608 | === added file 'plugins/WindowManager/ScreenAttached.cpp' |
609 | --- plugins/WindowManager/ScreenAttached.cpp 1970-01-01 00:00:00 +0000 |
610 | +++ plugins/WindowManager/ScreenAttached.cpp 2017-04-05 11:48:54 +0000 |
611 | @@ -0,0 +1,164 @@ |
612 | +/* |
613 | + * Copyright (C) 2017 Canonical, Ltd. |
614 | + * |
615 | + * This program is free software: you can redistribute it and/or modify it under |
616 | + * the terms of the GNU Lesser General Public License version 3, as published by |
617 | + * the Free Software Foundation. |
618 | + * |
619 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
620 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
621 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
622 | + * Lesser General Public License for more details. |
623 | + * |
624 | + * You should have received a copy of the GNU Lesser General Public License |
625 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
626 | + */ |
627 | + |
628 | +#include "ScreenAttached.h" |
629 | +#include "ScreenWindow.h" |
630 | +#include "Screens.h" |
631 | + |
632 | +#include <QQuickItem> |
633 | +#include <QScreen> |
634 | + |
635 | +namespace |
636 | +{ |
637 | +QQuickItem* itemForOwner(QObject* obj) { |
638 | + QObject* parent = obj; |
639 | + while(parent) { |
640 | + auto item = qobject_cast<QQuickItem*>(parent); |
641 | + if (item) return item; |
642 | + parent = parent->parent(); |
643 | + } |
644 | + return nullptr; |
645 | +} |
646 | +} // namesapce |
647 | + |
648 | +ScreenAttached::ScreenAttached(QObject *owner) |
649 | + : Screen(owner) |
650 | + , m_window(nullptr) |
651 | +{ |
652 | + if (auto item = itemForOwner(owner)) { |
653 | + connect(item, &QQuickItem::windowChanged, this, &ScreenAttached::windowChanged); |
654 | + windowChanged(item->window()); |
655 | + } else if (auto window = qobject_cast<QQuickWindow*>(owner)) { |
656 | + windowChanged(window); |
657 | + } |
658 | +} |
659 | + |
660 | +WorkspaceModel *ScreenAttached::workspaces() const |
661 | +{ |
662 | + if (!m_screen) return nullptr; |
663 | + return m_screen->workspaces(); |
664 | +} |
665 | + |
666 | +Workspace *ScreenAttached::currentWorkspace() const |
667 | +{ |
668 | + if (!m_screen) return nullptr; |
669 | + return m_screen->currentWorkspace(); |
670 | +} |
671 | + |
672 | +void ScreenAttached::setCurrentWorkspace(Workspace *workspace) |
673 | +{ |
674 | + if (!m_screen) return; |
675 | + return m_screen->setCurrentWorkspace(workspace); |
676 | +} |
677 | + |
678 | +void ScreenAttached::windowChanged(QQuickWindow *window) |
679 | +{ |
680 | + if (m_window) { |
681 | + disconnect(m_window, &QWindow::screenChanged, this, &ScreenAttached::screenChanged); |
682 | + } |
683 | + |
684 | + m_window = window; |
685 | + auto screenWindow = qobject_cast<ScreenWindow*>(window); |
686 | + |
687 | + if (screenWindow) { |
688 | + screenChanged2(screenWindow->screenWrapper()); |
689 | + connect(screenWindow, &ScreenWindow::screenWrapperChanged, this, &ScreenAttached::screenChanged2); |
690 | + } else { |
691 | + screenChanged(window ? window->screen() : NULL); |
692 | + if (window) { |
693 | + connect(window, &QWindow::screenChanged, this, &ScreenAttached::screenChanged); |
694 | + } |
695 | + } |
696 | +} |
697 | + |
698 | +void ScreenAttached::screenChanged(QScreen *qscreen) |
699 | +{ |
700 | + // Find a screen that matches. |
701 | + // Should only get here in mocks if we don't have a ScreenWindow |
702 | + Screen* screen{nullptr}; |
703 | + Q_FOREACH(auto s, ConcreteScreens::self()->list()) { |
704 | + if (s->qscreen() == qscreen) { |
705 | + screen = s; |
706 | + } |
707 | + } |
708 | + screenChanged2(screen); |
709 | +} |
710 | + |
711 | +void ScreenAttached::screenChanged2(Screen* screen) |
712 | +{ |
713 | + if (screen == m_screen) return; |
714 | + |
715 | + Screen* oldScreen = m_screen; |
716 | + m_screen = screen; |
717 | + |
718 | + if (oldScreen) |
719 | + oldScreen->disconnect(this); |
720 | + |
721 | + if (!screen) |
722 | + return; //Don't bother emitting signals, because the new values are garbage anyways |
723 | + |
724 | + if (!oldScreen || screen->isActive() != oldScreen->isActive()) |
725 | + Q_EMIT activeChanged(screen->isActive()); |
726 | + if (!oldScreen || screen->used() != oldScreen->used()) |
727 | + Q_EMIT usedChanged(); |
728 | + if (!oldScreen || screen->name() != oldScreen->name()) |
729 | + Q_EMIT nameChanged(); |
730 | + if (!oldScreen || screen->outputType() != oldScreen->outputType()) |
731 | + Q_EMIT outputTypeChanged(); |
732 | + if (!oldScreen || screen->scale() != oldScreen->scale()) |
733 | + Q_EMIT scaleChanged(); |
734 | + if (!oldScreen || screen->formFactor() != oldScreen->formFactor()) |
735 | + Q_EMIT formFactorChanged(); |
736 | + if (!oldScreen || screen->powerMode() != oldScreen->powerMode()) |
737 | + Q_EMIT powerModeChanged(); |
738 | + if (!oldScreen || screen->orientation() != oldScreen->orientation()) |
739 | + Q_EMIT orientationChanged(); |
740 | + if (!oldScreen || screen->position() != oldScreen->position()) |
741 | + Q_EMIT positionChanged(); |
742 | + if (!oldScreen || screen->currentModeIndex() != oldScreen->currentModeIndex()) |
743 | + Q_EMIT currentModeIndexChanged(); |
744 | + if (!oldScreen || screen->physicalSize() != oldScreen->physicalSize()) |
745 | + Q_EMIT physicalSizeChanged(); |
746 | + if (!oldScreen || screen->currentWorkspace() != oldScreen->currentWorkspace()) |
747 | + Q_EMIT currentWorkspaceChanged(currentWorkspace()); |
748 | + |
749 | + if (oldScreen) { |
750 | + QVector<qtmir::ScreenMode*> oldModes; |
751 | + auto oldModesQmlList = oldScreen->availableModes(); |
752 | + for (int i = 0; i < oldModesQmlList.count(&oldModesQmlList); i++) { |
753 | + oldModes << oldModesQmlList.at(&oldModesQmlList, i); |
754 | + } |
755 | + |
756 | + QVector<qtmir::ScreenMode*> newModes; |
757 | + auto newModesQmlList = screen->availableModes(); |
758 | + for (int i = 0; i < newModesQmlList.count(&newModesQmlList); i++) { |
759 | + newModes << newModesQmlList.at(&newModesQmlList, i); |
760 | + } |
761 | + |
762 | + if (newModes != newModes) { |
763 | + Q_EMIT availableModesChanged(); |
764 | + } |
765 | + } else { |
766 | + Q_EMIT availableModesChanged(); |
767 | + } |
768 | + |
769 | + connectToScreen(screen); |
770 | +} |
771 | + |
772 | +ScreenAttached *WMScreen::qmlAttachedProperties(QObject *owner) |
773 | +{ |
774 | + return new ScreenAttached(owner); |
775 | +} |
776 | |
777 | === added file 'plugins/WindowManager/ScreenAttached.h' |
778 | --- plugins/WindowManager/ScreenAttached.h 1970-01-01 00:00:00 +0000 |
779 | +++ plugins/WindowManager/ScreenAttached.h 2017-04-05 11:48:54 +0000 |
780 | @@ -0,0 +1,56 @@ |
781 | +/* |
782 | + * Copyright (C) 2017 Canonical, Ltd. |
783 | + * |
784 | + * This program is free software: you can redistribute it and/or modify it under |
785 | + * the terms of the GNU Lesser General Public License version 3, as published by |
786 | + * the Free Software Foundation. |
787 | + * |
788 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
789 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
790 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
791 | + * Lesser General Public License for more details. |
792 | + * |
793 | + * You should have received a copy of the GNU Lesser General Public License |
794 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
795 | + */ |
796 | + |
797 | +#ifndef SCREENATTACHED_H |
798 | +#define SCREENATTACHED_H |
799 | + |
800 | +#include "Screen.h" |
801 | + |
802 | +#include <QQmlEngine> |
803 | +#include <QtQml> |
804 | + |
805 | +class QQuickWindow; |
806 | + |
807 | +class ScreenAttached : public Screen |
808 | +{ |
809 | + Q_OBJECT |
810 | +public: |
811 | + ScreenAttached(QObject* owner); |
812 | + |
813 | + WorkspaceModel* workspaces() const override; |
814 | + Workspace *currentWorkspace() const override; |
815 | + void setCurrentWorkspace(Workspace* workspace) override; |
816 | + |
817 | +private Q_SLOTS: |
818 | + void windowChanged(QQuickWindow*); |
819 | + void screenChanged(QScreen*); |
820 | + void screenChanged2(Screen* screen); |
821 | + |
822 | +private: |
823 | + QPointer<Screen> m_screen; |
824 | + QQuickWindow* m_window; |
825 | +}; |
826 | + |
827 | +class WMScreen : public QObject |
828 | +{ |
829 | + Q_OBJECT |
830 | +public: |
831 | + static ScreenAttached *qmlAttachedProperties(QObject *owner); |
832 | +}; |
833 | + |
834 | +QML_DECLARE_TYPEINFO(WMScreen, QML_HAS_ATTACHED_PROPERTIES) |
835 | + |
836 | +#endif // SCREENATTACHED_H |
837 | |
838 | === added file 'plugins/WindowManager/ScreenWindow.cpp' |
839 | --- plugins/WindowManager/ScreenWindow.cpp 1970-01-01 00:00:00 +0000 |
840 | +++ plugins/WindowManager/ScreenWindow.cpp 2017-04-05 11:48:54 +0000 |
841 | @@ -0,0 +1,45 @@ |
842 | +/* |
843 | + * Copyright (C) 2016-2017 Canonical, Ltd. |
844 | + * |
845 | + * This program is free software: you can redistribute it and/or modify it under |
846 | + * the terms of the GNU Lesser General Public License version 3, as published by |
847 | + * the Free Software Foundation. |
848 | + * |
849 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
850 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
851 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
852 | + * Lesser General Public License for more details. |
853 | + * |
854 | + * You should have received a copy of the GNU Lesser General Public License |
855 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
856 | + */ |
857 | + |
858 | +#include "ScreenWindow.h" |
859 | +#include "Screen.h" |
860 | + |
861 | +// Qt |
862 | +#include <QGuiApplication> |
863 | +#include <QDebug> |
864 | + |
865 | +ScreenWindow::ScreenWindow(QQuickWindow *parent) |
866 | + : QQuickWindow(parent) |
867 | +{ |
868 | +} |
869 | + |
870 | +ScreenWindow::~ScreenWindow() |
871 | +{ |
872 | +} |
873 | + |
874 | +ConcreteScreen *ScreenWindow::screenWrapper() const |
875 | +{ |
876 | + return m_screen.data(); |
877 | +} |
878 | + |
879 | +void ScreenWindow::setScreenWrapper(ConcreteScreen *screen) |
880 | +{ |
881 | + if (m_screen != screen) { |
882 | + m_screen = screen; |
883 | + Q_EMIT screenWrapperChanged(screen); |
884 | + } |
885 | + QQuickWindow::setScreen(screen->qscreen()); |
886 | +} |
887 | |
888 | === added file 'plugins/WindowManager/ScreenWindow.h' |
889 | --- plugins/WindowManager/ScreenWindow.h 1970-01-01 00:00:00 +0000 |
890 | +++ plugins/WindowManager/ScreenWindow.h 2017-04-05 11:48:54 +0000 |
891 | @@ -0,0 +1,49 @@ |
892 | +/* |
893 | + * Copyright (C) 2016-2017 Canonical, Ltd. |
894 | + * |
895 | + * This program is free software: you can redistribute it and/or modify it under |
896 | + * the terms of the GNU Lesser General Public License version 3, as published by |
897 | + * the Free Software Foundation. |
898 | + * |
899 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
900 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
901 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
902 | + * Lesser General Public License for more details. |
903 | + * |
904 | + * You should have received a copy of the GNU Lesser General Public License |
905 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
906 | + */ |
907 | + |
908 | +#ifndef UNITY_SCREENWINDOW_H |
909 | +#define UNITY_SCREENWINDOW_H |
910 | + |
911 | +#include <QQuickWindow> |
912 | +#include <QPointer> |
913 | + |
914 | +#include "Screen.h" |
915 | + |
916 | +class ScreenAdapter; |
917 | + |
918 | +/* |
919 | + * ScreenWindow - wrapper of QQuickWindow to enable QML to specify destination screen. |
920 | +**/ |
921 | +class ScreenWindow : public QQuickWindow |
922 | +{ |
923 | + Q_OBJECT |
924 | + Q_PROPERTY(ConcreteScreen *screen READ screenWrapper WRITE setScreenWrapper NOTIFY screenWrapperChanged) |
925 | + Q_PROPERTY(int winId READ winId CONSTANT) |
926 | +public: |
927 | + explicit ScreenWindow(QQuickWindow *parent = 0); |
928 | + ~ScreenWindow(); |
929 | + |
930 | + ConcreteScreen *screenWrapper() const; |
931 | + void setScreenWrapper(ConcreteScreen *screen); |
932 | + |
933 | +Q_SIGNALS: |
934 | + void screenWrapperChanged(ConcreteScreen* screen); |
935 | + |
936 | +private: |
937 | + QPointer<ConcreteScreen> m_screen; |
938 | +}; |
939 | + |
940 | +#endif // UNITY_SCREENWINDOW_H |
941 | |
942 | === added file 'plugins/WindowManager/Screens.cpp' |
943 | --- plugins/WindowManager/Screens.cpp 1970-01-01 00:00:00 +0000 |
944 | +++ plugins/WindowManager/Screens.cpp 2017-04-05 11:48:54 +0000 |
945 | @@ -0,0 +1,235 @@ |
946 | +/* |
947 | + * Copyright (C) 2016-2017 Canonical, Ltd. |
948 | + * |
949 | + * This program is free software: you can redistribute it and/or modify it under |
950 | + * the terms of the GNU Lesser General Public License version 3, as published by |
951 | + * the Free Software Foundation. |
952 | + * |
953 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
954 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
955 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
956 | + * Lesser General Public License for more details. |
957 | + * |
958 | + * You should have received a copy of the GNU Lesser General Public License |
959 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
960 | + */ |
961 | + |
962 | +#include "Screens.h" |
963 | +#include "ScreensConfiguration.h" |
964 | +#include "Screen.h" |
965 | +#include "WorkspaceManager.h" |
966 | + |
967 | +// qtmirserver |
968 | +#include <qtmir/screens.h> |
969 | +#include <QGuiApplication> |
970 | +#include <QQmlEngine> |
971 | + |
972 | +// Qt |
973 | +#include <QScreen> |
974 | +#include <QWindow> |
975 | + |
976 | +ConcreteScreens* ConcreteScreens::m_self{nullptr}; |
977 | + |
978 | +Screens::Screens(const QSharedPointer<qtmir::Screens>& model) |
979 | + : m_wrapped(model) |
980 | +{ |
981 | +} |
982 | + |
983 | +Screens::~Screens() |
984 | +{ |
985 | + qDeleteAll(m_screens); |
986 | + m_screens.clear(); |
987 | +} |
988 | + |
989 | +QHash<int, QByteArray> Screens::roleNames() const |
990 | +{ |
991 | + QHash<int, QByteArray> roles; |
992 | + roles[ScreenRole] = "screen"; |
993 | + return roles; |
994 | +} |
995 | + |
996 | +QVariant Screens::data(const QModelIndex &index, int role) const |
997 | +{ |
998 | + if (!index.isValid() || index.row() >= m_screens.size()) { |
999 | + return QVariant(); |
1000 | + } |
1001 | + |
1002 | + switch(role) { |
1003 | + case ScreenRole: |
1004 | + return QVariant::fromValue(m_screens.at(index.row())); |
1005 | + } // switch |
1006 | + |
1007 | + return QVariant(); |
1008 | +} |
1009 | + |
1010 | +int Screens::rowCount(const QModelIndex &) const |
1011 | +{ |
1012 | + return count(); |
1013 | +} |
1014 | + |
1015 | +int Screens::count() const |
1016 | +{ |
1017 | + return m_screens.size(); |
1018 | +} |
1019 | + |
1020 | +QVariant Screens::activeScreen() const |
1021 | +{ |
1022 | + for (int i = 0; i < m_screens.count(); i++) { |
1023 | + if (m_screens[i]->isActive()) return i; |
1024 | + } |
1025 | + return QVariant(); |
1026 | +} |
1027 | + |
1028 | +void Screens::activateScreen(const QVariant& vindex) |
1029 | +{ |
1030 | + bool ok = false; |
1031 | + int index = vindex.toInt(&ok); |
1032 | + if (!ok || index < 0 || m_screens.count() <= index) return; |
1033 | + |
1034 | + auto screen = m_screens.at(index); |
1035 | + screen->setActive(true); |
1036 | +} |
1037 | + |
1038 | + |
1039 | +ConcreteScreens::ConcreteScreens(const QSharedPointer<qtmir::Screens> &model, ScreensConfiguration* config) |
1040 | + : Screens(model) |
1041 | + , m_config(config) |
1042 | +{ |
1043 | + m_self = this; |
1044 | + connect(m_wrapped.data(), &qtmir::Screens::screenAdded, this, &ConcreteScreens::onScreenAdded); |
1045 | + connect(m_wrapped.data(), &qtmir::Screens::screenRemoved, this, &ConcreteScreens::onScreenRemoved); |
1046 | + connect(m_wrapped.data(), &qtmir::Screens::activeScreenChanged, this, &ConcreteScreens::activeScreenChanged); |
1047 | + |
1048 | + Q_FOREACH(qtmir::Screen* screen, m_wrapped->screens()) { |
1049 | + auto screenWrapper(new ConcreteScreen(screen)); |
1050 | + m_config->load(screenWrapper); |
1051 | + |
1052 | + QQmlEngine::setObjectOwnership(screenWrapper, QQmlEngine::CppOwnership); |
1053 | + m_screens.push_back(screenWrapper); |
1054 | + } |
1055 | +} |
1056 | + |
1057 | +ConcreteScreens::~ConcreteScreens() |
1058 | +{ |
1059 | + Q_FOREACH(Screen* screen, m_screens) { |
1060 | + m_config->save(screen); |
1061 | + } |
1062 | + delete m_config; |
1063 | +} |
1064 | + |
1065 | +ConcreteScreens *ConcreteScreens::self() |
1066 | +{ |
1067 | + return ConcreteScreens::m_self; |
1068 | +} |
1069 | + |
1070 | +ProxyScreens *ConcreteScreens::createProxy() |
1071 | +{ |
1072 | + return new ProxyScreens(this); |
1073 | +} |
1074 | + |
1075 | +void ConcreteScreens::sync(ProxyScreens *proxy) |
1076 | +{ |
1077 | + if (!proxy) return; |
1078 | + proxy->setSyncing(true); |
1079 | + |
1080 | + const auto& proxyList = proxy->list(); |
1081 | + for (int i = 0; i < m_screens.count() && i < proxyList.count(); ++i) { |
1082 | + m_screens[i]->sync(proxyList[i]); |
1083 | + } |
1084 | + |
1085 | + proxy->setSyncing(false); |
1086 | +} |
1087 | + |
1088 | +void ConcreteScreens::onScreenAdded(qtmir::Screen *added) |
1089 | +{ |
1090 | + Q_FOREACH(auto screenWrapper, m_screens) { |
1091 | + if (screenWrapper->wrapped() == added) return; |
1092 | + } |
1093 | + |
1094 | + beginInsertRows(QModelIndex(), count(), count()); |
1095 | + auto screenWrapper(new ConcreteScreen(added)); |
1096 | + m_config->load(screenWrapper); |
1097 | + |
1098 | + QQmlEngine::setObjectOwnership(screenWrapper, QQmlEngine::CppOwnership); |
1099 | + m_screens.push_back(screenWrapper); |
1100 | + endInsertRows(); |
1101 | + Q_EMIT screenAdded(screenWrapper); |
1102 | + Q_EMIT countChanged(); |
1103 | +} |
1104 | + |
1105 | +void ConcreteScreens::onScreenRemoved(qtmir::Screen *removed) |
1106 | +{ |
1107 | + int index = 0; |
1108 | + QMutableVectorIterator<Screen*> iter(m_screens); |
1109 | + while(iter.hasNext()) { |
1110 | + auto screenWrapper = iter.next(); |
1111 | + if (screenWrapper->wrapped() == removed) { |
1112 | + m_config->save(screenWrapper); |
1113 | + |
1114 | + beginRemoveRows(QModelIndex(), index, index); |
1115 | + iter.remove(); |
1116 | + endRemoveRows(); |
1117 | + |
1118 | + Q_EMIT screenRemoved(screenWrapper); |
1119 | + Q_EMIT countChanged(); |
1120 | + |
1121 | + screenWrapper->deleteLater(); |
1122 | + break; |
1123 | + } |
1124 | + index++; |
1125 | + } |
1126 | +} |
1127 | + |
1128 | + |
1129 | +ProxyScreens::ProxyScreens(Screens * const screens) |
1130 | + : Screens(screens->m_wrapped) |
1131 | + , m_original(screens) |
1132 | + , m_syncing(false) |
1133 | +{ |
1134 | + connect(screens, &Screens::screenAdded, this, [this](Screen *added) { |
1135 | + Q_FOREACH(auto screen, m_screens) { |
1136 | + auto proxy = static_cast<ProxyScreen*>(screen); |
1137 | + if (proxy->proxyObject() == added) return; |
1138 | + } |
1139 | + |
1140 | + beginInsertRows(QModelIndex(), count(), count()); |
1141 | + auto screenWrapper(new ProxyScreen(added, this)); |
1142 | + QQmlEngine::setObjectOwnership(screenWrapper, QQmlEngine::CppOwnership); |
1143 | + m_screens.push_back(screenWrapper); |
1144 | + endInsertRows(); |
1145 | + Q_EMIT screenAdded(screenWrapper); |
1146 | + Q_EMIT countChanged(); |
1147 | + }); |
1148 | + |
1149 | + connect(screens, &Screens::screenRemoved, this, [this](Screen *removed) { |
1150 | + int index = 0; |
1151 | + QMutableVectorIterator<Screen*> iter(m_screens); |
1152 | + while(iter.hasNext()) { |
1153 | + auto proxy = static_cast<ProxyScreen*>(iter.next()); |
1154 | + if (proxy->proxyObject() == removed) { |
1155 | + |
1156 | + beginRemoveRows(QModelIndex(), index, index); |
1157 | + iter.remove(); |
1158 | + endRemoveRows(); |
1159 | + |
1160 | + Q_EMIT screenRemoved(proxy); |
1161 | + Q_EMIT countChanged(); |
1162 | + |
1163 | + delete proxy; |
1164 | + break; |
1165 | + } |
1166 | + index++; |
1167 | + } |
1168 | + }); |
1169 | + |
1170 | + Q_FOREACH(Screen* screen, screens->list()) { |
1171 | + auto screenWrapper(new ProxyScreen(screen, this)); |
1172 | + QQmlEngine::setObjectOwnership(screenWrapper, QQmlEngine::CppOwnership); |
1173 | + m_screens.push_back(screenWrapper); |
1174 | + } |
1175 | +} |
1176 | + |
1177 | +void ProxyScreens::setSyncing(bool syncing) |
1178 | +{ |
1179 | + m_syncing = syncing; |
1180 | +} |
1181 | |
1182 | === added file 'plugins/WindowManager/Screens.h' |
1183 | --- plugins/WindowManager/Screens.h 1970-01-01 00:00:00 +0000 |
1184 | +++ plugins/WindowManager/Screens.h 2017-04-05 11:48:54 +0000 |
1185 | @@ -0,0 +1,111 @@ |
1186 | +/* |
1187 | + * Copyright (C) 2016 Canonical, Ltd. |
1188 | + * |
1189 | + * This program is free software: you can redistribute it and/or modify it under |
1190 | + * the terms of the GNU Lesser General Public License version 3, as published by |
1191 | + * the Free Software Foundation. |
1192 | + * |
1193 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
1194 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
1195 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1196 | + * Lesser General Public License for more details. |
1197 | + * |
1198 | + * You should have received a copy of the GNU Lesser General Public License |
1199 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1200 | + */ |
1201 | + |
1202 | +#ifndef UNITY_SCREENS_H |
1203 | +#define UNITY_SCREENS_H |
1204 | + |
1205 | +#include <QAbstractListModel> |
1206 | +#include <QSharedPointer> |
1207 | +#include <QPointer> |
1208 | + |
1209 | +namespace qtmir |
1210 | +{ |
1211 | +class Screen; |
1212 | +class Screens; |
1213 | +} |
1214 | + |
1215 | +class Screen; |
1216 | +class ProxyScreens; |
1217 | +class ScreensConfiguration; |
1218 | + |
1219 | +class Screens : public QAbstractListModel |
1220 | +{ |
1221 | + Q_OBJECT |
1222 | + Q_PROPERTY(int count READ count NOTIFY countChanged) |
1223 | + Q_PROPERTY(QVariant activeScreen READ activeScreen WRITE activateScreen NOTIFY activeScreenChanged) |
1224 | + |
1225 | +public: |
1226 | + enum ItemRoles { |
1227 | + ScreenRole = Qt::UserRole + 1 |
1228 | + }; |
1229 | + |
1230 | + virtual ~Screens(); |
1231 | + |
1232 | + /* QAbstractItemModel */ |
1233 | + QHash<int, QByteArray> roleNames() const override; |
1234 | + QVariant data(const QModelIndex &index, int role = ScreenRole) const override; |
1235 | + int rowCount(const QModelIndex &parent = QModelIndex()) const override; |
1236 | + |
1237 | + int count() const; |
1238 | + QVariant activeScreen() const; |
1239 | + |
1240 | + const QVector<Screen*>& list() const { return m_screens; } |
1241 | + |
1242 | +public Q_SLOTS: |
1243 | + void activateScreen(const QVariant& index); |
1244 | + |
1245 | +Q_SIGNALS: |
1246 | + void countChanged(); |
1247 | + void activeScreenChanged(); |
1248 | + |
1249 | + void screenAdded(Screen* screen); |
1250 | + void screenRemoved(Screen* screen); |
1251 | + |
1252 | +protected: |
1253 | + Screens(const QSharedPointer<qtmir::Screens>& model); |
1254 | + |
1255 | + QVector<Screen*> m_screens; |
1256 | + const QSharedPointer<qtmir::Screens> m_wrapped; |
1257 | + |
1258 | + friend class ProxyScreens; |
1259 | +}; |
1260 | + |
1261 | +class ConcreteScreens : public Screens |
1262 | +{ |
1263 | + Q_OBJECT |
1264 | +public: |
1265 | + explicit ConcreteScreens(const QSharedPointer<qtmir::Screens>& model, ScreensConfiguration* config); |
1266 | + ~ConcreteScreens(); |
1267 | + |
1268 | + Q_INVOKABLE ProxyScreens *createProxy(); |
1269 | + Q_INVOKABLE void sync(ProxyScreens *proxy); |
1270 | + |
1271 | + static ConcreteScreens *self(); |
1272 | + |
1273 | +protected Q_SLOTS: |
1274 | + void onScreenAdded(qtmir::Screen *screen); |
1275 | + void onScreenRemoved(qtmir::Screen *screen); |
1276 | + |
1277 | +private: |
1278 | + ScreensConfiguration* m_config; |
1279 | + |
1280 | + static ConcreteScreens* m_self; |
1281 | +}; |
1282 | + |
1283 | +class ProxyScreens : public Screens |
1284 | +{ |
1285 | +public: |
1286 | + explicit ProxyScreens(Screens*const screens); |
1287 | + |
1288 | + void setSyncing(bool syncing); |
1289 | + bool isSyncing() const { return m_syncing; } |
1290 | + |
1291 | +private: |
1292 | + const QPointer<Screens> m_original; |
1293 | + bool m_syncing; |
1294 | +}; |
1295 | + |
1296 | +#endif // SCREENS_H |
1297 | |
1298 | === added file 'plugins/WindowManager/ScreensConfiguration.cpp' |
1299 | --- plugins/WindowManager/ScreensConfiguration.cpp 1970-01-01 00:00:00 +0000 |
1300 | +++ plugins/WindowManager/ScreensConfiguration.cpp 2017-04-05 11:48:54 +0000 |
1301 | @@ -0,0 +1,94 @@ |
1302 | +/* |
1303 | + * Copyright (C) 2017 Canonical, Ltd. |
1304 | + * |
1305 | + * This program is free software; you can redistribute it and/or modify |
1306 | + * it under the terms of the GNU General Public License as published by |
1307 | + * the Free Software Foundation; version 3. |
1308 | + * |
1309 | + * This program is distributed in the hope that it will be useful, |
1310 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1311 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1312 | + * GNU General Public License for more details. |
1313 | + * |
1314 | + * You should have received a copy of the GNU General Public License |
1315 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1316 | + */ |
1317 | + |
1318 | +#include "ScreensConfiguration.h" |
1319 | +#include "Screen.h" |
1320 | +#include "Workspace.h" |
1321 | +#include "WorkspaceManager.h" |
1322 | + |
1323 | +#include <QJsonObject> |
1324 | +#include <QJsonDocument> |
1325 | +#include <QJsonArray> |
1326 | +#include <QFile> |
1327 | +#include <QStandardPaths> |
1328 | + |
1329 | +namespace |
1330 | +{ |
1331 | +QJsonArray jsonScreens; |
1332 | +} |
1333 | + |
1334 | +ScreensConfiguration::ScreensConfiguration() |
1335 | +{ |
1336 | + const QString dbPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QStringLiteral("/unity8/"); |
1337 | + QFile f(dbPath + "workspaces"); |
1338 | + |
1339 | + if (f.open(QIODevice::ReadOnly)) { |
1340 | + QByteArray saveData = f.readAll(); |
1341 | + QJsonDocument loadDoc(QJsonDocument::fromJson(saveData)); |
1342 | + QJsonObject json(loadDoc.object()); |
1343 | + jsonScreens = json["screens"].toArray(); |
1344 | + } |
1345 | +} |
1346 | + |
1347 | +ScreensConfiguration::~ScreensConfiguration() |
1348 | +{ |
1349 | + const QString dbPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QStringLiteral("/unity8/"); |
1350 | + QFile f(dbPath + "workspaces"); |
1351 | + if (f.open(QIODevice::WriteOnly)) { |
1352 | + QJsonObject json; |
1353 | + json["screens"] = jsonScreens; |
1354 | + QJsonDocument saveDoc(json); |
1355 | + f.write(saveDoc.toJson()); |
1356 | + } |
1357 | +} |
1358 | + |
1359 | +void ScreensConfiguration::load(Screen *screen) |
1360 | +{ |
1361 | + int workspaces = 2; |
1362 | + for (auto iter = jsonScreens.begin(); iter != jsonScreens.end(); ++iter) { |
1363 | + QJsonObject jsonScreen = (*iter).toObject(); |
1364 | + if (jsonScreen["name"] == screen->name()) { |
1365 | + QJsonValue jsonWorkspaces = jsonScreen["workspaces"]; |
1366 | + workspaces = qMax(jsonWorkspaces.toInt(workspaces), 1); |
1367 | + break; |
1368 | + } |
1369 | + } |
1370 | + |
1371 | + for (int i = 0; i < workspaces; i++) { |
1372 | + WorkspaceManager::instance()->createWorkspace()->assign(screen->workspaces()); |
1373 | + } |
1374 | +} |
1375 | + |
1376 | +void ScreensConfiguration::save(Screen *screen) |
1377 | +{ |
1378 | + QJsonObject newJsonScreen; |
1379 | + newJsonScreen["name"] = screen->name(); |
1380 | + newJsonScreen["workspaces"] = qMax(screen->workspaces()->rowCount(), 1); |
1381 | + |
1382 | + auto iter = jsonScreens.begin(); |
1383 | + for (; iter != jsonScreens.end(); ++iter) { |
1384 | + QJsonObject jsonScreen = (*iter).toObject(); |
1385 | + if (jsonScreen["name"] == screen->name()) { |
1386 | + break; |
1387 | + } |
1388 | + } |
1389 | + |
1390 | + if (iter == jsonScreens.end()) { |
1391 | + jsonScreens.push_back(newJsonScreen); |
1392 | + } else { |
1393 | + *iter = newJsonScreen; |
1394 | + } |
1395 | +} |
1396 | |
1397 | === added file 'plugins/WindowManager/ScreensConfiguration.h' |
1398 | --- plugins/WindowManager/ScreensConfiguration.h 1970-01-01 00:00:00 +0000 |
1399 | +++ plugins/WindowManager/ScreensConfiguration.h 2017-04-05 11:48:54 +0000 |
1400 | @@ -0,0 +1,32 @@ |
1401 | +/* |
1402 | + * Copyright (C) 2017 Canonical, Ltd. |
1403 | + * |
1404 | + * This program is free software; you can redistribute it and/or modify |
1405 | + * it under the terms of the GNU General Public License as published by |
1406 | + * the Free Software Foundation; version 3. |
1407 | + * |
1408 | + * This program is distributed in the hope that it will be useful, |
1409 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1410 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1411 | + * GNU General Public License for more details. |
1412 | + * |
1413 | + * You should have received a copy of the GNU General Public License |
1414 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1415 | + */ |
1416 | + |
1417 | +#ifndef SCREENSCONFIGURATION_H |
1418 | +#define SCREENSCONFIGURATION_H |
1419 | + |
1420 | +class Screen; |
1421 | + |
1422 | +class ScreensConfiguration |
1423 | +{ |
1424 | +public: |
1425 | + explicit ScreensConfiguration(); |
1426 | + ~ScreensConfiguration(); |
1427 | + |
1428 | + void load(Screen* screen); |
1429 | + void save(Screen* screen); |
1430 | +}; |
1431 | + |
1432 | +#endif // SCREENSCONFIGURATION_H |
1433 | |
1434 | === modified file 'plugins/WindowManager/TopLevelWindowModel.cpp' |
1435 | --- plugins/WindowManager/TopLevelWindowModel.cpp 2017-03-16 15:30:33 +0000 |
1436 | +++ plugins/WindowManager/TopLevelWindowModel.cpp 2017-04-05 11:48:54 +0000 |
1437 | @@ -15,6 +15,7 @@ |
1438 | */ |
1439 | |
1440 | #include "TopLevelWindowModel.h" |
1441 | +#include "WindowManagerObjects.h" |
1442 | |
1443 | // unity-api |
1444 | #include <unity/shell/application/ApplicationInfoInterface.h> |
1445 | @@ -24,11 +25,11 @@ |
1446 | #include <unity/shell/application/SurfaceManagerInterface.h> |
1447 | |
1448 | // Qt |
1449 | -#include <QGuiApplication> |
1450 | #include <QDebug> |
1451 | |
1452 | // local |
1453 | #include "Window.h" |
1454 | +#include "Workspace.h" |
1455 | |
1456 | Q_LOGGING_CATEGORY(TOPLEVELWINDOWMODEL, "toplevelwindowmodel", QtInfoMsg) |
1457 | |
1458 | @@ -37,7 +38,19 @@ |
1459 | |
1460 | namespace unityapi = unity::shell::application; |
1461 | |
1462 | -TopLevelWindowModel::TopLevelWindowModel() |
1463 | +TopLevelWindowModel::TopLevelWindowModel(Workspace* workspace) |
1464 | + : m_workspace(workspace) |
1465 | +{ |
1466 | + connect(WindowManagerObjects::instance(), &WindowManagerObjects::applicationManagerChanged, |
1467 | + this, &TopLevelWindowModel::setApplicationManager); |
1468 | + connect(WindowManagerObjects::instance(), &WindowManagerObjects::surfaceManagerChanged, |
1469 | + this, &TopLevelWindowModel::setSurfaceManager); |
1470 | + |
1471 | + setApplicationManager(WindowManagerObjects::instance()->applicationManager()); |
1472 | + setSurfaceManager(WindowManagerObjects::instance()->surfaceManager()); |
1473 | +} |
1474 | + |
1475 | +TopLevelWindowModel::~TopLevelWindowModel() |
1476 | { |
1477 | } |
1478 | |
1479 | @@ -55,7 +68,6 @@ |
1480 | beginResetModel(); |
1481 | |
1482 | if (m_applicationManager) { |
1483 | - m_windowModel.clear(); |
1484 | disconnect(m_applicationManager, 0, this, 0); |
1485 | } |
1486 | |
1487 | @@ -64,26 +76,26 @@ |
1488 | if (m_applicationManager) { |
1489 | connect(m_applicationManager, &QAbstractItemModel::rowsInserted, |
1490 | this, [this](const QModelIndex &/*parent*/, int first, int last) { |
1491 | - for (int i = first; i <= last; ++i) { |
1492 | - auto application = m_applicationManager->get(i); |
1493 | - addApplication(application); |
1494 | - } |
1495 | - }); |
1496 | + if (!m_workspace || !m_workspace->isActive()) |
1497 | + return; |
1498 | + |
1499 | + for (int i = first; i <= last; ++i) { |
1500 | + auto application = m_applicationManager->get(i); |
1501 | + addApplication(application); |
1502 | + } |
1503 | + }); |
1504 | |
1505 | connect(m_applicationManager, &QAbstractItemModel::rowsAboutToBeRemoved, |
1506 | this, [this](const QModelIndex &/*parent*/, int first, int last) { |
1507 | - for (int i = first; i <= last; ++i) { |
1508 | - auto application = m_applicationManager->get(i); |
1509 | - removeApplication(application); |
1510 | - } |
1511 | - }); |
1512 | - |
1513 | - for (int i = 0; i < m_applicationManager->rowCount(); ++i) { |
1514 | - auto application = m_applicationManager->get(i); |
1515 | - addApplication(application); |
1516 | - } |
1517 | + for (int i = first; i <= last; ++i) { |
1518 | + auto application = m_applicationManager->get(i); |
1519 | + removeApplication(application); |
1520 | + } |
1521 | + }); |
1522 | } |
1523 | |
1524 | + refreshWindows(); |
1525 | + |
1526 | endResetModel(); |
1527 | m_modelState = IdleState; |
1528 | } |
1529 | @@ -96,6 +108,11 @@ |
1530 | |
1531 | DEBUG_MSG << "(" << surfaceManager << ")"; |
1532 | |
1533 | + Q_ASSERT(m_modelState == IdleState); |
1534 | + m_modelState = ResettingState; |
1535 | + |
1536 | + beginResetModel(); |
1537 | + |
1538 | if (m_surfaceManager) { |
1539 | disconnect(m_surfaceManager, 0, this, 0); |
1540 | } |
1541 | @@ -103,13 +120,16 @@ |
1542 | m_surfaceManager = surfaceManager; |
1543 | |
1544 | if (m_surfaceManager) { |
1545 | - connect(m_surfaceManager, &unityapi::SurfaceManagerInterface::surfaceCreated, this, &TopLevelWindowModel::onSurfaceCreated); |
1546 | + connect(m_surfaceManager, &unityapi::SurfaceManagerInterface::surfacesAddedToWorkspace, this, &TopLevelWindowModel::onSurfacesAddedToWorkspace); |
1547 | connect(m_surfaceManager, &unityapi::SurfaceManagerInterface::surfacesRaised, this, &TopLevelWindowModel::onSurfacesRaised); |
1548 | connect(m_surfaceManager, &unityapi::SurfaceManagerInterface::modificationsStarted, this, &TopLevelWindowModel::onModificationsStarted); |
1549 | connect(m_surfaceManager, &unityapi::SurfaceManagerInterface::modificationsEnded, this, &TopLevelWindowModel::onModificationsEnded); |
1550 | } |
1551 | |
1552 | - Q_EMIT surfaceManagerChanged(m_surfaceManager); |
1553 | + refreshWindows(); |
1554 | + |
1555 | + endResetModel(); |
1556 | + m_modelState = IdleState; |
1557 | } |
1558 | |
1559 | void TopLevelWindowModel::addApplication(unityapi::ApplicationInfoInterface *application) |
1560 | @@ -149,6 +169,7 @@ |
1561 | Q_ASSERT(surface != nullptr); |
1562 | |
1563 | connectSurface(surface); |
1564 | + m_allSurfaces.insert(surface); |
1565 | |
1566 | bool filledPlaceholder = false; |
1567 | for (int i = 0; i < m_windowModel.count() && !filledPlaceholder; ++i) { |
1568 | @@ -225,15 +246,14 @@ |
1569 | |
1570 | connect(window, &Window::focusedChanged, this, [this, window](bool focused) { |
1571 | if (window->surface()) { |
1572 | - // Condense changes to the focused window |
1573 | - // eg: Do focusedWindow=A to focusedWindow=B instead of |
1574 | - // focusedWindow=A to focusedWindow=null to focusedWindow=B |
1575 | if (focused) { |
1576 | - Q_ASSERT(m_newlyFocusedWindow == nullptr); |
1577 | - m_focusedWindowChanged = true; |
1578 | - m_newlyFocusedWindow = window; |
1579 | + setFocusedWindow(window); |
1580 | + m_focusedWindowCleared = false; |
1581 | } else if (m_focusedWindow == window) { |
1582 | - m_focusedWindowChanged = true; |
1583 | + // Condense changes to the focused window |
1584 | + // eg: Do focusedWindow=A to focusedWindow=B instead of |
1585 | + // focusedWindow=A to focusedWindow=null to focusedWindow=B |
1586 | + m_focusedWindowCleared = true; |
1587 | } else { |
1588 | // don't clear the focused window if you were not there in the first place |
1589 | // happens when a filled window gets replaced with an empty one (no surface) as the focused window. |
1590 | @@ -338,6 +358,7 @@ |
1591 | auto window = m_windowModel[i].window; |
1592 | window->setSurface(nullptr); |
1593 | window->setFocused(false); |
1594 | + m_allSurfaces.remove(surface); |
1595 | INFO_MSG << " Removed surface from entry. After: " << toString(); |
1596 | } |
1597 | } |
1598 | @@ -353,44 +374,103 @@ |
1599 | return qmlWindow; |
1600 | } |
1601 | |
1602 | -void TopLevelWindowModel::onSurfaceCreated(unityapi::MirSurfaceInterface *surface) |
1603 | -{ |
1604 | - DEBUG_MSG << "(" << surface << ")"; |
1605 | - |
1606 | - if (surface->parentSurface()) { |
1607 | - // Wrap it in a Window so that we keep focusedWindow() up to date. |
1608 | - Window *window = createWindow(surface); |
1609 | - connect(surface, &QObject::destroyed, window, [=](){ |
1610 | +void TopLevelWindowModel::onSurfacesAddedToWorkspace(const std::shared_ptr<miral::Workspace>& workspace, |
1611 | + const QVector<unity::shell::application::MirSurfaceInterface*> surfaces) |
1612 | +{ |
1613 | + if (!m_workspace || !m_applicationManager) return; |
1614 | + if (workspace != m_workspace->workspace()) { |
1615 | + removeSurfaces(surfaces); |
1616 | + return; |
1617 | + } |
1618 | + |
1619 | + Q_FOREACH(auto surface, surfaces) { |
1620 | + if (m_allSurfaces.contains(surface)) continue; |
1621 | + |
1622 | + if (surface->parentSurface()) { |
1623 | + // Wrap it in a Window so that we keep focusedWindow() up to date. |
1624 | + Window *window = createWindow(surface); |
1625 | + connect(surface, &QObject::destroyed, window, [=](){ |
1626 | + window->setSurface(nullptr); |
1627 | + window->deleteLater(); |
1628 | + }); |
1629 | + } else { |
1630 | + if (surface->type() == Mir::InputMethodType) { |
1631 | + connectSurface(surface); |
1632 | + setInputMethodWindow(createWindow(surface)); |
1633 | + } else { |
1634 | + auto *application = m_applicationManager->findApplicationWithSurface(surface); |
1635 | + if (application) { |
1636 | + if (surface->state() == Mir::HiddenState) { |
1637 | + // Ignore it until it's finally shown |
1638 | + connect(surface, &unityapi::MirSurfaceInterface::stateChanged, this, [=](Mir::State newState) { |
1639 | + Q_ASSERT(newState != Mir::HiddenState); |
1640 | + disconnect(surface, &unityapi::MirSurfaceInterface::stateChanged, this, 0); |
1641 | + prependSurface(surface, application); |
1642 | + }); |
1643 | + } else { |
1644 | + prependSurface(surface, application); |
1645 | + } |
1646 | + } else { |
1647 | + // Must be a prompt session. No need to do add it as a prompt surface is not top-level. |
1648 | + // It will show up in the ApplicationInfoInterface::promptSurfaceList of some application. |
1649 | + // Still wrap it in a Window though, so that we keep focusedWindow() up to date. |
1650 | + Window *promptWindow = createWindow(surface); |
1651 | + connect(surface, &QObject::destroyed, promptWindow, [=](){ |
1652 | + promptWindow->setSurface(nullptr); |
1653 | + promptWindow->deleteLater(); |
1654 | + }); |
1655 | + } |
1656 | + } |
1657 | + } |
1658 | + } |
1659 | +} |
1660 | + |
1661 | +void TopLevelWindowModel::removeSurfaces(const QVector<unity::shell::application::MirSurfaceInterface *> surfaces) |
1662 | +{ |
1663 | + int start = -1; |
1664 | + int end = -1; |
1665 | + for (auto iter = surfaces.constBegin(); iter != surfaces.constEnd();) { |
1666 | + auto surface = *iter; |
1667 | + iter++; |
1668 | + |
1669 | + // Do removals in adjacent blocks. |
1670 | + start = end = indexOf(surface); |
1671 | + if (start == -1) { |
1672 | + // could be a child surface |
1673 | + m_allSurfaces.remove(surface); |
1674 | + continue; |
1675 | + } |
1676 | + while(iter != surfaces.constEnd()) { |
1677 | + int index = indexOf(*iter); |
1678 | + if (index != end+1) { |
1679 | + break; |
1680 | + } |
1681 | + end++; |
1682 | + iter++; |
1683 | + } |
1684 | + |
1685 | + if (m_modelState == IdleState) { |
1686 | + beginRemoveRows(QModelIndex(), start, end); |
1687 | + m_modelState = RemovingState; |
1688 | + } else { |
1689 | + Q_ASSERT(m_modelState == ResettingState); |
1690 | + // No point in signaling anything if we're resetting the whole model |
1691 | + } |
1692 | + |
1693 | + for (int index = start; index <= end; index++) { |
1694 | + auto window = m_windowModel[start].window; |
1695 | window->setSurface(nullptr); |
1696 | - window->deleteLater(); |
1697 | - }); |
1698 | - } else { |
1699 | - if (surface->type() == Mir::InputMethodType) { |
1700 | - connectSurface(surface); |
1701 | - setInputMethodWindow(createWindow(surface)); |
1702 | - } else { |
1703 | - auto *application = m_applicationManager->findApplicationWithSurface(surface); |
1704 | - if (application) { |
1705 | - if (surface->state() == Mir::HiddenState) { |
1706 | - // Ignore it until it's finally shown |
1707 | - connect(surface, &unityapi::MirSurfaceInterface::stateChanged, this, [=](Mir::State newState) { |
1708 | - Q_ASSERT(newState != Mir::HiddenState); |
1709 | - disconnect(surface, &unityapi::MirSurfaceInterface::stateChanged, this, 0); |
1710 | - prependSurface(surface, application); |
1711 | - }); |
1712 | - } else { |
1713 | - prependSurface(surface, application); |
1714 | - } |
1715 | - } else { |
1716 | - // Must be a prompt session. No need to do add it as a prompt surface is not top-level. |
1717 | - // It will show up in the ApplicationInfoInterface::promptSurfaceList of some application. |
1718 | - // Still wrap it in a Window though, so that we keep focusedWindow() up to date. |
1719 | - Window *promptWindow = createWindow(surface); |
1720 | - connect(surface, &QObject::destroyed, promptWindow, [=](){ |
1721 | - promptWindow->setSurface(nullptr); |
1722 | - promptWindow->deleteLater(); |
1723 | - }); |
1724 | - } |
1725 | + window->setFocused(false); |
1726 | + |
1727 | + m_windowModel.removeAt(start); |
1728 | + m_allSurfaces.remove(surface); |
1729 | + } |
1730 | + |
1731 | + if (m_modelState == RemovingState) { |
1732 | + endRemoveRows(); |
1733 | + Q_EMIT countChanged(); |
1734 | + Q_EMIT listChanged(); |
1735 | + m_modelState = IdleState; |
1736 | } |
1737 | } |
1738 | } |
1739 | @@ -417,12 +497,14 @@ |
1740 | } |
1741 | |
1742 | auto window = m_windowModel[index].window; |
1743 | + auto surface = window->surface(); |
1744 | |
1745 | if (!window->surface()) { |
1746 | window->setFocused(false); |
1747 | } |
1748 | |
1749 | m_windowModel.removeAt(index); |
1750 | + m_allSurfaces.remove(surface); |
1751 | |
1752 | if (m_modelState == RemovingState) { |
1753 | endRemoveRows(); |
1754 | @@ -433,6 +515,7 @@ |
1755 | |
1756 | if (m_focusedWindow == window) { |
1757 | setFocusedWindow(nullptr); |
1758 | + m_focusedWindowCleared = false; |
1759 | } |
1760 | |
1761 | INFO_MSG << " after " << toString(); |
1762 | @@ -451,6 +534,15 @@ |
1763 | void TopLevelWindowModel::removeInputMethodWindow() |
1764 | { |
1765 | if (m_inputMethodWindow) { |
1766 | + auto surface = m_inputMethodWindow->surface(); |
1767 | + if (surface) { |
1768 | + m_allSurfaces.remove(surface); |
1769 | + } |
1770 | + if (m_focusedWindow == m_inputMethodWindow) { |
1771 | + setFocusedWindow(nullptr); |
1772 | + m_focusedWindowCleared = false; |
1773 | + } |
1774 | + |
1775 | delete m_inputMethodWindow; |
1776 | m_inputMethodWindow = nullptr; |
1777 | Q_EMIT inputMethodSurfaceChanged(nullptr); |
1778 | @@ -462,7 +554,7 @@ |
1779 | DEBUG_MSG << "(" << surfaces << ")"; |
1780 | const int raiseCount = surfaces.size(); |
1781 | for (int i = 0; i < raiseCount; i++) { |
1782 | - int fromIndex = findIndexOf(surfaces[i]); |
1783 | + int fromIndex = indexOf(surfaces[i]); |
1784 | if (fromIndex != -1) { |
1785 | move(fromIndex, 0); |
1786 | } |
1787 | @@ -489,16 +581,6 @@ |
1788 | } |
1789 | } |
1790 | |
1791 | -int TopLevelWindowModel::findIndexOf(const unityapi::MirSurfaceInterface *surface) const |
1792 | -{ |
1793 | - for (int i=0; i<m_windowModel.count(); i++) { |
1794 | - if (m_windowModel[i].window->surface() == surface) { |
1795 | - return i; |
1796 | - } |
1797 | - } |
1798 | - return -1; |
1799 | -} |
1800 | - |
1801 | int TopLevelWindowModel::generateId() |
1802 | { |
1803 | int id = m_nextId; |
1804 | @@ -700,12 +782,11 @@ |
1805 | |
1806 | void TopLevelWindowModel::onModificationsEnded() |
1807 | { |
1808 | - if (m_focusedWindowChanged) { |
1809 | - setFocusedWindow(m_newlyFocusedWindow); |
1810 | + if (m_focusedWindowCleared) { |
1811 | + setFocusedWindow(nullptr); |
1812 | } |
1813 | // reset |
1814 | - m_focusedWindowChanged = false; |
1815 | - m_newlyFocusedWindow = nullptr; |
1816 | + m_focusedWindowCleared = false; |
1817 | } |
1818 | |
1819 | void TopLevelWindowModel::activateTopMostWindowWithoutId(int forbiddenId) |
1820 | @@ -719,3 +800,54 @@ |
1821 | } |
1822 | } |
1823 | } |
1824 | + |
1825 | +void TopLevelWindowModel::refreshWindows() |
1826 | +{ |
1827 | + DEBUG_MSG << "()"; |
1828 | + clear(); |
1829 | + |
1830 | + if (!m_workspace || !m_applicationManager || !m_surfaceManager) return; |
1831 | + |
1832 | + m_surfaceManager->forEachSurfaceInWorkspace(m_workspace->workspace(), [this](unity::shell::application::MirSurfaceInterface* surface) { |
1833 | + if (surface->parentSurface()) { |
1834 | + // Wrap it in a Window so that we keep focusedWindow() up to date. |
1835 | + Window *window = createWindow(surface); |
1836 | + connect(surface, &QObject::destroyed, window, [=](){ |
1837 | + window->setSurface(nullptr); |
1838 | + window->deleteLater(); |
1839 | + }); |
1840 | + } else { |
1841 | + if (surface->type() == Mir::InputMethodType) { |
1842 | + setInputMethodWindow(createWindow(surface)); |
1843 | + } else { |
1844 | + auto *application = m_applicationManager->findApplicationWithSurface(surface); |
1845 | + if (application) { |
1846 | + prependSurface(surface, application); |
1847 | + } else { |
1848 | + // Must be a prompt session. No need to do add it as a prompt surface is not top-level. |
1849 | + // It will show up in the ApplicationInfoInterface::promptSurfaceList of some application. |
1850 | + // Still wrap it in a Window though, so that we keep focusedWindow() up to date. |
1851 | + Window *promptWindow = createWindow(surface); |
1852 | + connect(surface, &QObject::destroyed, promptWindow, [=](){ |
1853 | + promptWindow->setSurface(nullptr); |
1854 | + promptWindow->deleteLater(); |
1855 | + }); |
1856 | + } |
1857 | + } |
1858 | + } |
1859 | + }); |
1860 | +} |
1861 | + |
1862 | +void TopLevelWindowModel::clear() |
1863 | +{ |
1864 | + DEBUG_MSG << "()"; |
1865 | + |
1866 | + while(m_windowModel.count() > 0) { |
1867 | + ModelEntry entry = m_windowModel.takeAt(0); |
1868 | + disconnect(entry.window, 0, this, 0); |
1869 | + delete entry.window; |
1870 | + } |
1871 | + m_allSurfaces.clear(); |
1872 | + setFocusedWindow(nullptr); |
1873 | + m_focusedWindowCleared = false; |
1874 | +} |
1875 | |
1876 | === modified file 'plugins/WindowManager/TopLevelWindowModel.h' |
1877 | --- plugins/WindowManager/TopLevelWindowModel.h 2017-03-16 15:30:33 +0000 |
1878 | +++ plugins/WindowManager/TopLevelWindowModel.h 2017-04-05 11:48:54 +0000 |
1879 | @@ -20,11 +20,16 @@ |
1880 | #include <QAbstractListModel> |
1881 | #include <QLoggingCategory> |
1882 | |
1883 | +#include <memory> |
1884 | + |
1885 | #include "WindowManagerGlobal.h" |
1886 | |
1887 | Q_DECLARE_LOGGING_CATEGORY(TOPLEVELWINDOWMODEL) |
1888 | |
1889 | class Window; |
1890 | +class Workspace; |
1891 | + |
1892 | +namespace miral { class Workspace; } |
1893 | |
1894 | namespace unity { |
1895 | namespace shell { |
1896 | @@ -72,16 +77,6 @@ |
1897 | */ |
1898 | Q_PROPERTY(Window* focusedWindow READ focusedWindow NOTIFY focusedWindowChanged) |
1899 | |
1900 | - Q_PROPERTY(unity::shell::application::SurfaceManagerInterface* surfaceManager |
1901 | - READ surfaceManager |
1902 | - WRITE setSurfaceManager |
1903 | - NOTIFY surfaceManagerChanged) |
1904 | - |
1905 | - Q_PROPERTY(unity::shell::application::ApplicationManagerInterface* applicationManager |
1906 | - READ applicationManager |
1907 | - WRITE setApplicationManager |
1908 | - NOTIFY applicationManagerChanged) |
1909 | - |
1910 | /** |
1911 | The id to be used on the next entry created |
1912 | Useful for tests |
1913 | @@ -100,7 +95,8 @@ |
1914 | ApplicationRole = Qt::UserRole + 1, |
1915 | }; |
1916 | |
1917 | - TopLevelWindowModel(); |
1918 | + TopLevelWindowModel(Workspace* workspace); |
1919 | + ~TopLevelWindowModel(); |
1920 | |
1921 | // From QAbstractItemModel |
1922 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; |
1923 | @@ -111,17 +107,11 @@ |
1924 | return roleNames; |
1925 | } |
1926 | |
1927 | - // Own API |
1928 | + // Own API; |
1929 | |
1930 | unity::shell::application::MirSurfaceInterface* inputMethodSurface() const; |
1931 | Window* focusedWindow() const; |
1932 | |
1933 | - unity::shell::application::ApplicationManagerInterface *applicationManager() const { return m_applicationManager; } |
1934 | - void setApplicationManager(unity::shell::application::ApplicationManagerInterface*); |
1935 | - |
1936 | - unity::shell::application::SurfaceManagerInterface *surfaceManager() const { return m_surfaceManager; } |
1937 | - void setSurfaceManager(unity::shell::application::SurfaceManagerInterface*); |
1938 | - |
1939 | int nextId() const { return m_nextId; } |
1940 | |
1941 | public: |
1942 | @@ -164,12 +154,13 @@ |
1943 | */ |
1944 | Q_INVOKABLE void raiseId(int id); |
1945 | |
1946 | + void setApplicationManager(unity::shell::application::ApplicationManagerInterface*); |
1947 | + void setSurfaceManager(unity::shell::application::SurfaceManagerInterface*); |
1948 | + |
1949 | Q_SIGNALS: |
1950 | void countChanged(); |
1951 | void inputMethodSurfaceChanged(unity::shell::application::MirSurfaceInterface* inputMethodSurface); |
1952 | void focusedWindowChanged(Window *focusedWindow); |
1953 | - void applicationManagerChanged(unity::shell::application::ApplicationManagerInterface*); |
1954 | - void surfaceManagerChanged(unity::shell::application::SurfaceManagerInterface*); |
1955 | |
1956 | /** |
1957 | * @brief Emitted when the list changes |
1958 | @@ -181,7 +172,8 @@ |
1959 | void nextIdChanged(); |
1960 | |
1961 | private Q_SLOTS: |
1962 | - void onSurfaceCreated(unity::shell::application::MirSurfaceInterface *surface); |
1963 | + void onSurfacesAddedToWorkspace(const std::shared_ptr<miral::Workspace>& workspace, |
1964 | + const QVector<unity::shell::application::MirSurfaceInterface*> surfaces); |
1965 | void onSurfacesRaised(const QVector<unity::shell::application::MirSurfaceInterface*> &surfaces); |
1966 | |
1967 | void onModificationsStarted(); |
1968 | @@ -198,9 +190,9 @@ |
1969 | void setInputMethodWindow(Window *window); |
1970 | void setFocusedWindow(Window *window); |
1971 | void removeInputMethodWindow(); |
1972 | - int findIndexOf(const unity::shell::application::MirSurfaceInterface *surface) const; |
1973 | void deleteAt(int index); |
1974 | void removeAt(int index); |
1975 | + void removeSurfaces(const QVector<unity::shell::application::MirSurfaceInterface *> surfaces); |
1976 | |
1977 | void addApplication(unity::shell::application::ApplicationInfoInterface *application); |
1978 | void removeApplication(unity::shell::application::ApplicationInfoInterface *application); |
1979 | @@ -223,6 +215,8 @@ |
1980 | void activateEmptyWindow(Window *window); |
1981 | |
1982 | void activateTopMostWindowWithoutId(int forbiddenId); |
1983 | + void refreshWindows(); |
1984 | + void clear(); |
1985 | |
1986 | Window *createWindow(unity::shell::application::MirSurfaceInterface *surface); |
1987 | |
1988 | @@ -239,6 +233,9 @@ |
1989 | QVector<ModelEntry> m_windowModel; |
1990 | Window* m_inputMethodWindow{nullptr}; |
1991 | Window* m_focusedWindow{nullptr}; |
1992 | + Workspace* m_workspace{nullptr}; |
1993 | + // track all the surfaces we've been told about. |
1994 | + QSet<unity::shell::application::MirSurfaceInterface*> m_allSurfaces; |
1995 | |
1996 | int m_nextId{1}; |
1997 | // Just something big enough that we don't risk running out of unused id numbers. |
1998 | @@ -259,8 +256,7 @@ |
1999 | ModelState m_modelState{IdleState}; |
2000 | |
2001 | // Valid between modificationsStarted and modificationsEnded |
2002 | - bool m_focusedWindowChanged{false}; |
2003 | - Window *m_newlyFocusedWindow{nullptr}; |
2004 | + bool m_focusedWindowCleared{false}; |
2005 | }; |
2006 | |
2007 | #endif // TOPLEVELWINDOWMODEL_H |
2008 | |
2009 | === added file 'plugins/WindowManager/WindowManagerObjects.cpp' |
2010 | --- plugins/WindowManager/WindowManagerObjects.cpp 1970-01-01 00:00:00 +0000 |
2011 | +++ plugins/WindowManager/WindowManagerObjects.cpp 2017-04-05 11:48:54 +0000 |
2012 | @@ -0,0 +1,47 @@ |
2013 | +/* |
2014 | + * Copyright (C) 2017 Canonical, Ltd. |
2015 | + * |
2016 | + * This program is free software; you can redistribute it and/or modify |
2017 | + * it under the terms of the GNU General Public License as published by |
2018 | + * the Free Software Foundation; version 3. |
2019 | + * |
2020 | + * This program is distributed in the hope that it will be useful, |
2021 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2022 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2023 | + * GNU General Public License for more details. |
2024 | + * |
2025 | + * You should have received a copy of the GNU General Public License |
2026 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2027 | + */ |
2028 | + |
2029 | +#include "WindowManagerObjects.h" |
2030 | + |
2031 | +WindowManagerObjects::WindowManagerObjects(QObject *parent) |
2032 | + : QObject(parent) |
2033 | + , m_surfaceManager(nullptr) |
2034 | + , m_applicationManager(nullptr) |
2035 | +{ |
2036 | +} |
2037 | + |
2038 | +WindowManagerObjects *WindowManagerObjects::instance() |
2039 | +{ |
2040 | + static WindowManagerObjects* objects(new WindowManagerObjects()); |
2041 | + return objects; |
2042 | +} |
2043 | + |
2044 | + |
2045 | +void WindowManagerObjects::setSurfaceManager(unity::shell::application::SurfaceManagerInterface *surfaceManager) |
2046 | +{ |
2047 | + if (m_surfaceManager == surfaceManager) return; |
2048 | + |
2049 | + m_surfaceManager = surfaceManager; |
2050 | + Q_EMIT surfaceManagerChanged(surfaceManager); |
2051 | +} |
2052 | + |
2053 | +void WindowManagerObjects::setApplicationManager(unity::shell::application::ApplicationManagerInterface *applicationManager) |
2054 | +{ |
2055 | + if (m_applicationManager == applicationManager) return; |
2056 | + |
2057 | + m_applicationManager = applicationManager; |
2058 | + Q_EMIT applicationManagerChanged(applicationManager); |
2059 | +} |
2060 | |
2061 | === added file 'plugins/WindowManager/WindowManagerObjects.h' |
2062 | --- plugins/WindowManager/WindowManagerObjects.h 1970-01-01 00:00:00 +0000 |
2063 | +++ plugins/WindowManager/WindowManagerObjects.h 2017-04-05 11:48:54 +0000 |
2064 | @@ -0,0 +1,66 @@ |
2065 | +/* |
2066 | + * Copyright (C) 2017 Canonical, Ltd. |
2067 | + * |
2068 | + * This program is free software; you can redistribute it and/or modify |
2069 | + * it under the terms of the GNU General Public License as published by |
2070 | + * the Free Software Foundation; version 3. |
2071 | + * |
2072 | + * This program is distributed in the hope that it will be useful, |
2073 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2074 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2075 | + * GNU General Public License for more details. |
2076 | + * |
2077 | + * You should have received a copy of the GNU General Public License |
2078 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2079 | + */ |
2080 | + |
2081 | +#ifndef WINDOWMANAGEROBJECTS_H |
2082 | +#define WINDOWMANAGEROBJECTS_H |
2083 | + |
2084 | +#include <QObject> |
2085 | + |
2086 | +#include "WindowManagerGlobal.h" |
2087 | + |
2088 | +namespace unity { |
2089 | + namespace shell { |
2090 | + namespace application { |
2091 | + class SurfaceManagerInterface; |
2092 | + class ApplicationManagerInterface; |
2093 | + } |
2094 | + } |
2095 | +} |
2096 | + |
2097 | +class WINDOWMANAGERQML_EXPORT WindowManagerObjects : public QObject |
2098 | +{ |
2099 | + Q_OBJECT |
2100 | + |
2101 | + Q_PROPERTY(unity::shell::application::SurfaceManagerInterface* surfaceManager |
2102 | + READ surfaceManager |
2103 | + WRITE setSurfaceManager |
2104 | + NOTIFY surfaceManagerChanged) |
2105 | + |
2106 | + Q_PROPERTY(unity::shell::application::ApplicationManagerInterface* applicationManager |
2107 | + READ applicationManager |
2108 | + WRITE setApplicationManager |
2109 | + NOTIFY applicationManagerChanged) |
2110 | +public: |
2111 | + explicit WindowManagerObjects(QObject *parent = 0); |
2112 | + |
2113 | + static WindowManagerObjects *instance(); |
2114 | + |
2115 | + unity::shell::application::SurfaceManagerInterface *surfaceManager() const { return m_surfaceManager; } |
2116 | + void setSurfaceManager(unity::shell::application::SurfaceManagerInterface*); |
2117 | + |
2118 | + unity::shell::application::ApplicationManagerInterface *applicationManager() const { return m_applicationManager; } |
2119 | + void setApplicationManager(unity::shell::application::ApplicationManagerInterface*); |
2120 | + |
2121 | +Q_SIGNALS: |
2122 | + void surfaceManagerChanged(unity::shell::application::SurfaceManagerInterface*); |
2123 | + void applicationManagerChanged(unity::shell::application::ApplicationManagerInterface*); |
2124 | + |
2125 | +private: |
2126 | + unity::shell::application::SurfaceManagerInterface* m_surfaceManager; |
2127 | + unity::shell::application::ApplicationManagerInterface* m_applicationManager; |
2128 | +}; |
2129 | + |
2130 | +#endif // WINDOWMANAGEROBJECTS_H |
2131 | |
2132 | === modified file 'plugins/WindowManager/WindowManagerPlugin.cpp' |
2133 | --- plugins/WindowManager/WindowManagerPlugin.cpp 2017-03-24 14:04:50 +0000 |
2134 | +++ plugins/WindowManager/WindowManagerPlugin.cpp 2017-04-05 11:48:54 +0000 |
2135 | @@ -17,19 +17,74 @@ |
2136 | #include "WindowManagerPlugin.h" |
2137 | |
2138 | #include "AvailableDesktopArea.h" |
2139 | +#include "Screen.h" |
2140 | +#include "ScreenAttached.h" |
2141 | +#include "Screens.h" |
2142 | +#include "ScreensConfiguration.h" |
2143 | +#include "ScreenWindow.h" |
2144 | #include "TopLevelWindowModel.h" |
2145 | #include "Window.h" |
2146 | +#include "WindowManagerObjects.h" |
2147 | #include "WindowMargins.h" |
2148 | +#include "WorkspaceManager.h" |
2149 | +#include "Workspace.h" |
2150 | +#include "WorkspaceModel.h" |
2151 | |
2152 | #include <QtQml> |
2153 | +#include <qtmir/qtmir.h> |
2154 | + |
2155 | +namespace { |
2156 | + |
2157 | +static const QString notInstantiatable = QStringLiteral("Not instantiatable"); |
2158 | + |
2159 | +static QObject *workspace_manager(QQmlEngine *engine, QJSEngine *scriptEngine) |
2160 | +{ |
2161 | + Q_UNUSED(engine) |
2162 | + Q_UNUSED(scriptEngine) |
2163 | + return WorkspaceManager::instance(); |
2164 | +} |
2165 | +QObject* screensSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) { |
2166 | + Q_UNUSED(engine); |
2167 | + Q_UNUSED(scriptEngine); |
2168 | + return ConcreteScreens::self(); |
2169 | +} |
2170 | +QObject* objectsSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) { |
2171 | + Q_UNUSED(engine); |
2172 | + Q_UNUSED(scriptEngine); |
2173 | + return WindowManagerObjects::instance(); |
2174 | +} |
2175 | + |
2176 | +} // namspace |
2177 | |
2178 | void WindowManagerPlugin::registerTypes(const char *uri) |
2179 | { |
2180 | qmlRegisterType<AvailableDesktopArea>(uri, 1, 0, "AvailableDesktopArea"); |
2181 | - qmlRegisterType<TopLevelWindowModel>(uri, 1, 0, "TopLevelWindowModel"); |
2182 | qmlRegisterType<WindowMargins>(uri, 1, 0, "WindowMargins"); |
2183 | + qmlRegisterSingletonType<WorkspaceManager>(uri, 1, 0, "WorkspaceManager", workspace_manager); |
2184 | + qmlRegisterSingletonType<ConcreteScreens>(uri, 1, 0, "Screens", screensSingleton); |
2185 | + qmlRegisterUncreatableType<qtmir::ScreenMode>(uri, 1, 0, "ScreenMode", notInstantiatable); |
2186 | + qmlRegisterSingletonType<WindowManagerObjects>(uri, 1, 0, "WindowManagerObjects", objectsSingleton); |
2187 | + |
2188 | + qRegisterMetaType<ConcreteScreen*>("ConcreteScreen*"); |
2189 | + qRegisterMetaType<ProxyScreens*>("ProxyScreens*"); |
2190 | + qRegisterMetaType<Workspace*>("Workspace*"); |
2191 | + qRegisterMetaType<TopLevelWindowModel*>("TopLevelWindowModel*"); |
2192 | + qRegisterMetaType<ScreenConfig*>("ScreenConfig*"); |
2193 | + qRegisterMetaType<WorkspaceModel*>("WorkspaceModel*"); |
2194 | |
2195 | qRegisterMetaType<Window*>("Window*"); |
2196 | - |
2197 | qRegisterMetaType<QAbstractListModel*>("QAbstractListModel*"); |
2198 | + |
2199 | + qmlRegisterType<ScreenWindow>(uri, 1, 0, "ScreenWindow"); |
2200 | + qmlRegisterRevision<QWindow,1>(uri, 1, 0); |
2201 | + |
2202 | + qmlRegisterUncreatableType<WMScreen>(uri, 1, 0, "WMScreen", notInstantiatable); |
2203 | +} |
2204 | + |
2205 | +void WindowManagerPlugin::initializeEngine(QQmlEngine *engine, const char *uri) |
2206 | +{ |
2207 | + QQmlExtensionPlugin::initializeEngine(engine, uri); |
2208 | + |
2209 | + // Create Screens |
2210 | + new ConcreteScreens(qtmir::get_screen_model(), new ScreensConfiguration()); |
2211 | } |
2212 | |
2213 | === modified file 'plugins/WindowManager/WindowManagerPlugin.h' |
2214 | --- plugins/WindowManager/WindowManagerPlugin.h 2016-04-04 13:37:49 +0000 |
2215 | +++ plugins/WindowManager/WindowManagerPlugin.h 2017-04-05 11:48:54 +0000 |
2216 | @@ -27,6 +27,7 @@ |
2217 | |
2218 | public: |
2219 | void registerTypes(const char *uri) override; |
2220 | + void initializeEngine(QQmlEngine *engine, const char *uri) override; |
2221 | }; |
2222 | |
2223 | #endif // WINDOWMANAGER_PLUGIN_H |
2224 | |
2225 | === added file 'plugins/WindowManager/Workspace.cpp' |
2226 | --- plugins/WindowManager/Workspace.cpp 1970-01-01 00:00:00 +0000 |
2227 | +++ plugins/WindowManager/Workspace.cpp 2017-04-05 11:48:54 +0000 |
2228 | @@ -0,0 +1,178 @@ |
2229 | +/* |
2230 | + * Copyright (C) 2017 Canonical, Ltd. |
2231 | + * |
2232 | + * This program is free software; you can redistribute it and/or modify |
2233 | + * it under the terms of the GNU General Public License as published by |
2234 | + * the Free Software Foundation; version 3. |
2235 | + * |
2236 | + * This program is distributed in the hope that it will be useful, |
2237 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2238 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2239 | + * GNU General Public License for more details. |
2240 | + * |
2241 | + * You should have received a copy of the GNU General Public License |
2242 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2243 | + */ |
2244 | + |
2245 | +#include "Workspace.h" |
2246 | +#include "WorkspaceModel.h" |
2247 | +#include "WorkspaceManager.h" |
2248 | +#include "TopLevelWindowModel.h" |
2249 | +#include "Screen.h" |
2250 | + |
2251 | +#include "wmpolicyinterface.h" |
2252 | + |
2253 | +int nextWorkspace = 0; |
2254 | + |
2255 | +Workspace::Workspace(QObject *parent) |
2256 | + : QObject(parent) |
2257 | + , m_workspace(WMPolicyInterface::instance()->createWorkspace()) |
2258 | + , m_model(nullptr) |
2259 | +{ |
2260 | + setObjectName((QString("Wks%1").arg(nextWorkspace++))); |
2261 | +} |
2262 | + |
2263 | +Workspace::Workspace(const Workspace &other) |
2264 | + : QObject(nullptr) |
2265 | + , m_workspace(other.m_workspace) |
2266 | + , m_model(nullptr) |
2267 | +{ |
2268 | + setObjectName(other.objectName()); |
2269 | + |
2270 | + connect(&other, &Workspace::activeChanged, this, &Workspace::activeChanged); |
2271 | +} |
2272 | + |
2273 | +Workspace::~Workspace() |
2274 | +{ |
2275 | + if (m_model) { |
2276 | + m_model->remove(this); |
2277 | + } |
2278 | +} |
2279 | + |
2280 | +void Workspace::assign(WorkspaceModel *model, const QVariant& vIndex) |
2281 | +{ |
2282 | + if (m_model == model) return; |
2283 | + |
2284 | + if (m_model) { |
2285 | + disconnect(m_model, 0, this, 0); |
2286 | + m_model->remove(this); |
2287 | + } |
2288 | + |
2289 | + m_model = model; |
2290 | + |
2291 | + if (model) { |
2292 | + int index = m_model->rowCount(); |
2293 | + if (vIndex.isValid() && vIndex.canConvert(QVariant::Int)) { |
2294 | + index = vIndex.toInt(); |
2295 | + } |
2296 | + m_model->insert(index, this); |
2297 | + |
2298 | + connect(m_model, &QObject::destroyed, this, [this]() { |
2299 | + m_model = nullptr; |
2300 | + Q_EMIT unassigned(); |
2301 | + }); |
2302 | + Q_EMIT assigned(); |
2303 | + } else { |
2304 | + Q_EMIT unassigned(); |
2305 | + } |
2306 | +} |
2307 | + |
2308 | +void Workspace::unassign() |
2309 | +{ |
2310 | + assign(nullptr); |
2311 | +} |
2312 | + |
2313 | +bool Workspace::isAssigned() const |
2314 | +{ |
2315 | + return m_model != nullptr; |
2316 | +} |
2317 | + |
2318 | +bool Workspace::isSameAs(Workspace *wks) const |
2319 | +{ |
2320 | + if (!wks) return false; |
2321 | + if (wks == this) return true; |
2322 | + return wks->workspace() == workspace(); |
2323 | +} |
2324 | + |
2325 | + |
2326 | +ConcreteWorkspace::ConcreteWorkspace(QObject *parent) |
2327 | + : Workspace(parent) |
2328 | + , m_active(false) |
2329 | + , m_windowModel(new TopLevelWindowModel(this)) |
2330 | +{ |
2331 | + connect(WorkspaceManager::instance(), &WorkspaceManager::activeWorkspaceChanged, this, [this](Workspace* activeWorkspace) { |
2332 | + bool newActive = activeWorkspace == this; |
2333 | + if (newActive != m_active) { |
2334 | + m_active = newActive; |
2335 | + Q_EMIT activeChanged(m_active); |
2336 | + |
2337 | + if (m_active) { |
2338 | + WMPolicyInterface::instance()->setActiveWorkspace(m_workspace); |
2339 | + } |
2340 | + } |
2341 | + }); |
2342 | +} |
2343 | + |
2344 | +ConcreteWorkspace::~ConcreteWorkspace() |
2345 | +{ |
2346 | + WorkspaceManager::instance()->destroyWorkspace(this); |
2347 | + WMPolicyInterface::instance()->releaseWorkspace(m_workspace); |
2348 | +} |
2349 | + |
2350 | +TopLevelWindowModel *ConcreteWorkspace::windowModel() const |
2351 | +{ |
2352 | + return m_windowModel.data(); |
2353 | +} |
2354 | + |
2355 | +void ConcreteWorkspace::activate() |
2356 | +{ |
2357 | + WorkspaceManager::instance()->setActiveWorkspace(this); |
2358 | +} |
2359 | + |
2360 | +void ConcreteWorkspace::setCurrentOn(Screen *screen) |
2361 | +{ |
2362 | + if (screen) { |
2363 | + screen->setCurrentWorkspace(this); |
2364 | + } |
2365 | +} |
2366 | + |
2367 | + |
2368 | +ProxyWorkspace::ProxyWorkspace(Workspace * const workspace) |
2369 | + : Workspace(*workspace) |
2370 | + , m_original(workspace) |
2371 | +{ |
2372 | +} |
2373 | + |
2374 | +void ProxyWorkspace::assign(WorkspaceModel *model, const QVariant &index) |
2375 | +{ |
2376 | + Workspace::assign(model, index); |
2377 | +} |
2378 | + |
2379 | +void ProxyWorkspace::unassign() |
2380 | +{ |
2381 | + Workspace::unassign(); |
2382 | +} |
2383 | + |
2384 | +bool ProxyWorkspace::isActive() const |
2385 | +{ |
2386 | + return m_original ? m_original->isActive() : false; |
2387 | +} |
2388 | + |
2389 | +TopLevelWindowModel *ProxyWorkspace::windowModel() const |
2390 | +{ |
2391 | + return m_original ? m_original->windowModel() : nullptr; |
2392 | +} |
2393 | + |
2394 | +void ProxyWorkspace::activate() |
2395 | +{ |
2396 | + if (m_original) { |
2397 | + m_original->activate(); |
2398 | + } |
2399 | +} |
2400 | + |
2401 | +void ProxyWorkspace::setCurrentOn(Screen *screen) |
2402 | +{ |
2403 | + if (screen && m_original) { |
2404 | + screen->setCurrentWorkspace(m_original); |
2405 | + } |
2406 | +} |
2407 | |
2408 | === added file 'plugins/WindowManager/Workspace.h' |
2409 | --- plugins/WindowManager/Workspace.h 1970-01-01 00:00:00 +0000 |
2410 | +++ plugins/WindowManager/Workspace.h 2017-04-05 11:48:54 +0000 |
2411 | @@ -0,0 +1,122 @@ |
2412 | +/* |
2413 | + * Copyright (C) 2017 Canonical, Ltd. |
2414 | + * |
2415 | + * This program is free software; you can redistribute it and/or modify |
2416 | + * it under the terms of the GNU General Public License as published by |
2417 | + * the Free Software Foundation; version 3. |
2418 | + * |
2419 | + * This program is distributed in the hope that it will be useful, |
2420 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2421 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2422 | + * GNU General Public License for more details. |
2423 | + * |
2424 | + * You should have received a copy of the GNU General Public License |
2425 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2426 | + */ |
2427 | + |
2428 | +#ifndef WINDOWMANAGER_WORKSPACE_H |
2429 | +#define WINDOWMANAGER_WORKSPACE_H |
2430 | + |
2431 | +#include <QObject> |
2432 | +#include <QVariant> |
2433 | +#include <QPointer> |
2434 | +#include <QSharedPointer> |
2435 | + |
2436 | +#include <memory> |
2437 | +#include <functional> |
2438 | + |
2439 | +#include "WindowManagerGlobal.h" |
2440 | + |
2441 | +class WorkspaceModel; |
2442 | +class TopLevelWindowModel; |
2443 | +class Screen; |
2444 | + |
2445 | +namespace miral { class Workspace; } |
2446 | + |
2447 | +namespace unity { |
2448 | + namespace shell { |
2449 | + namespace application { |
2450 | + class MirSurfaceInterface; |
2451 | + } |
2452 | + } |
2453 | +} |
2454 | + |
2455 | +class WINDOWMANAGERQML_EXPORT Workspace : public QObject |
2456 | +{ |
2457 | + Q_OBJECT |
2458 | + Q_PROPERTY(bool active READ isActive NOTIFY activeChanged) |
2459 | + Q_PROPERTY(TopLevelWindowModel* windowModel READ windowModel CONSTANT) |
2460 | +public: |
2461 | + virtual ~Workspace(); |
2462 | + |
2463 | + virtual void assign(WorkspaceModel* model, const QVariant& index = QVariant()); |
2464 | + virtual void unassign(); |
2465 | + |
2466 | + virtual bool isActive() const = 0; |
2467 | + virtual TopLevelWindowModel *windowModel() const = 0; |
2468 | + virtual void setCurrentOn(Screen*) = 0; |
2469 | + |
2470 | + std::shared_ptr<miral::Workspace> workspace() const { return m_workspace; } |
2471 | + bool isAssigned() const; |
2472 | + Q_INVOKABLE bool isSameAs(Workspace*) const; |
2473 | + |
2474 | +public Q_SLOTS: |
2475 | + virtual void activate() = 0; |
2476 | + |
2477 | +Q_SIGNALS: |
2478 | + void assigned(); |
2479 | + void unassigned(); |
2480 | + |
2481 | + void activeChanged(bool); |
2482 | + |
2483 | +protected: |
2484 | + Workspace(QObject *parent = nullptr); |
2485 | + Workspace(Workspace const& other); |
2486 | + |
2487 | + std::shared_ptr<miral::Workspace> m_workspace; |
2488 | + WorkspaceModel* m_model; |
2489 | +}; |
2490 | + |
2491 | +class WINDOWMANAGERQML_EXPORT ConcreteWorkspace : public Workspace |
2492 | +{ |
2493 | +public: |
2494 | + ~ConcreteWorkspace(); |
2495 | + |
2496 | + bool isActive() const override { return m_active; } |
2497 | + TopLevelWindowModel *windowModel() const override; |
2498 | + void activate() override; |
2499 | + void setCurrentOn(Screen*) override; |
2500 | + |
2501 | +private: |
2502 | + explicit ConcreteWorkspace(QObject *parent = nullptr); |
2503 | + |
2504 | + bool m_active; |
2505 | + const QScopedPointer<TopLevelWindowModel> m_windowModel; |
2506 | + |
2507 | + friend class WorkspaceManager; |
2508 | +}; |
2509 | + |
2510 | +class ProxyWorkspace : public Workspace |
2511 | +{ |
2512 | + Q_OBJECT |
2513 | +public: |
2514 | + explicit ProxyWorkspace(Workspace*const workspace); |
2515 | + ~ProxyWorkspace() = default; |
2516 | + |
2517 | + Q_INVOKABLE void assign(WorkspaceModel* model, const QVariant& index = QVariant()) override; |
2518 | + |
2519 | + bool isActive() const override; |
2520 | + TopLevelWindowModel *windowModel() const override; |
2521 | + void activate() override; |
2522 | + void setCurrentOn(Screen*) override; |
2523 | + |
2524 | + Workspace* proxyObject() const { return m_original.data(); } |
2525 | + |
2526 | +public Q_SLOTS: |
2527 | + void unassign() override; |
2528 | + |
2529 | +private: |
2530 | + const QPointer<Workspace> m_original; |
2531 | +}; |
2532 | + |
2533 | +#endif // WINDOWMANAGER_WORKSPACE_H |
2534 | |
2535 | === added file 'plugins/WindowManager/WorkspaceManager.cpp' |
2536 | --- plugins/WindowManager/WorkspaceManager.cpp 1970-01-01 00:00:00 +0000 |
2537 | +++ plugins/WindowManager/WorkspaceManager.cpp 2017-04-05 11:48:54 +0000 |
2538 | @@ -0,0 +1,106 @@ |
2539 | +/* |
2540 | + * Copyright (C) 2017 Canonical, Ltd. |
2541 | + * |
2542 | + * This program is free software; you can redistribute it and/or modify |
2543 | + * it under the terms of the GNU General Public License as published by |
2544 | + * the Free Software Foundation; version 3. |
2545 | + * |
2546 | + * This program is distributed in the hope that it will be useful, |
2547 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2548 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2549 | + * GNU General Public License for more details. |
2550 | + * |
2551 | + * You should have received a copy of the GNU General Public License |
2552 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2553 | + */ |
2554 | + |
2555 | +#include "WorkspaceManager.h" |
2556 | +#include "Workspace.h" |
2557 | +#include "TopLevelWindowModel.h" |
2558 | +#include "WindowManagerObjects.h" |
2559 | +#include <unity/shell/application/SurfaceManagerInterface.h> |
2560 | + |
2561 | +// Qt |
2562 | +#include <QGuiApplication> |
2563 | +#include <QScreen> |
2564 | +#include <QQmlEngine> |
2565 | + |
2566 | +WorkspaceManager *WorkspaceManager::instance() |
2567 | +{ |
2568 | + static WorkspaceManager* workspaceManager(new WorkspaceManager()); |
2569 | + return workspaceManager; |
2570 | +} |
2571 | + |
2572 | +WorkspaceManager::WorkspaceManager() |
2573 | + : m_activeWorkspace(nullptr) |
2574 | +{ |
2575 | +} |
2576 | + |
2577 | +Workspace *WorkspaceManager::createWorkspace() |
2578 | +{ |
2579 | + auto workspace = new ConcreteWorkspace(this); |
2580 | + QQmlEngine::setObjectOwnership(workspace, QQmlEngine::CppOwnership); |
2581 | + m_allWorkspaces.insert(workspace); |
2582 | + |
2583 | + if (m_allWorkspaces.count() == 0 && m_activeWorkspace) { |
2584 | + setActiveWorkspace(nullptr); |
2585 | + } else if (m_allWorkspaces.count() == 1) { |
2586 | + setActiveWorkspace(workspace); |
2587 | + } |
2588 | + |
2589 | + return workspace; |
2590 | +} |
2591 | + |
2592 | +void WorkspaceManager::destroyWorkspace(Workspace *workspace) |
2593 | +{ |
2594 | + if (!workspace) return; |
2595 | + |
2596 | + if (workspace->isAssigned()) { |
2597 | + workspace->unassign(); |
2598 | + } |
2599 | + m_allWorkspaces.remove(workspace); |
2600 | + |
2601 | + if (m_activeWorkspace == workspace) { |
2602 | + setActiveWorkspace(m_allWorkspaces.count() ? *m_allWorkspaces.begin() : nullptr); |
2603 | + } |
2604 | + if (m_activeWorkspace) { |
2605 | + moveWorkspaceContentToWorkspace(m_activeWorkspace, workspace); |
2606 | + } |
2607 | + |
2608 | + disconnect(workspace, 0, this, 0); |
2609 | +} |
2610 | + |
2611 | +void WorkspaceManager::moveSurfaceToWorkspace(unity::shell::application::MirSurfaceInterface *surface, Workspace *workspace) |
2612 | +{ |
2613 | + auto surfaceManager = WindowManagerObjects::instance()->surfaceManager(); |
2614 | + if (surfaceManager) { |
2615 | + surfaceManager->moveSurfaceToWorkspace(surface, workspace->workspace()); |
2616 | + } |
2617 | +} |
2618 | + |
2619 | +void WorkspaceManager::moveWorkspaceContentToWorkspace(Workspace *to, Workspace *from) |
2620 | +{ |
2621 | + auto surfaceManager = WindowManagerObjects::instance()->surfaceManager(); |
2622 | + if (surfaceManager) { |
2623 | + surfaceManager->moveWorkspaceContentToWorkspace(to->workspace(), from->workspace()); |
2624 | + } |
2625 | +} |
2626 | + |
2627 | +Workspace *WorkspaceManager::activeWorkspace() const |
2628 | +{ |
2629 | + return m_activeWorkspace; |
2630 | +} |
2631 | + |
2632 | +void WorkspaceManager::setActiveWorkspace(Workspace *workspace) |
2633 | +{ |
2634 | + if (workspace != m_activeWorkspace) { |
2635 | + m_activeWorkspace = workspace; |
2636 | + Q_EMIT activeWorkspaceChanged(workspace); |
2637 | + } |
2638 | +} |
2639 | + |
2640 | +void WorkspaceManager::setActiveWorkspace2(Workspace *workspace) |
2641 | +{ |
2642 | + if (!workspace) return; |
2643 | + workspace->activate(); |
2644 | +} |
2645 | |
2646 | === added file 'plugins/WindowManager/WorkspaceManager.h' |
2647 | --- plugins/WindowManager/WorkspaceManager.h 1970-01-01 00:00:00 +0000 |
2648 | +++ plugins/WindowManager/WorkspaceManager.h 2017-04-05 11:48:54 +0000 |
2649 | @@ -0,0 +1,69 @@ |
2650 | +/* |
2651 | + * Copyright (C) 2017 Canonical, Ltd. |
2652 | + * |
2653 | + * This program is free software; you can redistribute it and/or modify |
2654 | + * it under the terms of the GNU General Public License as published by |
2655 | + * the Free Software Foundation; version 3. |
2656 | + * |
2657 | + * This program is distributed in the hope that it will be useful, |
2658 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2659 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2660 | + * GNU General Public License for more details. |
2661 | + * |
2662 | + * You should have received a copy of the GNU General Public License |
2663 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2664 | + */ |
2665 | + |
2666 | +#ifndef WORKSPACEMANAGER_H |
2667 | +#define WORKSPACEMANAGER_H |
2668 | + |
2669 | +#include <QQmlListProperty> |
2670 | + |
2671 | +#include "WindowManagerGlobal.h" |
2672 | +#include "WorkspaceModel.h" |
2673 | + |
2674 | +class Workspace; |
2675 | + |
2676 | +namespace unity { |
2677 | + namespace shell { |
2678 | + namespace application { |
2679 | + class MirSurfaceInterface; |
2680 | + class SurfaceManagerInterface; |
2681 | + } |
2682 | + } |
2683 | +} |
2684 | + |
2685 | +class WINDOWMANAGERQML_EXPORT WorkspaceManager : public QObject |
2686 | +{ |
2687 | + Q_OBJECT |
2688 | + Q_PROPERTY(Workspace* activeWorkspace READ activeWorkspace WRITE setActiveWorkspace2 NOTIFY activeWorkspaceChanged) |
2689 | + |
2690 | +public: |
2691 | + WorkspaceManager(); |
2692 | + static WorkspaceManager* instance(); |
2693 | + |
2694 | + Workspace* activeWorkspace() const; |
2695 | + void setActiveWorkspace(Workspace* workspace); |
2696 | + |
2697 | + Workspace* createWorkspace(); |
2698 | + void destroyWorkspace(Workspace* workspace); |
2699 | + |
2700 | + void destroyFloatingWorkspaces(); |
2701 | + |
2702 | + Q_INVOKABLE void moveSurfaceToWorkspace(unity::shell::application::MirSurfaceInterface* surface, |
2703 | + Workspace* workspace); |
2704 | + |
2705 | + Q_INVOKABLE void moveWorkspaceContentToWorkspace(Workspace* to, Workspace* from); |
2706 | + |
2707 | +Q_SIGNALS: |
2708 | + void activeWorkspaceChanged(Workspace*); |
2709 | + |
2710 | +private: |
2711 | + void setActiveWorkspace2(Workspace* workspace); |
2712 | + |
2713 | + QSet<Workspace*> m_allWorkspaces; |
2714 | + Workspace* m_activeWorkspace; |
2715 | + unity::shell::application::SurfaceManagerInterface* m_surfaceManager; |
2716 | +}; |
2717 | + |
2718 | +#endif // WORKSPACEMANAGER_H |
2719 | |
2720 | === added file 'plugins/WindowManager/WorkspaceModel.cpp' |
2721 | --- plugins/WindowManager/WorkspaceModel.cpp 1970-01-01 00:00:00 +0000 |
2722 | +++ plugins/WindowManager/WorkspaceModel.cpp 2017-04-05 11:48:54 +0000 |
2723 | @@ -0,0 +1,254 @@ |
2724 | +/* |
2725 | + * Copyright (C) 2017 Canonical, Ltd. |
2726 | + * |
2727 | + * This program is free software; you can redistribute it and/or modify |
2728 | + * it under the terms of the GNU General Public License as published by |
2729 | + * the Free Software Foundation; version 3. |
2730 | + * |
2731 | + * This program is distributed in the hope that it will be useful, |
2732 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2733 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2734 | + * GNU General Public License for more details. |
2735 | + * |
2736 | + * You should have received a copy of the GNU General Public License |
2737 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2738 | + */ |
2739 | + |
2740 | +#include "WorkspaceModel.h" |
2741 | +#include "WorkspaceManager.h" |
2742 | +#include "Workspace.h" |
2743 | +#include "Screen.h" |
2744 | + |
2745 | +#include <QQmlEngine> |
2746 | + |
2747 | +Q_LOGGING_CATEGORY(WORKSPACES, "Workspaces", QtInfoMsg) |
2748 | + |
2749 | +#define DEBUG_MSG qCDebug(WORKSPACES).nospace().noquote() << __func__ |
2750 | +#define INFO_MSG qCInfo(WORKSPACES).nospace().noquote() << __func__ |
2751 | + |
2752 | +WorkspaceModel::WorkspaceModel(QObject *parent) |
2753 | + : QAbstractListModel(parent) |
2754 | +{ |
2755 | +} |
2756 | + |
2757 | +WorkspaceModel::~WorkspaceModel() |
2758 | +{ |
2759 | + qDeleteAll(m_workspaces.toList()); // make a copy so the list doesnt edit itself during delete. |
2760 | + m_workspaces.clear(); |
2761 | +} |
2762 | + |
2763 | +void WorkspaceModel::append(Workspace *workspace) |
2764 | +{ |
2765 | + insert(m_workspaces.count(), workspace); |
2766 | +} |
2767 | + |
2768 | +void WorkspaceModel::insert(int index, Workspace *workspace) |
2769 | +{ |
2770 | + beginInsertRows(QModelIndex(), index, index); |
2771 | + |
2772 | + m_workspaces.insert(index, workspace); |
2773 | + |
2774 | + endInsertRows(); |
2775 | + |
2776 | + Q_EMIT workspaceInserted(index, workspace); |
2777 | + Q_EMIT countChanged(); |
2778 | +} |
2779 | + |
2780 | +void WorkspaceModel::remove(Workspace *workspace) |
2781 | +{ |
2782 | + int index = m_workspaces.indexOf(workspace); |
2783 | + if (index < 0) return; |
2784 | + |
2785 | + beginRemoveRows(QModelIndex(), index, index); |
2786 | + |
2787 | + m_workspaces.removeAt(index); |
2788 | + insertUnassigned(workspace); |
2789 | + |
2790 | + endRemoveRows(); |
2791 | + |
2792 | + Q_EMIT workspaceRemoved(workspace); |
2793 | + Q_EMIT countChanged(); |
2794 | +} |
2795 | + |
2796 | +void WorkspaceModel::move(int from, int to) |
2797 | +{ |
2798 | + if (from == to) return; |
2799 | + DEBUG_MSG << " from=" << from << " to=" << to; |
2800 | + |
2801 | + if (from >= 0 && from < m_workspaces.size() && to >= 0 && to < m_workspaces.size()) { |
2802 | + QModelIndex parent; |
2803 | + |
2804 | + beginMoveRows(parent, from, from, parent, to + (to > from ? 1 : 0)); |
2805 | +#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0) |
2806 | + const auto &window = m_windowModel.takeAt(from); |
2807 | + m_workspaces.insert(to, window); |
2808 | +#else |
2809 | + m_workspaces.move(from, to); |
2810 | +#endif |
2811 | + endMoveRows(); |
2812 | + |
2813 | + Q_EMIT workspaceMoved(from, to); |
2814 | + } |
2815 | +} |
2816 | + |
2817 | +int WorkspaceModel::indexOf(Workspace *workspace) const |
2818 | +{ |
2819 | + return m_workspaces.indexOf(workspace); |
2820 | +} |
2821 | + |
2822 | +Workspace *WorkspaceModel::get(int index) const |
2823 | +{ |
2824 | + if (index < 0 || index >= rowCount()) return nullptr; |
2825 | + return m_workspaces.at(index); |
2826 | +} |
2827 | + |
2828 | +int WorkspaceModel::rowCount(const QModelIndex &) const |
2829 | +{ |
2830 | + return m_workspaces.count(); |
2831 | +} |
2832 | + |
2833 | +QVariant WorkspaceModel::data(const QModelIndex &index, int role) const |
2834 | +{ |
2835 | + if (index.row() < 0 || index.row() >= m_workspaces.size()) |
2836 | + return QVariant(); |
2837 | + |
2838 | + if (role == WorkspaceRole) { |
2839 | + Workspace *workspace = m_workspaces.at(index.row()); |
2840 | + return QVariant::fromValue(workspace); |
2841 | + } else { |
2842 | + return QVariant(); |
2843 | + } |
2844 | +} |
2845 | + |
2846 | +void WorkspaceModel::sync(WorkspaceModel *proxy) |
2847 | +{ |
2848 | + if (!proxy) return; |
2849 | + const auto& proxyList = proxy->list(); |
2850 | + |
2851 | + // check for removals |
2852 | + int removedIndexWhichWasActive = -1; |
2853 | + QVector<Workspace*> dpCpy(this->list()); |
2854 | + Q_FOREACH(auto workspace, dpCpy) { |
2855 | + |
2856 | + bool found = false; |
2857 | + Q_FOREACH(auto p, proxyList) { |
2858 | + auto workspaceProxy = qobject_cast<ProxyWorkspace*>(p); |
2859 | + if (workspaceProxy->proxyObject() == workspace) { |
2860 | + found = true; |
2861 | + break; |
2862 | + } |
2863 | + } |
2864 | + if (!found) { |
2865 | + if (workspace->isActive()) { |
2866 | + removedIndexWhichWasActive = indexOf(workspace); |
2867 | + } |
2868 | + workspace->unassign(); |
2869 | + } |
2870 | + } |
2871 | + |
2872 | + // existing |
2873 | + QSet<Workspace*> newWorkspaces; |
2874 | + for (int i = 0; i < proxyList.count(); i++) { |
2875 | + auto workspaceProxy = qobject_cast<ProxyWorkspace*>(proxyList[i]); |
2876 | + auto workspace = workspaceProxy->proxyObject(); |
2877 | + |
2878 | + int oldIndex = this->indexOf(workspace); |
2879 | + |
2880 | + if (oldIndex < 0) { |
2881 | + workspace->assign(this, QVariant(i)); |
2882 | + } else if (oldIndex != i) { |
2883 | + this->move(oldIndex, i); |
2884 | + } |
2885 | + newWorkspaces.insert(workspace); |
2886 | + } |
2887 | + |
2888 | + // Make sure we have at least one workspace in the model. |
2889 | + if (rowCount() == 0) { |
2890 | + Workspace* workspace = WorkspaceManager::instance()->createWorkspace(); |
2891 | + workspace->assign(this); |
2892 | + (new ProxyWorkspace(workspace))->assign(proxy); |
2893 | + } |
2894 | + |
2895 | + if (removedIndexWhichWasActive != -1) { |
2896 | + int newActiveIndex = qMin(removedIndexWhichWasActive, this->rowCount()-1); |
2897 | + Workspace* newActiveWorkspace = newActiveIndex >= 0 ? this->get(newActiveIndex) : nullptr; |
2898 | + |
2899 | + WorkspaceManager::instance()->setActiveWorkspace(newActiveWorkspace); |
2900 | + } |
2901 | + |
2902 | + proxy->finishSync(); |
2903 | + finishSync(); |
2904 | +} |
2905 | + |
2906 | +void WorkspaceModel::finishSync() |
2907 | +{ |
2908 | + QSet<Workspace*> dpCpy(m_unassignedWorkspaces); |
2909 | + Q_FOREACH(auto workspace, dpCpy) { |
2910 | + delete workspace; |
2911 | + } |
2912 | + m_unassignedWorkspaces.clear(); |
2913 | +} |
2914 | + |
2915 | +void WorkspaceModel::insertUnassigned(Workspace *workspace) |
2916 | +{ |
2917 | + m_unassignedWorkspaces.insert(workspace); |
2918 | + connect(workspace, &Workspace::assigned, this, [=]() { |
2919 | + m_unassignedWorkspaces.remove(workspace); |
2920 | + disconnect(workspace, &Workspace::assigned, this, 0); |
2921 | + }); |
2922 | + connect(workspace, &QObject::destroyed, this, [=]() { |
2923 | + m_unassignedWorkspaces.remove(workspace); |
2924 | + }); |
2925 | +} |
2926 | + |
2927 | + |
2928 | +ProxyWorkspaceModel::ProxyWorkspaceModel(WorkspaceModel * const model, ProxyScreen* screen) |
2929 | + : m_original(model) |
2930 | + , m_screen(screen) |
2931 | +{ |
2932 | + Q_FOREACH(auto workspace, model->list()) { |
2933 | + auto proxy = new ProxyWorkspace(workspace); |
2934 | + QQmlEngine::setObjectOwnership(proxy, QQmlEngine::CppOwnership); |
2935 | + proxy->assign(this); |
2936 | + } |
2937 | + connect(m_original, &WorkspaceModel::workspaceInserted, this, [this](int index, Workspace* inserted) { |
2938 | + if (isSyncing()) return; |
2939 | + |
2940 | + (new ProxyWorkspace(inserted))->assign(this, index); |
2941 | + }); |
2942 | + connect(m_original, &WorkspaceModel::workspaceRemoved, this, [this](Workspace* removed) { |
2943 | + if (isSyncing()) return; |
2944 | + |
2945 | + for (int i = 0; i < rowCount(); i++) { |
2946 | + auto workspaceProxy = qobject_cast<ProxyWorkspace*>(get(i)); |
2947 | + auto w = workspaceProxy->proxyObject(); |
2948 | + if (w == removed) { |
2949 | + remove(workspaceProxy); |
2950 | + break; |
2951 | + } |
2952 | + } |
2953 | + }); |
2954 | + connect(m_original, &WorkspaceModel::workspaceMoved, this, [this](int from, int to) { |
2955 | + if (isSyncing()) return; |
2956 | + |
2957 | + move(from, to); |
2958 | + }); |
2959 | +} |
2960 | + |
2961 | +void ProxyWorkspaceModel::move(int from, int to) |
2962 | +{ |
2963 | + WorkspaceModel::move(from, to); |
2964 | +} |
2965 | + |
2966 | +bool ProxyWorkspaceModel::isSyncing() const |
2967 | +{ |
2968 | + return m_screen->isSyncing(); |
2969 | +} |
2970 | + |
2971 | +void ProxyWorkspaceModel::addWorkspace() |
2972 | +{ |
2973 | + auto newWorkspace = WorkspaceManager::instance()->createWorkspace(); |
2974 | + m_original->insertUnassigned(newWorkspace); |
2975 | + |
2976 | + (new ProxyWorkspace(newWorkspace))->assign(this); |
2977 | +} |
2978 | |
2979 | === added file 'plugins/WindowManager/WorkspaceModel.h' |
2980 | --- plugins/WindowManager/WorkspaceModel.h 1970-01-01 00:00:00 +0000 |
2981 | +++ plugins/WindowManager/WorkspaceModel.h 2017-04-05 11:48:54 +0000 |
2982 | @@ -0,0 +1,102 @@ |
2983 | +/* |
2984 | + * Copyright (C) 2017 Canonical, Ltd. |
2985 | + * |
2986 | + * This program is free software; you can redistribute it and/or modify |
2987 | + * it under the terms of the GNU General Public License as published by |
2988 | + * the Free Software Foundation; version 3. |
2989 | + * |
2990 | + * This program is distributed in the hope that it will be useful, |
2991 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2992 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2993 | + * GNU General Public License for more details. |
2994 | + * |
2995 | + * You should have received a copy of the GNU General Public License |
2996 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2997 | + */ |
2998 | + |
2999 | +#ifndef WORKSPACEMODEL_H |
3000 | +#define WORKSPACEMODEL_H |
3001 | + |
3002 | +#include <QAbstractListModel> |
3003 | +#include <QLoggingCategory> |
3004 | +#include <QPointer> |
3005 | + |
3006 | +Q_DECLARE_LOGGING_CATEGORY(WORKSPACES) |
3007 | + |
3008 | +class Workspace; |
3009 | +class ProxyWorkspaceModel; |
3010 | +class ProxyScreen; |
3011 | + |
3012 | +class WorkspaceModel : public QAbstractListModel |
3013 | +{ |
3014 | + Q_OBJECT |
3015 | + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) |
3016 | +public: |
3017 | + /** |
3018 | + * @brief The Roles supported by the model |
3019 | + * |
3020 | + * WorkspaceRole - A workspace. |
3021 | + */ |
3022 | + enum Roles { |
3023 | + WorkspaceRole = Qt::UserRole |
3024 | + }; |
3025 | + |
3026 | + explicit WorkspaceModel(QObject *parent = 0); |
3027 | + ~WorkspaceModel(); |
3028 | + |
3029 | + void append(Workspace *workspace); |
3030 | + void insert(int index, Workspace *workspace); |
3031 | + void remove(Workspace* workspace); |
3032 | + virtual void move(int from, int to); |
3033 | + |
3034 | + int indexOf(Workspace *workspace) const; |
3035 | + Workspace* get(int index) const; |
3036 | + |
3037 | + // From QAbstractItemModel |
3038 | + int rowCount(const QModelIndex &parent = QModelIndex()) const override; |
3039 | + QVariant data(const QModelIndex& index, int role) const override; |
3040 | + QHash<int, QByteArray> roleNames() const override { |
3041 | + QHash<int, QByteArray> roleNames { {WorkspaceRole, "workspace"} }; |
3042 | + return roleNames; |
3043 | + } |
3044 | + |
3045 | + const QVector<Workspace*>& list() const { return m_workspaces; } |
3046 | + |
3047 | + void sync(WorkspaceModel* proxy); |
3048 | + void finishSync(); |
3049 | + |
3050 | +Q_SIGNALS: |
3051 | + void countChanged(); |
3052 | + |
3053 | + void workspaceInserted(int index, Workspace *workspace); |
3054 | + void workspaceRemoved(Workspace *workspace); |
3055 | + void workspaceMoved(int from, int to); |
3056 | + |
3057 | +protected: |
3058 | + void insertUnassigned(Workspace* workspace); |
3059 | + |
3060 | + QVector<Workspace*> m_workspaces; |
3061 | + QSet<Workspace*> m_unassignedWorkspaces; |
3062 | + |
3063 | + friend class ProxyWorkspaceModel; |
3064 | +}; |
3065 | + |
3066 | +class ProxyWorkspaceModel : public WorkspaceModel |
3067 | +{ |
3068 | + Q_OBJECT |
3069 | +public: |
3070 | + explicit ProxyWorkspaceModel(WorkspaceModel*const model, ProxyScreen* screen); |
3071 | + |
3072 | + Q_INVOKABLE void move(int from, int to) override; |
3073 | + |
3074 | + bool isSyncing() const; |
3075 | + |
3076 | +public Q_SLOTS: |
3077 | + void addWorkspace(); |
3078 | + |
3079 | +protected: |
3080 | + const QPointer<WorkspaceModel> m_original; |
3081 | + const ProxyScreen* m_screen; |
3082 | +}; |
3083 | + |
3084 | +#endif // WORKSPACEMODEL_H |
3085 | |
3086 | === modified file 'qml/ApplicationMenus/MenuItem.qml' |
3087 | --- qml/ApplicationMenus/MenuItem.qml 2017-04-05 11:48:53 +0000 |
3088 | +++ qml/ApplicationMenus/MenuItem.qml 2017-02-23 13:19:41 +0000 |
3089 | @@ -17,7 +17,6 @@ |
3090 | import QtQuick 2.4 |
3091 | import QtQuick.Layouts 1.1 |
3092 | import Ubuntu.Components 1.3 |
3093 | -import "../Components/PanelState" |
3094 | |
3095 | ActionItem { |
3096 | id: root |
3097 | @@ -25,7 +24,6 @@ |
3098 | implicitWidth: requiredWidth |
3099 | |
3100 | property var menuData: undefined |
3101 | - property PanelState panelState |
3102 | |
3103 | readonly property real requiredWidth: { |
3104 | var val = 0; |
3105 | |
3106 | === modified file 'qml/ApplicationMenus/MenuPopup.qml' |
3107 | --- qml/ApplicationMenus/MenuPopup.qml 2017-04-05 11:48:53 +0000 |
3108 | +++ qml/ApplicationMenus/MenuPopup.qml 2017-04-05 11:48:54 +0000 |
3109 | @@ -294,7 +294,6 @@ |
3110 | // Parent will be loader |
3111 | id: menuItem |
3112 | menuData: parent.__menuData |
3113 | - panelState: root.panelState |
3114 | objectName: parent.objectName + "-actionItem" |
3115 | |
3116 | width: MathUtils.clamp(implicitWidth, d.__minimumWidth, d.__maximumWidth) |
3117 | |
3118 | === modified file 'qml/Components/VirtualTouchPad.qml' |
3119 | --- qml/Components/VirtualTouchPad.qml 2017-04-05 11:48:53 +0000 |
3120 | +++ qml/Components/VirtualTouchPad.qml 2017-04-05 11:48:54 +0000 |
3121 | @@ -18,7 +18,7 @@ |
3122 | import QtQuick.Layouts 1.1 |
3123 | import Ubuntu.Components 1.3 |
3124 | import Qt.labs.settings 1.0 |
3125 | -import Unity.Screens 0.1 |
3126 | +import WindowManager 1.0 |
3127 | import UInput 0.1 |
3128 | import "../Components" |
3129 | |
3130 | |
3131 | === modified file 'qml/ErrorApplication.qml' |
3132 | --- qml/ErrorApplication.qml 2017-04-05 11:48:53 +0000 |
3133 | +++ qml/ErrorApplication.qml 2017-04-05 11:48:54 +0000 |
3134 | @@ -17,7 +17,7 @@ |
3135 | import QtQuick 2.4 |
3136 | import QtQuick.Window 2.2 |
3137 | import Ubuntu.Components 1.3 |
3138 | -import Unity.Screens 0.1 |
3139 | +import WindowManager 1.0 |
3140 | |
3141 | Instantiator { |
3142 | id: root |
3143 | |
3144 | === modified file 'qml/OrientedShell.qml' |
3145 | --- qml/OrientedShell.qml 2017-04-05 11:48:53 +0000 |
3146 | +++ qml/OrientedShell.qml 2017-04-05 11:48:54 +0000 |
3147 | @@ -18,7 +18,7 @@ |
3148 | import QtQuick.Window 2.2 |
3149 | import Unity.InputInfo 0.1 |
3150 | import Unity.Session 0.1 |
3151 | -import Unity.Screens 0.1 |
3152 | +import WindowManager 1.0 |
3153 | import Utils 0.1 |
3154 | import GSettings 1.0 |
3155 | import "Components" |
3156 | @@ -34,7 +34,6 @@ |
3157 | |
3158 | property alias deviceConfiguration: _deviceConfiguration |
3159 | property alias orientations: d.orientations |
3160 | - property alias surfaceManager: shell.surfaceManager |
3161 | |
3162 | onWidthChanged: calculateUsageMode(); |
3163 | |
3164 | |
3165 | === modified file 'qml/Shell.qml' |
3166 | --- qml/Shell.qml 2017-04-05 11:48:53 +0000 |
3167 | +++ qml/Shell.qml 2017-04-05 11:48:54 +0000 |
3168 | @@ -53,7 +53,6 @@ |
3169 | theme.name: "Ubuntu.Components.Themes.SuruDark" |
3170 | |
3171 | // to be set from outside |
3172 | - property alias surfaceManager: topLevelSurfaceList.surfaceManager |
3173 | property int orientationAngle: 0 |
3174 | property int orientation |
3175 | property Orientations orientations |
3176 | @@ -98,6 +97,11 @@ |
3177 | |
3178 | readonly property var mainApp: stage.mainApp |
3179 | |
3180 | + readonly property var topLevelSurfaceList: { |
3181 | + if (!WMScreen.currentWorkspace) return null; |
3182 | + return WMScreen.currentWorkspace.windowModel |
3183 | + } |
3184 | + |
3185 | onMainAppChanged: { |
3186 | if (mainApp) { |
3187 | _onMainAppChanged(mainApp.appId); |
3188 | @@ -280,12 +284,6 @@ |
3189 | width: parent.width |
3190 | height: parent.height |
3191 | |
3192 | - TopLevelWindowModel { |
3193 | - id: topLevelSurfaceList |
3194 | - objectName: "topLevelSurfaceList" |
3195 | - applicationManager: ApplicationManager // it's a singleton |
3196 | - } |
3197 | - |
3198 | Stage { |
3199 | id: stage |
3200 | objectName: "stage" |
3201 | @@ -296,7 +294,7 @@ |
3202 | background: wallpaperResolver.background |
3203 | |
3204 | applicationManager: ApplicationManager |
3205 | - topLevelSurfaceList: topLevelSurfaceList |
3206 | + topLevelSurfaceList: shell.topLevelSurfaceList |
3207 | inputMethodRect: inputMethod.visibleRect |
3208 | rightEdgePushProgress: rightEdgeBarrier.progress |
3209 | availableDesktopArea: availableDesktopAreaItem |
3210 | @@ -366,7 +364,7 @@ |
3211 | InputMethod { |
3212 | id: inputMethod |
3213 | objectName: "inputMethod" |
3214 | - surface: topLevelSurfaceList.inputMethodSurface |
3215 | + surface: shell.topLevelSurfaceList.inputMethodSurface |
3216 | anchors { |
3217 | fill: parent |
3218 | topMargin: panel.panelHeight |
3219 | @@ -553,8 +551,8 @@ |
3220 | && !stage.spreadShown |
3221 | } |
3222 | |
3223 | - readonly property bool focusedSurfaceIsFullscreen: topLevelSurfaceList.focusedWindow |
3224 | - ? topLevelSurfaceList.focusedWindow.state === Mir.FullscreenState |
3225 | + readonly property bool focusedSurfaceIsFullscreen: shell.topLevelSurfaceList.focusedWindow |
3226 | + ? shell.topLevelSurfaceList.focusedWindow.state === Mir.FullscreenState |
3227 | : false |
3228 | fullscreenMode: (focusedSurfaceIsFullscreen && !LightDMService.greeter.active && launcher.progress == 0 && !stage.spreadShown) |
3229 | || greeter.hasLockedApp |
3230 | @@ -890,7 +888,7 @@ |
3231 | |
3232 | // non-visual objects |
3233 | KeymapSwitcher { |
3234 | - focusedSurface: topLevelSurfaceList.focusedWindow ? topLevelSurfaceList.focusedWindow.surface : null |
3235 | + focusedSurface: shell.topLevelSurfaceList.focusedWindow ? shell.topLevelSurfaceList.focusedWindow.surface : null |
3236 | } |
3237 | BrightnessControl {} |
3238 | |
3239 | |
3240 | === modified file 'qml/ShellApplication.qml' |
3241 | --- qml/ShellApplication.qml 2017-04-05 11:48:53 +0000 |
3242 | +++ qml/ShellApplication.qml 2017-04-05 11:48:54 +0000 |
3243 | @@ -16,22 +16,19 @@ |
3244 | |
3245 | import QtQuick 2.4 |
3246 | import QtQuick.Window 2.2 |
3247 | -import Unity.Screens 0.1 |
3248 | +import WindowManager 1.0 |
3249 | import Unity.Application 0.1 |
3250 | |
3251 | Instantiator { |
3252 | id: root |
3253 | model: Screens |
3254 | |
3255 | - property QtObject surfaceMan: SurfaceManager {} |
3256 | - |
3257 | ShellScreen { |
3258 | id: window |
3259 | objectName: "screen"+index |
3260 | screen: model.screen |
3261 | visibility: applicationArguments.hasFullscreen ? Window.FullScreen : Window.Windowed |
3262 | flags: applicationArguments.hasFrameless ? Qt.FramelessWindowHint : 0 |
3263 | - surfaceManager: surfaceMan |
3264 | |
3265 | Binding { |
3266 | when: applicationArguments.hasGeometry |
3267 | @@ -49,4 +46,15 @@ |
3268 | Component.onCompleted: screen.active = primary |
3269 | primary: index == 0 |
3270 | } |
3271 | + |
3272 | + property var windowManagerSurfaceManagerBinding: Binding { |
3273 | + target: WindowManagerObjects |
3274 | + property: "surfaceManager" |
3275 | + value: SurfaceManager |
3276 | + } |
3277 | + property var windowManagerApplicationManagerBinding: Binding { |
3278 | + target: WindowManagerObjects |
3279 | + property: "applicationManager" |
3280 | + value: ApplicationManager |
3281 | + } |
3282 | } |
3283 | |
3284 | === modified file 'qml/ShellScreen.qml' |
3285 | --- qml/ShellScreen.qml 2017-04-05 11:48:53 +0000 |
3286 | +++ qml/ShellScreen.qml 2017-04-05 11:48:54 +0000 |
3287 | @@ -16,7 +16,7 @@ |
3288 | |
3289 | import QtQuick 2.4 |
3290 | import Ubuntu.Components 1.3 |
3291 | -import Unity.Screens 0.1 |
3292 | +import WindowManager 1.0 |
3293 | import Cursor 1.1 |
3294 | import "Components" |
3295 | |
3296 | @@ -26,7 +26,6 @@ |
3297 | color: "black" |
3298 | title: "Unity8 Shell" |
3299 | property bool primary: false |
3300 | - property QtObject surfaceManager: null |
3301 | |
3302 | DeviceConfiguration { |
3303 | id: deviceConfiguration |
3304 | @@ -51,7 +50,6 @@ |
3305 | OrientedShell { |
3306 | implicitWidth: screenWindow.width |
3307 | implicitHeight: screenWindow.height |
3308 | - surfaceManager: screenWindow.surfaceManager |
3309 | |
3310 | deviceConfiguration { |
3311 | name: Screens.count > 1 ? "desktop" : applicationArguments.deviceName |
3312 | |
3313 | === modified file 'src/CMakeLists.txt' |
3314 | --- src/CMakeLists.txt 2017-04-05 11:48:53 +0000 |
3315 | +++ src/CMakeLists.txt 2017-04-05 11:48:54 +0000 |
3316 | @@ -9,6 +9,7 @@ |
3317 | ${Qt5Quick_PRIVATE_INCLUDE_DIRS} |
3318 | ${GSETTINGS_QT_INCLUDE_DIRS} |
3319 | ${CONNECTIVITY_INCLUDE_DIRS} |
3320 | + ${QTMIRSERVER_INCLUDE_DIRS} |
3321 | ) |
3322 | |
3323 | include_directories( |
3324 | @@ -29,10 +30,12 @@ |
3325 | ApplicationArguments.cpp |
3326 | main.cpp |
3327 | CachingNetworkManagerFactory.cpp |
3328 | - ShellApplication.cpp |
3329 | + DisplayConfigurationStorage.cpp |
3330 | + UnityApplication.cpp |
3331 | UnityCommandLineParser.cpp |
3332 | UnixSignalHandler.cpp |
3333 | DebuggingController.cpp |
3334 | + WindowManagementPolicy.cpp |
3335 | ${QML_FILES} # This is to make qml and image files appear in the IDE's project tree |
3336 | ) |
3337 | |
3338 | @@ -47,7 +50,14 @@ |
3339 | if (NOT "${ANDROID_PROPERTIES_INCLUDE_DIRS}" STREQUAL "") |
3340 | set_target_properties(${SHELL_APP} PROPERTIES INCLUDE_DIRECTORIES ${ANDROID_PROPERTIES_INCLUDE_DIRS}) |
3341 | endif() |
3342 | -target_link_libraries(${SHELL_APP} ${ANDROID_PROPERTIES_LDFLAGS} ${GSETTINGS_QT_LDFLAGS} UbuntuGestures connectivity-qt1 unity8-private) |
3343 | +target_link_libraries(${SHELL_APP} |
3344 | + ${ANDROID_PROPERTIES_LDFLAGS} |
3345 | + ${GSETTINGS_QT_LDFLAGS} |
3346 | + ${QTMIRSERVER_LDFLAGS} |
3347 | + UbuntuGestures |
3348 | + connectivity-qt1 |
3349 | + unity8-private |
3350 | +) |
3351 | |
3352 | if (ENABLE_TOUCH_EMULATION) |
3353 | target_link_libraries(${SHELL_APP} ${MOUSETOUCHADAPTOR_LIBS_LDFLAGS}) |
3354 | |
3355 | === added file 'src/DisplayConfigurationStorage.cpp' |
3356 | --- src/DisplayConfigurationStorage.cpp 1970-01-01 00:00:00 +0000 |
3357 | +++ src/DisplayConfigurationStorage.cpp 2017-04-05 11:48:54 +0000 |
3358 | @@ -0,0 +1,90 @@ |
3359 | +#include "DisplayConfigurationStorage.h" |
3360 | + |
3361 | +#include <QFile> |
3362 | +#include <QStandardPaths> |
3363 | +#include <QJsonObject> |
3364 | +#include <QJsonDocument> |
3365 | + |
3366 | +namespace { |
3367 | + |
3368 | +inline QString stringFromEdid(const miral::Edid& edid) |
3369 | +{ |
3370 | + QString str; |
3371 | + str += QString::fromStdString(edid.vendor); |
3372 | + str += QString("%1%2").arg(edid.product_code).arg(edid.serial_number); |
3373 | + |
3374 | + for (int i = 0; i < 4; i++) { |
3375 | + str += QString::fromStdString(edid.descriptors[i].string_value()); |
3376 | + } |
3377 | + return str; |
3378 | +} |
3379 | + |
3380 | +} |
3381 | + |
3382 | +DisplayConfigurationStorage::DisplayConfigurationStorage() |
3383 | +{ |
3384 | +} |
3385 | + |
3386 | +void DisplayConfigurationStorage::save(const miral::DisplayId &displayId, const miral::DisplayConfigurationOptions &options) |
3387 | +{ |
3388 | + const QString dbPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QStringLiteral("/unity8/"); |
3389 | + QFile f(dbPath + stringFromEdid(displayId.edid) + ".edid"); |
3390 | + |
3391 | + QJsonObject json; |
3392 | + if (options.used.is_set()) json.insert("used", options.used.value()); |
3393 | + if (options.clone_output_index.is_set()) json.insert("clone_output_index", static_cast<int>(options.clone_output_index.value())); |
3394 | + if (options.mode.is_set()) { |
3395 | + auto const& mode = options.mode.value(); |
3396 | + |
3397 | + QString sz(QString("%1x%2").arg(mode.size.width.as_int()).arg(mode.size.height.as_int())); |
3398 | + QJsonObject jsonMode({ |
3399 | + {"size", sz}, |
3400 | + {"refresh_rate", mode.refresh_rate } |
3401 | + }); |
3402 | + json.insert("mode", jsonMode); |
3403 | + } |
3404 | + if (options.orientation.is_set()) json.insert("orientation", static_cast<int>(options.orientation.value())); |
3405 | + if (options.form_factor.is_set()) json.insert("form_factor", static_cast<int>(options.form_factor.value())); |
3406 | + if (options.scale.is_set()) json.insert("scale", options.scale.value()); |
3407 | + |
3408 | + if (f.open(QIODevice::WriteOnly)) { |
3409 | + QJsonDocument saveDoc(json); |
3410 | + f.write(saveDoc.toJson()); |
3411 | + } |
3412 | +} |
3413 | + |
3414 | +bool DisplayConfigurationStorage::load(const miral::DisplayId &displayId, miral::DisplayConfigurationOptions &options) const |
3415 | +{ |
3416 | + const QString dbPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QStringLiteral("/unity8/"); |
3417 | + QFile f(dbPath + stringFromEdid(displayId.edid) + ".edid"); |
3418 | + |
3419 | + if (f.open(QIODevice::ReadOnly)) { |
3420 | + QByteArray saveData = f.readAll(); |
3421 | + QJsonDocument loadDoc(QJsonDocument::fromJson(saveData)); |
3422 | + |
3423 | + QJsonObject json(loadDoc.object()); |
3424 | + if (json.contains("used")) options.used = json["used"].toBool(); |
3425 | + if (json.contains("clone_output_index")) options.clone_output_index = json["clone_output_index"].toInt(); |
3426 | + if (json.contains("mode")) { |
3427 | + QJsonObject jsonMode = json["mode"].toObject(); |
3428 | + |
3429 | + if (jsonMode.contains("size") && jsonMode.contains("refresh_rate")) { |
3430 | + QString sz(jsonMode["size"].toString()); |
3431 | + QStringList geo = sz.split("x", QString::SkipEmptyParts); |
3432 | + if (geo.count() == 2) { |
3433 | + miral::DisplayConfigurationOptions::DisplayMode mode; |
3434 | + mode.size = mir::geometry::Size(geo[0].toInt(), geo[1].toInt()); |
3435 | + mode.refresh_rate = jsonMode["refresh_rate"].toDouble(); |
3436 | + options.mode = mode; |
3437 | + } |
3438 | + } |
3439 | + } |
3440 | + if (json.contains("orientation")) options.orientation = static_cast<MirOrientation>(json["orientation"].toInt()); |
3441 | + if (json.contains("form_factor")) options.form_factor = static_cast<MirFormFactor>(json["form_factor"].toInt()); |
3442 | + if (json.contains("scale")) options.scale = json["form_factor"].toDouble(); |
3443 | + |
3444 | + return true; |
3445 | + } |
3446 | + |
3447 | + return false; |
3448 | +} |
3449 | |
3450 | === added file 'src/DisplayConfigurationStorage.h' |
3451 | --- src/DisplayConfigurationStorage.h 1970-01-01 00:00:00 +0000 |
3452 | +++ src/DisplayConfigurationStorage.h 2017-04-05 11:48:54 +0000 |
3453 | @@ -0,0 +1,15 @@ |
3454 | +#ifndef UNITY_DISPLAYCONFIGURATIONSTORAGE_H |
3455 | +#define UNITY_DISPLAYCONFIGURATIONSTORAGE_H |
3456 | + |
3457 | +#include <qtmir/miral/display_configuration_storage.h> |
3458 | + |
3459 | +class DisplayConfigurationStorage : public miral::DisplayConfigurationStorage |
3460 | +{ |
3461 | +public: |
3462 | + DisplayConfigurationStorage(); |
3463 | + |
3464 | + void save(const miral::DisplayId& displayId, const miral::DisplayConfigurationOptions& options) override; |
3465 | + bool load(const miral::DisplayId& displayId, miral::DisplayConfigurationOptions& options) const override; |
3466 | +}; |
3467 | + |
3468 | +#endif // UNITY_DISPLAYCONFIGURATIONSTORAGE_H |
3469 | |
3470 | === renamed file 'src/ShellApplication.cpp' => 'src/UnityApplication.cpp' |
3471 | --- src/ShellApplication.cpp 2017-04-05 11:48:53 +0000 |
3472 | +++ src/UnityApplication.cpp 2017-04-05 11:48:54 +0000 |
3473 | @@ -14,7 +14,7 @@ |
3474 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3475 | */ |
3476 | |
3477 | -#include "ShellApplication.h" |
3478 | +#include "UnityApplication.h" |
3479 | |
3480 | // Qt |
3481 | #include <QLibrary> |
3482 | @@ -30,20 +30,30 @@ |
3483 | // libandroid-properties |
3484 | #include <hybris/properties/properties.h> |
3485 | |
3486 | +// qtmir |
3487 | +#include <qtmir/displayconfigurationstorage.h> |
3488 | + |
3489 | // local |
3490 | #include <paths.h> |
3491 | #include "CachingNetworkManagerFactory.h" |
3492 | #include "UnityCommandLineParser.h" |
3493 | #include "DebuggingController.h" |
3494 | - |
3495 | -ShellApplication::ShellApplication(int & argc, char ** argv, bool isMirServer) |
3496 | - : QGuiApplication(argc, argv) |
3497 | +#include "WindowManagementPolicy.h" |
3498 | +#include "DisplayConfigurationStorage.h" |
3499 | + |
3500 | +#include <QDebug> |
3501 | + |
3502 | + |
3503 | + |
3504 | +UnityApplication::UnityApplication(int & argc, char ** argv) |
3505 | + : qtmir::MirServerApplication(argc, argv, { qtmir::SetWindowManagementPolicy<WindowManagementPolicy>(), |
3506 | + qtmir::SetDisplayConfigurationStorage<DisplayConfigurationStorage>() }) |
3507 | , m_qmlArgs(this) |
3508 | { |
3509 | setApplicationName(QStringLiteral("unity8")); |
3510 | setOrganizationName(QStringLiteral("Canonical")); |
3511 | |
3512 | - setupQmlEngine(isMirServer); |
3513 | + setupQmlEngine(); |
3514 | |
3515 | if (m_qmlArgs.deviceName().isEmpty()) { |
3516 | char buffer[200]; |
3517 | @@ -85,8 +95,7 @@ |
3518 | m_qmlEngine->rootContext()->setContextProperty(QStringLiteral("applicationArguments"), &m_qmlArgs); |
3519 | m_qmlEngine->rootContext()->setContextProperty("DebuggingController", new DebuggingController(this)); |
3520 | |
3521 | - auto component(new QQmlComponent(m_qmlEngine, |
3522 | - QUrl::fromLocalFile(::qmlDirectory() + "/ShellApplication.qml"))); |
3523 | + auto component(new QQmlComponent(m_qmlEngine, m_qmlArgs.qmlfie())); |
3524 | component->create(); |
3525 | if (component->status() == QQmlComponent::Error) { |
3526 | m_qmlEngine->rootContext()->setContextProperty(QStringLiteral("errorString"), component->errorString()); |
3527 | @@ -112,12 +121,12 @@ |
3528 | } |
3529 | } |
3530 | |
3531 | -ShellApplication::~ShellApplication() |
3532 | +UnityApplication::~UnityApplication() |
3533 | { |
3534 | destroyResources(); |
3535 | } |
3536 | |
3537 | -void ShellApplication::destroyResources() |
3538 | +void UnityApplication::destroyResources() |
3539 | { |
3540 | #ifdef UNITY8_ENABLE_TOUCH_EMULATION |
3541 | delete m_mouseTouchAdaptor; |
3542 | @@ -128,16 +137,13 @@ |
3543 | m_qmlEngine = nullptr; |
3544 | } |
3545 | |
3546 | -void ShellApplication::setupQmlEngine(bool isMirServer) |
3547 | +void UnityApplication::setupQmlEngine() |
3548 | { |
3549 | m_qmlEngine = new QQmlEngine(this); |
3550 | |
3551 | m_qmlEngine->setBaseUrl(QUrl::fromLocalFile(::qmlDirectory())); |
3552 | |
3553 | prependImportPaths(m_qmlEngine, ::overrideImportPaths()); |
3554 | - if (!isMirServer) { |
3555 | - prependImportPaths(m_qmlEngine, ::nonMirImportPaths()); |
3556 | - } |
3557 | appendImportPaths(m_qmlEngine, ::fallbackImportPaths()); |
3558 | |
3559 | m_qmlEngine->setNetworkAccessManagerFactory(new CachingNetworkManagerFactory); |
3560 | |
3561 | === renamed file 'src/ShellApplication.h' => 'src/UnityApplication.h' |
3562 | --- src/ShellApplication.h 2017-04-05 11:48:53 +0000 |
3563 | +++ src/UnityApplication.h 2017-04-05 11:48:54 +0000 |
3564 | @@ -14,8 +14,8 @@ |
3565 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3566 | */ |
3567 | |
3568 | -#ifndef SHELLAPPLICATION_H |
3569 | -#define SHELLAPPLICATION_H |
3570 | +#ifndef UNITYAPPLICATION_H |
3571 | +#define UNITYAPPLICATION_H |
3572 | |
3573 | #include <QGuiApplication> |
3574 | #include <QQmlApplicationEngine> |
3575 | @@ -28,17 +28,19 @@ |
3576 | #include "MouseTouchAdaptor.h" |
3577 | #endif |
3578 | |
3579 | -class ShellApplication : public QGuiApplication |
3580 | +#include <qtmir/mirserverapplication.h> |
3581 | + |
3582 | +class UnityApplication : public qtmir::MirServerApplication |
3583 | { |
3584 | Q_OBJECT |
3585 | public: |
3586 | - ShellApplication(int & argc, char ** argv, bool isMirServer); |
3587 | - virtual ~ShellApplication(); |
3588 | + UnityApplication(int & argc, char ** argv); |
3589 | + virtual ~UnityApplication(); |
3590 | |
3591 | void destroyResources(); |
3592 | |
3593 | private: |
3594 | - void setupQmlEngine(bool isMirServer); |
3595 | + void setupQmlEngine(); |
3596 | ApplicationArguments m_qmlArgs; |
3597 | |
3598 | #ifdef UNITY8_ENABLE_TOUCH_EMULATION |
3599 | @@ -48,4 +50,4 @@ |
3600 | QQmlEngine *m_qmlEngine{nullptr}; |
3601 | }; |
3602 | |
3603 | -#endif // SHELLAPPLICATION_H |
3604 | +#endif // UNITYAPPLICATION_H |
3605 | |
3606 | === modified file 'src/UnityCommandLineParser.cpp' |
3607 | --- src/UnityCommandLineParser.cpp 2015-12-16 13:58:39 +0000 |
3608 | +++ src/UnityCommandLineParser.cpp 2017-04-05 11:48:54 +0000 |
3609 | @@ -15,6 +15,7 @@ |
3610 | */ |
3611 | |
3612 | #include "UnityCommandLineParser.h" |
3613 | +#include <paths.h> |
3614 | |
3615 | #include <QDebug> |
3616 | |
3617 | @@ -60,6 +61,11 @@ |
3618 | QStringLiteral("mode"), QStringLiteral("full-greeter")); |
3619 | parser.addOption(modeOption); |
3620 | |
3621 | + QCommandLineOption qmlfileOption(QStringLiteral("qmlfile"), |
3622 | + QStringLiteral("The base qml file to load"), |
3623 | + QStringLiteral("qmlfile"), ::qmlDirectory() + "/ShellApplication.qml"); |
3624 | + parser.addOption(qmlfileOption); |
3625 | + |
3626 | // Treat args with single dashes the same as arguments with two dashes |
3627 | // Ex: -fullscreen == --fullscreen |
3628 | parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); |
3629 | @@ -85,6 +91,8 @@ |
3630 | m_hasFullscreen = parser.isSet(fullscreenOption); |
3631 | m_deviceName = parser.value(devicenameOption); |
3632 | resolveMode(parser, modeOption); |
3633 | + |
3634 | + m_qmlfile = parser.value(qmlfileOption); |
3635 | } |
3636 | |
3637 | int UnityCommandLineParser::parsePixelsValue(const QString &str) |
3638 | |
3639 | === modified file 'src/UnityCommandLineParser.h' |
3640 | --- src/UnityCommandLineParser.h 2017-04-05 11:48:53 +0000 |
3641 | +++ src/UnityCommandLineParser.h 2017-04-05 11:48:54 +0000 |
3642 | @@ -37,6 +37,8 @@ |
3643 | QString deviceName() const { return m_deviceName; } |
3644 | QString mode() const { return m_mode; } |
3645 | |
3646 | + QString qmlfie() const { return m_qmlfile; } |
3647 | + |
3648 | protected: |
3649 | int parsePixelsValue(const QString &str); |
3650 | static float getenvFloat(const char* name, float defaultValue); |
3651 | @@ -55,6 +57,7 @@ |
3652 | bool m_hasFullscreen; |
3653 | QString m_deviceName; |
3654 | QString m_mode; |
3655 | + QString m_qmlfile; |
3656 | }; |
3657 | |
3658 | #endif // UNITY_COMMAND_LINE_PARSER_H |
3659 | |
3660 | === added file 'src/WindowManagementPolicy.cpp' |
3661 | --- src/WindowManagementPolicy.cpp 1970-01-01 00:00:00 +0000 |
3662 | +++ src/WindowManagementPolicy.cpp 2017-04-05 11:48:54 +0000 |
3663 | @@ -0,0 +1,69 @@ |
3664 | +/* |
3665 | + * Copyright (C) 2017 Canonical, Ltd. |
3666 | + * |
3667 | + * This program is free software; you can redistribute it and/or modify |
3668 | + * it under the terms of the GNU General Public License as published by |
3669 | + * the Free Software Foundation; version 3. |
3670 | + * |
3671 | + * This program is distributed in the hope that it will be useful, |
3672 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3673 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3674 | + * GNU General Public License for more details. |
3675 | + * |
3676 | + * You should have received a copy of the GNU General Public License |
3677 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3678 | + */ |
3679 | + |
3680 | +#include "WindowManagementPolicy.h" |
3681 | + |
3682 | +WindowManagementPolicy::WindowManagementPolicy(const miral::WindowManagerTools &tools, std::shared_ptr<qtmir::WindowManagementPolicyPrivate> dd) |
3683 | + : qtmir::WindowManagementPolicy(tools, dd) |
3684 | + , m_dummyWorkspace(this->tools.create_workspace()) |
3685 | +{ |
3686 | + wmPolicyInterface = this; |
3687 | + |
3688 | + // we must always have a active workspace. |
3689 | + m_activeWorkspace = m_dummyWorkspace; |
3690 | +} |
3691 | + |
3692 | +void WindowManagementPolicy::advise_new_window(miral::WindowInfo const& window_info) |
3693 | +{ |
3694 | + qtmir::WindowManagementPolicy::advise_new_window(window_info); |
3695 | + |
3696 | + auto const parent = window_info.parent(); |
3697 | + |
3698 | + auto activeWorkspace = m_activeWorkspace.lock(); |
3699 | + if (!parent && activeWorkspace) { |
3700 | + tools.add_tree_to_workspace(window_info.window(), activeWorkspace); |
3701 | + } |
3702 | +} |
3703 | + |
3704 | +std::shared_ptr<miral::Workspace> WindowManagementPolicy::createWorkspace() |
3705 | +{ |
3706 | + auto workspace = tools.create_workspace(); |
3707 | + m_workspaces.insert(workspace); |
3708 | + |
3709 | + if (m_activeWorkspace.lock() == m_dummyWorkspace) { |
3710 | + tools.move_workspace_content_to_workspace(workspace, m_dummyWorkspace); |
3711 | + m_activeWorkspace = workspace; |
3712 | + } |
3713 | + return workspace; |
3714 | +} |
3715 | + |
3716 | +void WindowManagementPolicy::releaseWorkspace(const std::shared_ptr<miral::Workspace> &workspace) |
3717 | +{ |
3718 | + auto iter = m_workspaces.find(workspace); |
3719 | + if (iter != m_workspaces.end()) m_workspaces.erase(iter); |
3720 | + |
3721 | + if (m_workspaces.size() == 0) { |
3722 | + m_activeWorkspace = m_dummyWorkspace; |
3723 | + tools.move_workspace_content_to_workspace(m_dummyWorkspace, workspace); |
3724 | + } |
3725 | +} |
3726 | + |
3727 | +void WindowManagementPolicy::setActiveWorkspace(const std::shared_ptr<miral::Workspace> &workspace) |
3728 | +{ |
3729 | + if (m_activeWorkspace.lock() == workspace) |
3730 | + return; |
3731 | + m_activeWorkspace = workspace ? workspace : m_dummyWorkspace; |
3732 | +} |
3733 | |
3734 | === added file 'src/WindowManagementPolicy.h' |
3735 | --- src/WindowManagementPolicy.h 1970-01-01 00:00:00 +0000 |
3736 | +++ src/WindowManagementPolicy.h 2017-04-05 11:48:54 +0000 |
3737 | @@ -0,0 +1,47 @@ |
3738 | +/* |
3739 | + * Copyright (C) 2017 Canonical, Ltd. |
3740 | + * |
3741 | + * This program is free software; you can redistribute it and/or modify |
3742 | + * it under the terms of the GNU General Public License as published by |
3743 | + * the Free Software Foundation; version 3. |
3744 | + * |
3745 | + * This program is distributed in the hope that it will be useful, |
3746 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3747 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3748 | + * GNU General Public License for more details. |
3749 | + * |
3750 | + * You should have received a copy of the GNU General Public License |
3751 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3752 | + */ |
3753 | + |
3754 | +#ifndef UNITY_WINDOWMANAGEMENTPOLICY_H |
3755 | +#define UNITY_WINDOWMANAGEMENTPOLICY_H |
3756 | + |
3757 | +#include <qtmir/windowmanagementpolicy.h> |
3758 | +#include "wmpolicyinterface.h" |
3759 | + |
3760 | +#include <unordered_set> |
3761 | + |
3762 | +class Q_DECL_EXPORT WindowManagementPolicy : public qtmir::WindowManagementPolicy, |
3763 | + public WMPolicyInterface |
3764 | +{ |
3765 | +public: |
3766 | + WindowManagementPolicy(const miral::WindowManagerTools &tools, std::shared_ptr<qtmir::WindowManagementPolicyPrivate> dd); |
3767 | + |
3768 | + void advise_new_window(miral::WindowInfo const& window_info) override; |
3769 | + |
3770 | + // From WMPolicyInterface |
3771 | + std::shared_ptr<miral::Workspace> createWorkspace() override; |
3772 | + |
3773 | + void releaseWorkspace(const std::shared_ptr<miral::Workspace> &workspace) override; |
3774 | + |
3775 | + void setActiveWorkspace(const std::shared_ptr<miral::Workspace> &workspace) override; |
3776 | + |
3777 | +private: |
3778 | + std::weak_ptr<miral::Workspace> m_activeWorkspace; |
3779 | + |
3780 | + std::unordered_set<std::shared_ptr<miral::Workspace>> m_workspaces; |
3781 | + const std::shared_ptr<miral::Workspace> m_dummyWorkspace; |
3782 | +}; |
3783 | + |
3784 | +#endif // UNITY_WINDOWMANAGEMENTPOLICY_H |
3785 | |
3786 | === modified file 'src/libunity8-private/CMakeLists.txt' |
3787 | --- src/libunity8-private/CMakeLists.txt 2014-10-09 14:53:00 +0000 |
3788 | +++ src/libunity8-private/CMakeLists.txt 2017-04-05 11:48:54 +0000 |
3789 | @@ -8,6 +8,7 @@ |
3790 | abstractdbusservicemonitor.cpp |
3791 | unitydbusobject.cpp |
3792 | unitydbusvirtualobject.cpp |
3793 | + wmpolicyinterface.cpp |
3794 | ) |
3795 | |
3796 | add_library(${LIB_NAME} SHARED |
3797 | |
3798 | === added file 'src/libunity8-private/wmpolicyinterface.cpp' |
3799 | --- src/libunity8-private/wmpolicyinterface.cpp 1970-01-01 00:00:00 +0000 |
3800 | +++ src/libunity8-private/wmpolicyinterface.cpp 2017-04-05 11:48:54 +0000 |
3801 | @@ -0,0 +1,24 @@ |
3802 | +/* |
3803 | + * Copyright (C) 2017 Canonical, Ltd. |
3804 | + * |
3805 | + * This program is free software; you can redistribute it and/or modify |
3806 | + * it under the terms of the GNU General Public License as published by |
3807 | + * the Free Software Foundation; version 3. |
3808 | + * |
3809 | + * This program is distributed in the hope that it will be useful, |
3810 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3811 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3812 | + * GNU General Public License for more details. |
3813 | + * |
3814 | + * You should have received a copy of the GNU General Public License |
3815 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3816 | + */ |
3817 | + |
3818 | +#include "wmpolicyinterface.h" |
3819 | + |
3820 | +WMPolicyInterface* wmPolicyInterface = nullptr; |
3821 | + |
3822 | +WMPolicyInterface *WMPolicyInterface::instance() |
3823 | +{ |
3824 | + return wmPolicyInterface; |
3825 | +} |
3826 | |
3827 | === added file 'src/libunity8-private/wmpolicyinterface.h' |
3828 | --- src/libunity8-private/wmpolicyinterface.h 1970-01-01 00:00:00 +0000 |
3829 | +++ src/libunity8-private/wmpolicyinterface.h 2017-04-05 11:48:54 +0000 |
3830 | @@ -0,0 +1,46 @@ |
3831 | +/* |
3832 | + * Copyright (C) 2017 Canonical, Ltd. |
3833 | + * |
3834 | + * This program is free software; you can redistribute it and/or modify |
3835 | + * it under the terms of the GNU General Public License as published by |
3836 | + * the Free Software Foundation; version 3. |
3837 | + * |
3838 | + * This program is distributed in the hope that it will be useful, |
3839 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3840 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3841 | + * GNU General Public License for more details. |
3842 | + * |
3843 | + * You should have received a copy of the GNU General Public License |
3844 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3845 | + */ |
3846 | + |
3847 | +#ifndef WMPOLICYINTERFACE_H |
3848 | +#define WMPOLICYINTERFACE_H |
3849 | + |
3850 | +#include <memory> |
3851 | +#include <functional> |
3852 | + |
3853 | +#include <qglobal.h> |
3854 | + |
3855 | +namespace miral { |
3856 | +class Workspace; |
3857 | +class Window; |
3858 | +} |
3859 | + |
3860 | +class Q_DECL_EXPORT WMPolicyInterface |
3861 | +{ |
3862 | +public: |
3863 | + virtual ~WMPolicyInterface() {} |
3864 | + |
3865 | + static WMPolicyInterface *instance(); |
3866 | + |
3867 | + virtual std::shared_ptr<miral::Workspace> createWorkspace() = 0; |
3868 | + |
3869 | + virtual void releaseWorkspace(const std::shared_ptr<miral::Workspace> &workspace) = 0; |
3870 | + |
3871 | + virtual void setActiveWorkspace(const std::shared_ptr<miral::Workspace> &workspace) = 0; |
3872 | +}; |
3873 | + |
3874 | +extern Q_DECL_EXPORT WMPolicyInterface* wmPolicyInterface; |
3875 | + |
3876 | +#endif // WMPOLICYINTERFACE_H |
3877 | |
3878 | === modified file 'src/main.cpp' |
3879 | --- src/main.cpp 2016-11-28 13:46:55 +0000 |
3880 | +++ src/main.cpp 2017-04-05 11:48:54 +0000 |
3881 | @@ -15,9 +15,10 @@ |
3882 | */ |
3883 | |
3884 | // local |
3885 | -#include "ShellApplication.h" |
3886 | +#include "UnityApplication.h" |
3887 | #include "qmldebuggerutils.h" |
3888 | #include "UnixSignalHandler.h" |
3889 | +#include <paths.h> |
3890 | |
3891 | #include <QTranslator> |
3892 | #include <QLibraryInfo> |
3893 | @@ -27,17 +28,12 @@ |
3894 | { |
3895 | qSetMessagePattern("[%{time yyyy-MM-dd:hh:mm:ss.zzz}] %{if-category}%{category}: %{endif}%{message}"); |
3896 | |
3897 | - bool isMirServer = qgetenv("QT_QPA_PLATFORM") == "mirserver"; |
3898 | - if (!isMirServer && qgetenv("QT_QPA_PLATFORM") == "ubuntumirclient") { |
3899 | - setenv("QT_QPA_PLATFORM", "mirserver", 1 /* overwrite */); |
3900 | - isMirServer = true; |
3901 | - } |
3902 | - |
3903 | if (enableQmlDebugger(argc, argv)) { |
3904 | QQmlDebuggingEnabler qQmlEnableDebuggingHelper(true); |
3905 | } |
3906 | |
3907 | - ShellApplication *application = new ShellApplication(argc, (char**)argv, isMirServer); |
3908 | + auto *application = new UnityApplication(argc, |
3909 | + (char**)argv); |
3910 | |
3911 | UnixSignalHandler signalHandler([]{ |
3912 | QGuiApplication::exit(0); |
3913 | |
3914 | === modified file 'tests/CMakeLists.txt' |
3915 | --- tests/CMakeLists.txt 2017-03-15 18:57:52 +0000 |
3916 | +++ tests/CMakeLists.txt 2017-04-05 11:48:54 +0000 |
3917 | @@ -47,6 +47,7 @@ |
3918 | list(APPEND ld_paths |
3919 | ${UNITY_MOCKPATH}/liblightdm |
3920 | ${UNITY_MOCKPATH}/libusermetrics |
3921 | + ${UNITY_MOCKPATH}/WindowManager |
3922 | ) |
3923 | |
3924 | string(REPLACE ";" ":" ld_library_path "${ld_paths}") |
3925 | |
3926 | === modified file 'tests/mocks/CMakeLists.txt' |
3927 | --- tests/mocks/CMakeLists.txt 2017-01-18 00:25:13 +0000 |
3928 | +++ tests/mocks/CMakeLists.txt 2017-04-05 11:48:54 +0000 |
3929 | @@ -43,6 +43,7 @@ |
3930 | add_subdirectory(Ubuntu) |
3931 | add_subdirectory(Unity) |
3932 | add_subdirectory(QtMultimedia) |
3933 | +add_subdirectory(WindowManager) |
3934 | add_subdirectory(Wizard) |
3935 | add_subdirectory(Utils) |
3936 | add_subdirectory(UInput) |
3937 | |
3938 | === modified file 'tests/mocks/Unity/Application/CMakeLists.txt' |
3939 | --- tests/mocks/Unity/Application/CMakeLists.txt 2016-12-20 15:50:41 +0000 |
3940 | +++ tests/mocks/Unity/Application/CMakeLists.txt 2017-04-05 11:48:54 +0000 |
3941 | @@ -1,3 +1,12 @@ |
3942 | +pkg_check_modules(MIRTEST mirtest>=0.26 REQUIRED) |
3943 | + |
3944 | +include_directories( |
3945 | + SYSTEM |
3946 | + ${MIRTEST_INCLUDE_DIRS} |
3947 | + ${MIRAL_INCLUDE_DIRS} |
3948 | + ${libunity8-private_SOURCE_DIR} |
3949 | +) |
3950 | + |
3951 | set(FakeUnityApplicationQml_SOURCES |
3952 | plugin.cpp |
3953 | ApplicationInfo.cpp |
3954 | @@ -19,11 +28,27 @@ |
3955 | resources/surfaces.qrc |
3956 | ) |
3957 | |
3958 | -add_library(FakeUnityApplicationQml MODULE ${FakeUnityApplicationQml_SOURCES}) |
3959 | +add_library(FakeUnityApplicationQml MODULE |
3960 | + ${FakeUnityApplicationQml_SOURCES} |
3961 | +) |
3962 | + |
3963 | +#add_dependencies(FakeUnityApplicationQml windowmanagementpolicy) |
3964 | + |
3965 | +target_link_libraries(FakeUnityApplicationQml |
3966 | + ${MIRTEST_LDFLAGS} |
3967 | + ${MIRAL_LDFLAGS} |
3968 | + mockwindowmanagmentpolicy |
3969 | +) |
3970 | |
3971 | add_library(NonMirUnityApplicationQml MODULE ${FakeUnityApplicationQml_SOURCES}) |
3972 | set_target_properties(NonMirUnityApplicationQml PROPERTIES OUTPUT_NAME FakeUnityApplicationQml) |
3973 | |
3974 | +target_link_libraries(NonMirUnityApplicationQml |
3975 | + ${MIRTEST_LDFLAGS} |
3976 | + ${MIRAL_LDFLAGS} |
3977 | + mockwindowmanagmentpolicy |
3978 | +) |
3979 | + |
3980 | qt5_use_modules(FakeUnityApplicationQml Core Quick DBus) |
3981 | qt5_use_modules(NonMirUnityApplicationQml Core Quick DBus) |
3982 | |
3983 | |
3984 | === modified file 'tests/mocks/Unity/Application/SurfaceManager.cpp' |
3985 | --- tests/mocks/Unity/Application/SurfaceManager.cpp 2017-04-05 11:48:53 +0000 |
3986 | +++ tests/mocks/Unity/Application/SurfaceManager.cpp 2017-04-05 11:48:54 +0000 |
3987 | @@ -18,8 +18,10 @@ |
3988 | |
3989 | #include "ApplicationInfo.h" |
3990 | #include "VirtualKeyboard.h" |
3991 | +#include "../../WindowManager/WindowManagementPolicy.h" |
3992 | |
3993 | #include <paths.h> |
3994 | +#include <mirtest/mir/test/doubles/stub_surface.h> |
3995 | |
3996 | #define SURFACEMANAGER_DEBUG 1 |
3997 | |
3998 | @@ -31,6 +33,12 @@ |
3999 | |
4000 | namespace unityapi = unity::shell::application; |
4001 | |
4002 | +uint qHash(const WindowWrapper &key, uint) |
4003 | +{ |
4004 | + std::shared_ptr<mir::scene::Surface> surface = key.window; |
4005 | + return (quintptr)surface.get(); |
4006 | +} |
4007 | + |
4008 | SurfaceManager *SurfaceManager::m_instance = nullptr; |
4009 | |
4010 | SurfaceManager *SurfaceManager::instance() |
4011 | @@ -44,20 +52,63 @@ |
4012 | |
4013 | Q_ASSERT(m_instance == nullptr); |
4014 | m_instance = this; |
4015 | + |
4016 | + connect(WindowManagementPolicy::instance(), &WindowManagementPolicy::windowAdded, |
4017 | + this, [this](const miral::Window& window) { |
4018 | + Q_EMIT surfaceCreated(surfaceFor(window)); |
4019 | + }); |
4020 | + |
4021 | + connect(WindowManagementPolicy::instance(), &WindowManagementPolicy::windowsAddedToWorkspace, |
4022 | + this, [this](const std::shared_ptr<miral::Workspace> &workspace, const std::vector<miral::Window> &windows) { |
4023 | + Q_EMIT surfacesAddedToWorkspace(workspace, surfacesFor(windows)); |
4024 | + }); |
4025 | + |
4026 | + connect(WindowManagementPolicy::instance(), &WindowManagementPolicy::windowsAboutToBeRemovedFromWorkspace, |
4027 | + this, [this](const std::shared_ptr<miral::Workspace> &workspace, const std::vector<miral::Window> &windows) { |
4028 | + Q_EMIT surfacesAboutToBeRemovedFromWorkspace(workspace, surfacesFor(windows)); |
4029 | + }); |
4030 | } |
4031 | |
4032 | SurfaceManager::~SurfaceManager() |
4033 | { |
4034 | DEBUG_MSG(""); |
4035 | |
4036 | - if (m_virtualKeyboard) { |
4037 | - m_virtualKeyboard->setLive(false); |
4038 | - } |
4039 | + releaseInputMethodSurface(); |
4040 | |
4041 | Q_ASSERT(m_instance == this); |
4042 | m_instance = nullptr; |
4043 | } |
4044 | |
4045 | +MirSurfaceInterface *SurfaceManager::surfaceFor(const miral::Window& window) const |
4046 | +{ |
4047 | + auto iter = m_windowToSurface.find({window}); |
4048 | + if (iter != m_windowToSurface.end()) { |
4049 | + return *iter; |
4050 | + } |
4051 | + return nullptr; |
4052 | +} |
4053 | + |
4054 | +QVector<MirSurfaceInterface*> SurfaceManager::surfacesFor(const std::vector<miral::Window> &windows) const |
4055 | +{ |
4056 | + QVector<unityapi::MirSurfaceInterface*> surfaces; |
4057 | + for (size_t i = 0; i < windows.size(); i++) { |
4058 | + auto mirSurface = surfaceFor(windows[i]); |
4059 | + if (mirSurface) { |
4060 | + surfaces.push_back(mirSurface); |
4061 | + } |
4062 | + } |
4063 | + return surfaces; |
4064 | +} |
4065 | + |
4066 | +miral::Window SurfaceManager::windowFor(MirSurfaceInterface *surface) const |
4067 | +{ |
4068 | + auto iter = m_surfaceToWindow.find(surface); |
4069 | + if (iter != m_surfaceToWindow.end()) { |
4070 | + return iter->window; |
4071 | + } |
4072 | + return miral::Window(); |
4073 | +} |
4074 | + |
4075 | MirSurface *SurfaceManager::createSurface(const QString& name, |
4076 | Mir::Type type, |
4077 | Mir::State state, |
4078 | @@ -75,7 +126,12 @@ |
4079 | |
4080 | void SurfaceManager::registerSurface(MirSurface *surface) |
4081 | { |
4082 | + auto fakeSurface = std::make_shared<mir::test::doubles::StubSurface>(); |
4083 | + WindowWrapper window{miral::Window(nullptr, fakeSurface), fakeSurface}; |
4084 | + |
4085 | m_surfaces.prepend(surface); |
4086 | + m_windowToSurface.insert(window, surface); |
4087 | + m_surfaceToWindow.insert(surface, window); |
4088 | |
4089 | if (!surface->parentSurface()) { |
4090 | surface->setMinimumWidth(m_newSurfaceMinimumWidth); |
4091 | @@ -90,16 +146,24 @@ |
4092 | this->onStateRequested(surface, state); |
4093 | }); |
4094 | |
4095 | - const QString persistentId = surface->persistentId(); |
4096 | connect(surface, &QObject::destroyed, this, [=]() { |
4097 | - this->onSurfaceDestroyed(surface, persistentId); |
4098 | + auto iter = m_surfaceToWindow.find(surface); |
4099 | + if (iter != m_surfaceToWindow.end()) { |
4100 | + WindowWrapper key = m_surfaceToWindow.value(surface); |
4101 | + WindowManagementPolicy::instance()->removeWindow(key.window); |
4102 | + this->onSurfaceDestroyed(surface); |
4103 | + } |
4104 | }); |
4105 | - |
4106 | } |
4107 | |
4108 | void SurfaceManager::notifySurfaceCreated(unityapi::MirSurfaceInterface *surface) |
4109 | { |
4110 | - Q_EMIT surfaceCreated(surface); |
4111 | + if (Q_UNLIKELY(!m_surfaceToWindow.contains(surface))) { |
4112 | + Q_EMIT surfaceCreated(surface); |
4113 | + return; |
4114 | + } |
4115 | + |
4116 | + WindowManagementPolicy::instance()->addWindow(m_surfaceToWindow[surface].window); |
4117 | } |
4118 | |
4119 | void SurfaceManager::setNewSurfaceMinimumWidth(int value) |
4120 | @@ -209,6 +273,32 @@ |
4121 | DEBUG_MSG("("<<surface<<") ended"); |
4122 | } |
4123 | |
4124 | +void SurfaceManager::forEachSurfaceInWorkspace(const std::shared_ptr<miral::Workspace> &workspace, |
4125 | + const std::function<void(unity::shell::application::MirSurfaceInterface*)> &callback) |
4126 | +{ |
4127 | + WindowManagementPolicy::instance()->forEachWindowInWorkspace(workspace, [&](const miral::Window &window) { |
4128 | + auto surface = surfaceFor(window); |
4129 | + if (surface) { |
4130 | + callback(surface); |
4131 | + } |
4132 | + }); |
4133 | +} |
4134 | + |
4135 | +void SurfaceManager::moveSurfaceToWorkspace(unity::shell::application::MirSurfaceInterface* surface, |
4136 | + const std::shared_ptr<miral::Workspace> &workspace) |
4137 | +{ |
4138 | + auto window = windowFor(surface); |
4139 | + if (window) { |
4140 | + WindowManagementPolicy::instance()->moveWindowToWorkspace(window, workspace); |
4141 | + } |
4142 | +} |
4143 | + |
4144 | +void SurfaceManager::moveWorkspaceContentToWorkspace(const std::shared_ptr<miral::Workspace> &to, |
4145 | + const std::shared_ptr<miral::Workspace> &from) |
4146 | +{ |
4147 | + WindowManagementPolicy::instance()->moveWorkspaceContentToWorkspace(to, from); |
4148 | +} |
4149 | + |
4150 | void SurfaceManager::onStateRequested(MirSurface *surface, Mir::State state) |
4151 | { |
4152 | DEBUG_MSG("("<<surface<<","<<state<<") started"); |
4153 | @@ -230,9 +320,17 @@ |
4154 | DEBUG_MSG("("<<surface<<","<<state<<") ended"); |
4155 | } |
4156 | |
4157 | -void SurfaceManager::onSurfaceDestroyed(MirSurface *surface, const QString& persistentId) |
4158 | +void SurfaceManager::onSurfaceDestroyed(MirSurface *surface) |
4159 | { |
4160 | m_surfaces.removeAll(surface); |
4161 | + |
4162 | + auto iter = m_surfaceToWindow.find(surface); |
4163 | + if (iter != m_surfaceToWindow.end()) { |
4164 | + WindowWrapper key = iter.value(); |
4165 | + m_windowToSurface.remove(key); |
4166 | + m_surfaceToWindow.erase(iter); |
4167 | + } |
4168 | + |
4169 | if (m_focusedSurface == surface) { |
4170 | m_focusedSurface = nullptr; |
4171 | |
4172 | @@ -244,7 +342,7 @@ |
4173 | m_underModification = false; |
4174 | Q_EMIT modificationsEnded(); |
4175 | } |
4176 | - Q_EMIT surfaceDestroyed(persistentId); |
4177 | + Q_EMIT surfaceRemoved(surface); |
4178 | } |
4179 | |
4180 | void SurfaceManager::focusFirstAvailableSurface() |
4181 | @@ -276,6 +374,15 @@ |
4182 | if (!m_virtualKeyboard) { |
4183 | m_virtualKeyboard = new VirtualKeyboard; |
4184 | registerSurface(m_virtualKeyboard); |
4185 | - Q_EMIT surfaceCreated(m_virtualKeyboard); |
4186 | + |
4187 | + WindowManagementPolicy::instance()->addWindow(m_surfaceToWindow[m_virtualKeyboard].window); |
4188 | + } |
4189 | +} |
4190 | + |
4191 | +void SurfaceManager::releaseInputMethodSurface() |
4192 | +{ |
4193 | + if (m_virtualKeyboard) { |
4194 | + m_virtualKeyboard->setLive(false); |
4195 | + m_virtualKeyboard = nullptr; |
4196 | } |
4197 | } |
4198 | |
4199 | === modified file 'tests/mocks/Unity/Application/SurfaceManager.h' |
4200 | --- tests/mocks/Unity/Application/SurfaceManager.h 2017-01-26 11:10:01 +0000 |
4201 | +++ tests/mocks/Unity/Application/SurfaceManager.h 2017-04-05 11:48:54 +0000 |
4202 | @@ -20,12 +20,20 @@ |
4203 | #include <QObject> |
4204 | |
4205 | #include <unity/shell/application/SurfaceManagerInterface.h> |
4206 | +#include <miral/window.h> |
4207 | |
4208 | #include "MirSurface.h" |
4209 | #include "VirtualKeyboard.h" |
4210 | |
4211 | class ApplicationInfo; |
4212 | |
4213 | +struct WindowWrapper { |
4214 | + miral::Window window; |
4215 | + std::shared_ptr<mir::scene::Surface> session{nullptr}; // Keeps the window surface alive. |
4216 | + bool operator==(const WindowWrapper& other) const { return window==other.window; } |
4217 | +}; |
4218 | +uint qHash(const WindowWrapper &key, uint seed = 0); |
4219 | + |
4220 | class SurfaceManager : public unity::shell::application::SurfaceManagerInterface |
4221 | { |
4222 | Q_OBJECT |
4223 | @@ -46,6 +54,13 @@ |
4224 | void raise(unity::shell::application::MirSurfaceInterface *surface) override; |
4225 | void activate(unity::shell::application::MirSurfaceInterface *surface) override; |
4226 | |
4227 | + void forEachSurfaceInWorkspace(const std::shared_ptr<miral::Workspace> &workspace, |
4228 | + const std::function<void(unity::shell::application::MirSurfaceInterface*)> &callback) override; |
4229 | + void moveSurfaceToWorkspace(unity::shell::application::MirSurfaceInterface* surface, |
4230 | + const std::shared_ptr<miral::Workspace> &workspace) override; |
4231 | + void moveWorkspaceContentToWorkspace(const std::shared_ptr<miral::Workspace> &to, |
4232 | + const std::shared_ptr<miral::Workspace> &from) override; |
4233 | + |
4234 | Q_INVOKABLE MirSurface* createSurface(const QString& name, |
4235 | Mir::Type type, |
4236 | Mir::State state, |
4237 | @@ -76,10 +91,9 @@ |
4238 | |
4239 | public Q_SLOTS: |
4240 | void createInputMethodSurface(); |
4241 | + void releaseInputMethodSurface(); |
4242 | |
4243 | Q_SIGNALS: |
4244 | - void surfaceDestroyed(const QString& persistentSurfaceId); |
4245 | - |
4246 | void newSurfaceMinimumWidthChanged(int value); |
4247 | void newSurfaceMaximumWidthChanged(int value); |
4248 | void newSurfaceMinimumHeightChanged(int value); |
4249 | @@ -89,12 +103,15 @@ |
4250 | |
4251 | private Q_SLOTS: |
4252 | void onStateRequested(MirSurface *surface, Mir::State state); |
4253 | - void onSurfaceDestroyed(MirSurface *surface, const QString& persistentId); |
4254 | + void onSurfaceDestroyed(MirSurface *surface); |
4255 | |
4256 | private: |
4257 | void doRaise(unity::shell::application::MirSurfaceInterface *surface); |
4258 | void focusFirstAvailableSurface(); |
4259 | void registerSurface(MirSurface *surface); |
4260 | + unity::shell::application::MirSurfaceInterface* surfaceFor(const miral::Window &window) const; |
4261 | + QVector<unity::shell::application::MirSurfaceInterface*> surfacesFor(const std::vector<miral::Window> &windows) const; |
4262 | + miral::Window windowFor(unity::shell::application::MirSurfaceInterface* surface) const; |
4263 | |
4264 | static SurfaceManager *m_instance; |
4265 | |
4266 | @@ -110,6 +127,9 @@ |
4267 | |
4268 | QList<MirSurface*> m_surfaces; |
4269 | |
4270 | + QHash<WindowWrapper, unity::shell::application::MirSurfaceInterface*> m_windowToSurface; |
4271 | + QHash<unity::shell::application::MirSurfaceInterface*, WindowWrapper> m_surfaceToWindow; |
4272 | + |
4273 | VirtualKeyboard *m_virtualKeyboard{nullptr}; |
4274 | }; |
4275 | |
4276 | |
4277 | === modified file 'tests/mocks/Unity/Application/plugin.cpp' |
4278 | --- tests/mocks/Unity/Application/plugin.cpp 2016-12-01 11:38:26 +0000 |
4279 | +++ tests/mocks/Unity/Application/plugin.cpp 2017-04-05 11:48:54 +0000 |
4280 | @@ -38,6 +38,12 @@ |
4281 | { |
4282 | return new MirMock; |
4283 | } |
4284 | + |
4285 | +QObject* surfaceManagerSingleton(QQmlEngine*, QJSEngine*) |
4286 | +{ |
4287 | + return new SurfaceManager; |
4288 | +} |
4289 | + |
4290 | } // anonymous namespace |
4291 | |
4292 | void FakeUnityApplicationQmlPlugin::registerTypes(const char *uri) |
4293 | @@ -59,7 +65,7 @@ |
4294 | |
4295 | qmlRegisterSingletonType<ApplicationManager>(uri, 0, 1, "ApplicationManager", applicationManagerSingleton); |
4296 | qmlRegisterSingletonType<MirMock>(uri, 0, 1, "Mir", mirSingleton); |
4297 | - qmlRegisterType<SurfaceManager>(uri, 0, 1, "SurfaceManager"); |
4298 | + qmlRegisterSingletonType<SurfaceManager>(uri, 0, 1, "SurfaceManager", surfaceManagerSingleton); |
4299 | } |
4300 | |
4301 | void FakeUnityApplicationQmlPlugin::initializeEngine(QQmlEngine *engine, const char *uri) |
4302 | |
4303 | === modified file 'tests/mocks/Unity/CMakeLists.txt' |
4304 | --- tests/mocks/Unity/CMakeLists.txt 2017-01-31 13:35:50 +0000 |
4305 | +++ tests/mocks/Unity/CMakeLists.txt 2017-04-05 11:48:54 +0000 |
4306 | @@ -6,7 +6,6 @@ |
4307 | add_subdirectory(Launcher) |
4308 | add_subdirectory(Notifications) |
4309 | add_subdirectory(DashCommunicator) |
4310 | -add_subdirectory(Screens) |
4311 | add_subdirectory(Platform) |
4312 | |
4313 | pkg_search_module(GOBJECT gobject-2.0 REQUIRED) |
4314 | |
4315 | === removed directory 'tests/mocks/Unity/Screens' |
4316 | === removed file 'tests/mocks/Unity/Screens/CMakeLists.txt' |
4317 | --- tests/mocks/Unity/Screens/CMakeLists.txt 2017-04-05 11:48:53 +0000 |
4318 | +++ tests/mocks/Unity/Screens/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
4319 | @@ -1,15 +0,0 @@ |
4320 | -include_directories( |
4321 | - ${CMAKE_CURRENT_SOURCE_DIR} |
4322 | -) |
4323 | - |
4324 | -set(MockScreens_SOURCES |
4325 | - plugin.cpp |
4326 | - screens.cpp |
4327 | - screenwindow.cpp |
4328 | -) |
4329 | - |
4330 | -add_library(MockScreensPlugin MODULE ${MockScreens_SOURCES}) |
4331 | - |
4332 | -qt5_use_modules(MockScreensPlugin Gui Qml Quick) |
4333 | - |
4334 | -add_unity8_mock(Unity.Screens 0.1 Unity/Screens PREFIX mocks TARGETS MockScreensPlugin) |
4335 | |
4336 | === removed file 'tests/mocks/Unity/Screens/plugin.cpp' |
4337 | --- tests/mocks/Unity/Screens/plugin.cpp 2017-04-05 11:48:53 +0000 |
4338 | +++ tests/mocks/Unity/Screens/plugin.cpp 1970-01-01 00:00:00 +0000 |
4339 | @@ -1,42 +0,0 @@ |
4340 | -/* |
4341 | - * Copyright (C) 2015 Canonical, Ltd. |
4342 | - * |
4343 | - * This program is free software: you can redistribute it and/or modify it under |
4344 | - * the terms of the GNU Lesser General Public License version 3, as published by |
4345 | - * the Free Software Foundation. |
4346 | - * |
4347 | - * This program is distributed in the hope that it will be useful, but WITHOUT |
4348 | - * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
4349 | - * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
4350 | - * Lesser General Public License for more details. |
4351 | - * |
4352 | - * You should have received a copy of the GNU Lesser General Public License |
4353 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4354 | - */ |
4355 | - |
4356 | -#include "plugin.h" |
4357 | -#include "screens.h" |
4358 | -#include "screenwindow.h" |
4359 | - |
4360 | -#include <QScreen> |
4361 | - |
4362 | -namespace { |
4363 | -QObject* screensSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) { |
4364 | - Q_UNUSED(engine); |
4365 | - Q_UNUSED(scriptEngine); |
4366 | - return new Screens(); |
4367 | -} |
4368 | -} |
4369 | - |
4370 | -void UnityScreensPlugin::registerTypes(const char* uri) |
4371 | -{ |
4372 | - Q_ASSERT(QLatin1String(uri) == QLatin1String("Unity.Screens")); |
4373 | - |
4374 | - qRegisterMetaType<QScreen*>("QScreen*"); |
4375 | - qRegisterMetaType<ScreenMode*>("ScreenMode*"); |
4376 | - qmlRegisterUncreatableType<ScreenMode>(uri, 0, 1, "ScreenMode", "ScreenMode is not creatable."); |
4377 | - |
4378 | - qmlRegisterSingletonType<Screens>(uri, 0, 1, "Screens", screensSingleton); |
4379 | - qmlRegisterType<ScreenWindow>(uri, 0, 1, "ScreenWindow"); |
4380 | - qmlRegisterRevision<QWindow,1>(uri, 0, 1); |
4381 | -} |
4382 | |
4383 | === removed file 'tests/mocks/Unity/Screens/plugin.h' |
4384 | --- tests/mocks/Unity/Screens/plugin.h 2016-04-28 12:17:38 +0000 |
4385 | +++ tests/mocks/Unity/Screens/plugin.h 1970-01-01 00:00:00 +0000 |
4386 | @@ -1,25 +0,0 @@ |
4387 | -/* |
4388 | - * Copyright (C) 2015 Canonical, Ltd. |
4389 | - * |
4390 | - * This program is free software: you can redistribute it and/or modify it under |
4391 | - * the terms of the GNU Lesser General Public License version 3, as published by |
4392 | - * the Free Software Foundation. |
4393 | - * |
4394 | - * This program is distributed in the hope that it will be useful, but WITHOUT |
4395 | - * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
4396 | - * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
4397 | - * Lesser General Public License for more details. |
4398 | - * |
4399 | - * You should have received a copy of the GNU Lesser General Public License |
4400 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4401 | - */ |
4402 | - |
4403 | -#include <QQmlExtensionPlugin> |
4404 | -#include <QtQml/qqml.h> |
4405 | - |
4406 | -class UnityScreensPlugin : public QQmlExtensionPlugin { |
4407 | - Q_OBJECT |
4408 | - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") |
4409 | -public: |
4410 | - void registerTypes(const char* uri) override; |
4411 | -}; |
4412 | |
4413 | === removed file 'tests/mocks/Unity/Screens/qmldir' |
4414 | --- tests/mocks/Unity/Screens/qmldir 2015-12-02 13:23:45 +0000 |
4415 | +++ tests/mocks/Unity/Screens/qmldir 1970-01-01 00:00:00 +0000 |
4416 | @@ -1,2 +0,0 @@ |
4417 | -module Unity.Screens |
4418 | -plugin MockScreensPlugin |
4419 | |
4420 | === removed file 'tests/mocks/Unity/Screens/screens.cpp' |
4421 | --- tests/mocks/Unity/Screens/screens.cpp 2017-04-05 11:48:53 +0000 |
4422 | +++ tests/mocks/Unity/Screens/screens.cpp 1970-01-01 00:00:00 +0000 |
4423 | @@ -1,114 +0,0 @@ |
4424 | -/* |
4425 | - * Copyright (C) 2015 Canonical, Ltd. |
4426 | - * |
4427 | - * This program is free software: you can redistribute it and/or modify it under |
4428 | - * the terms of the GNU Lesser General Public License version 3, as published by |
4429 | - * the Free Software Foundation. |
4430 | - * |
4431 | - * This program is distributed in the hope that it will be useful, but WITHOUT |
4432 | - * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
4433 | - * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
4434 | - * Lesser General Public License for more details. |
4435 | - * |
4436 | - * You should have received a copy of the GNU Lesser General Public License |
4437 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4438 | - */ |
4439 | - |
4440 | -#include "screens.h" |
4441 | - |
4442 | -// Qt |
4443 | -#include <QGuiApplication> |
4444 | -#include <QDebug> |
4445 | - |
4446 | -Screens::Screens(QObject *parent) : |
4447 | - QAbstractListModel(parent) |
4448 | -{ |
4449 | - bool ok = false; |
4450 | - int screenCount = qEnvironmentVariableIntValue("UNITY_MOCK_SCREEN_COUNT", &ok); |
4451 | - if (!ok) screenCount = 1; |
4452 | - QPoint lastPoint(0,0); |
4453 | - for (int i = 0; i < screenCount; ++i) { |
4454 | - auto screen = new Screen(); |
4455 | - screen->m_active = i == 0; |
4456 | - screen->m_name = QString("Monitor %1").arg(i); |
4457 | - screen->m_position = QPoint(lastPoint.x(), lastPoint.y()); |
4458 | - screen->m_sizes.append(new ScreenMode(50, QSize(640,480))); |
4459 | - screen->m_sizes.append(new ScreenMode(60, QSize(1280,1024))); |
4460 | - screen->m_sizes.append(new ScreenMode(60, QSize(1440,900))); |
4461 | - screen->m_sizes.append(new ScreenMode(60, QSize(1920,1080))); |
4462 | - screen->m_currentModeIndex = 3; |
4463 | - screen->m_physicalSize = QSize(300,200); |
4464 | - m_screenList.append(screen); |
4465 | - |
4466 | - lastPoint.rx() += screen->m_sizes[screen->m_currentModeIndex]->size.width(); |
4467 | - } |
4468 | -} |
4469 | - |
4470 | -Screens::~Screens() noexcept |
4471 | -{ |
4472 | - qDeleteAll(m_screenList); |
4473 | - m_screenList.clear(); |
4474 | -} |
4475 | - |
4476 | -QHash<int, QByteArray> Screens::roleNames() const |
4477 | -{ |
4478 | - QHash<int, QByteArray> roles; |
4479 | - roles[ScreenRole] = "screen"; |
4480 | - return roles; |
4481 | -} |
4482 | - |
4483 | -QVariant Screens::data(const QModelIndex &index, int role) const |
4484 | -{ |
4485 | - if (!index.isValid() || index.row() >= m_screenList.size()) { |
4486 | - return QVariant(); |
4487 | - } |
4488 | - |
4489 | - switch(role) { |
4490 | - case ScreenRole: |
4491 | - return QVariant::fromValue(m_screenList.at(index.row())); |
4492 | - } |
4493 | - |
4494 | - return QVariant(); |
4495 | -} |
4496 | - |
4497 | -int Screens::rowCount(const QModelIndex &) const |
4498 | -{ |
4499 | - return count(); |
4500 | -} |
4501 | - |
4502 | -int Screens::count() const |
4503 | -{ |
4504 | - return m_screenList.size(); |
4505 | -} |
4506 | - |
4507 | -void Screens::activateScreen(int) |
4508 | -{ |
4509 | - qWarning("Not Implemented"); |
4510 | -} |
4511 | - |
4512 | -Screen::Screen(QObject* parent) |
4513 | - : QObject(parent) |
4514 | -{ |
4515 | -} |
4516 | - |
4517 | -Screen::~Screen() |
4518 | -{ |
4519 | - qDeleteAll(m_sizes); |
4520 | - m_sizes.clear(); |
4521 | -} |
4522 | - |
4523 | -QQmlListProperty<ScreenMode> Screen::availableModes() |
4524 | -{ |
4525 | - return QQmlListProperty<ScreenMode>(this, m_sizes); |
4526 | -} |
4527 | - |
4528 | -Screen *Screen::beginConfiguration() |
4529 | -{ |
4530 | - qWarning("Not Implemented"); |
4531 | - return nullptr; |
4532 | -} |
4533 | - |
4534 | -void Screen::applyConfiguration() |
4535 | -{ |
4536 | - qWarning("Not Implemented"); |
4537 | -} |
4538 | |
4539 | === removed file 'tests/mocks/Unity/Screens/screens.h' |
4540 | --- tests/mocks/Unity/Screens/screens.h 2017-04-05 11:48:53 +0000 |
4541 | +++ tests/mocks/Unity/Screens/screens.h 1970-01-01 00:00:00 +0000 |
4542 | @@ -1,162 +0,0 @@ |
4543 | -/* |
4544 | - * Copyright (C) 2015 Canonical, Ltd. |
4545 | - * |
4546 | - * This program is free software: you can redistribute it and/or modify it under |
4547 | - * the terms of the GNU Lesser General Public License version 3, as published by |
4548 | - * the Free Software Foundation. |
4549 | - * |
4550 | - * This program is distributed in the hope that it will be useful, but WITHOUT |
4551 | - * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
4552 | - * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
4553 | - * Lesser General Public License for more details. |
4554 | - * |
4555 | - * You should have received a copy of the GNU Lesser General Public License |
4556 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4557 | - */ |
4558 | - |
4559 | -#ifndef SCREENS_H |
4560 | -#define SCREENS_H |
4561 | - |
4562 | -#include <QAbstractListModel> |
4563 | -#include <QScreen> |
4564 | -#include <QQmlListProperty> |
4565 | - |
4566 | -class Screen; |
4567 | - |
4568 | -class Screens : public QAbstractListModel |
4569 | -{ |
4570 | - Q_OBJECT |
4571 | - |
4572 | - Q_PROPERTY(int count READ count NOTIFY countChanged) |
4573 | - |
4574 | -public: |
4575 | - enum ItemRoles { |
4576 | - ScreenRole = Qt::UserRole + 1, |
4577 | - OutputTypeRole, |
4578 | - EnabledRole, |
4579 | - NameRole, |
4580 | - ScaleRole, |
4581 | - FormFactorRole, |
4582 | - GeometryRole, |
4583 | - SizesRole |
4584 | - }; |
4585 | - |
4586 | - enum OutputTypes { |
4587 | - Unknown, |
4588 | - VGA, |
4589 | - DVII, |
4590 | - DVID, |
4591 | - DVIA, |
4592 | - Composite, |
4593 | - SVideo, |
4594 | - LVDS, |
4595 | - Component, |
4596 | - NinePinDIN, |
4597 | - DisplayPort, |
4598 | - HDMIA, |
4599 | - HDMIB, |
4600 | - TV, |
4601 | - EDP |
4602 | - }; |
4603 | - Q_ENUM(OutputTypes) |
4604 | - |
4605 | - enum FormFactor { |
4606 | - FormFactorUnknown, |
4607 | - FormFactorPhone, |
4608 | - FormFactorTablet, |
4609 | - FormFactorMonitor, |
4610 | - FormFactorTV, |
4611 | - FormFactorProjector, |
4612 | - }; |
4613 | - |
4614 | - explicit Screens(QObject *parent = 0); |
4615 | - virtual ~Screens() noexcept; |
4616 | - |
4617 | - /* QAbstractItemModel */ |
4618 | - QHash<int, QByteArray> roleNames() const override; |
4619 | - QVariant data(const QModelIndex &index, int role = ScreenRole) const override; |
4620 | - int rowCount(const QModelIndex &parent = QModelIndex()) const override; |
4621 | - |
4622 | - int count() const; |
4623 | - |
4624 | -public Q_SLOTS: |
4625 | - void activateScreen(int index); |
4626 | - |
4627 | -Q_SIGNALS: |
4628 | - void countChanged(); |
4629 | - void screenAdded(QScreen *screen); |
4630 | - void screenRemoved(QScreen *screen); |
4631 | - |
4632 | -private: |
4633 | - QList<Screen *> m_screenList; |
4634 | -}; |
4635 | - |
4636 | -class ScreenMode : public QObject |
4637 | -{ |
4638 | - Q_OBJECT |
4639 | - Q_PROPERTY(qreal refreshRate MEMBER refreshRate CONSTANT) |
4640 | - Q_PROPERTY(QSize size MEMBER size CONSTANT) |
4641 | -public: |
4642 | - ScreenMode() {} |
4643 | - ScreenMode(qreal refreshRate, QSize size):refreshRate(refreshRate),size(size) {} |
4644 | - ScreenMode(const ScreenMode& other) |
4645 | - : QObject(nullptr), |
4646 | - refreshRate{other.refreshRate},size{other.size} |
4647 | - {} |
4648 | - |
4649 | - qreal refreshRate; |
4650 | - QSize size; |
4651 | -}; |
4652 | - |
4653 | -class Screen : public QObject |
4654 | -{ |
4655 | - Q_OBJECT |
4656 | - |
4657 | - Q_PROPERTY(bool active MEMBER m_active NOTIFY activeChanged) |
4658 | - |
4659 | - Q_PROPERTY(bool used MEMBER m_used NOTIFY usedChanged) |
4660 | - Q_PROPERTY(QString name MEMBER m_name NOTIFY nameChanged) |
4661 | - Q_PROPERTY(Screens::OutputTypes outputType MEMBER m_outputType NOTIFY outputTypeChanged) |
4662 | - Q_PROPERTY(float scale MEMBER m_scale NOTIFY scaleChanged) |
4663 | - Q_PROPERTY(Screens::FormFactor formFactor MEMBER m_formFactor NOTIFY formFactorChanged) |
4664 | - Q_PROPERTY(QPoint position MEMBER m_position NOTIFY positionChanged) |
4665 | - Q_PROPERTY(uint currentModeIndex MEMBER m_currentModeIndex NOTIFY currentModeIndexChanged) |
4666 | - Q_PROPERTY(QQmlListProperty<ScreenMode> availableModes READ availableModes NOTIFY availableModesChanged) |
4667 | - Q_PROPERTY(QSizeF physicalSize MEMBER m_physicalSize NOTIFY physicalSizeChanged) |
4668 | -public: |
4669 | - Screen(QObject* parent = 0); |
4670 | - ~Screen(); |
4671 | - |
4672 | - QQmlListProperty<ScreenMode> availableModes(); |
4673 | - |
4674 | - Q_INVOKABLE Screen* beginConfiguration(); |
4675 | - Q_INVOKABLE void applyConfiguration(); |
4676 | - |
4677 | -Q_SIGNALS: |
4678 | - void activeChanged(); |
4679 | - void usedChanged(); |
4680 | - void nameChanged(); |
4681 | - void outputTypeChanged(); |
4682 | - void scaleChanged(); |
4683 | - void formFactorChanged(); |
4684 | - void positionChanged(); |
4685 | - void currentModeIndexChanged(); |
4686 | - void availableModesChanged(); |
4687 | - void physicalSizeChanged(); |
4688 | - |
4689 | -public: |
4690 | - bool m_active{false}; |
4691 | - bool m_used{true}; |
4692 | - QString m_name; |
4693 | - Screens::OutputTypes m_outputType{Screens::Unknown}; |
4694 | - float m_scale{1.0}; |
4695 | - Screens::FormFactor m_formFactor{Screens::FormFactorMonitor}; |
4696 | - QPoint m_position; |
4697 | - uint m_currentModeIndex{0}; |
4698 | - QList<ScreenMode*> m_sizes; |
4699 | - QSizeF m_physicalSize; |
4700 | -}; |
4701 | - |
4702 | -Q_DECLARE_METATYPE(ScreenMode) |
4703 | - |
4704 | -#endif // SCREENS_H |
4705 | |
4706 | === removed file 'tests/mocks/Unity/Screens/screenwindow.cpp' |
4707 | --- tests/mocks/Unity/Screens/screenwindow.cpp 2017-04-05 11:48:53 +0000 |
4708 | +++ tests/mocks/Unity/Screens/screenwindow.cpp 1970-01-01 00:00:00 +0000 |
4709 | @@ -1,35 +0,0 @@ |
4710 | -/* |
4711 | - * Copyright (C) 2016 Canonical, Ltd. |
4712 | - * |
4713 | - * This program is free software: you can redistribute it and/or modify it under |
4714 | - * the terms of the GNU Lesser General Public License version 3, as published by |
4715 | - * the Free Software Foundation. |
4716 | - * |
4717 | - * This program is distributed in the hope that it will be useful, but WITHOUT |
4718 | - * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
4719 | - * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
4720 | - * Lesser General Public License for more details. |
4721 | - * |
4722 | - * You should have received a copy of the GNU Lesser General Public License |
4723 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4724 | - */ |
4725 | - |
4726 | -#include "screenwindow.h" |
4727 | - |
4728 | -ScreenWindow::ScreenWindow(QWindow *parent) |
4729 | - : QQuickWindow(parent) |
4730 | -{ |
4731 | -} |
4732 | - |
4733 | -Screen *ScreenWindow::screenWrapper() const |
4734 | -{ |
4735 | - return m_screen.data(); |
4736 | -} |
4737 | - |
4738 | -void ScreenWindow::setScreenWrapper(Screen *screen) |
4739 | -{ |
4740 | - if (m_screen != screen) { |
4741 | - m_screen = screen; |
4742 | - Q_EMIT screenWrapperChanged(); |
4743 | - } |
4744 | -} |
4745 | |
4746 | === removed file 'tests/mocks/Unity/Screens/screenwindow.h' |
4747 | --- tests/mocks/Unity/Screens/screenwindow.h 2017-04-05 11:48:53 +0000 |
4748 | +++ tests/mocks/Unity/Screens/screenwindow.h 1970-01-01 00:00:00 +0000 |
4749 | @@ -1,42 +0,0 @@ |
4750 | -/* |
4751 | - * Copyright (C) 2016 Canonical, Ltd. |
4752 | - * |
4753 | - * This program is free software: you can redistribute it and/or modify it under |
4754 | - * the terms of the GNU Lesser General Public License version 3, as published by |
4755 | - * the Free Software Foundation. |
4756 | - * |
4757 | - * This program is distributed in the hope that it will be useful, but WITHOUT |
4758 | - * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
4759 | - * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
4760 | - * Lesser General Public License for more details. |
4761 | - * |
4762 | - * You should have received a copy of the GNU Lesser General Public License |
4763 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4764 | - */ |
4765 | - |
4766 | -#ifndef SCREENWINDOW_H |
4767 | -#define SCREENWINDOW_H |
4768 | - |
4769 | -#include <QQuickWindow> |
4770 | -#include <QPointer> |
4771 | - |
4772 | -#include "screens.h" |
4773 | - |
4774 | -class ScreenWindow : public QQuickWindow |
4775 | -{ |
4776 | - Q_OBJECT |
4777 | - Q_PROPERTY(Screen *screen READ screenWrapper WRITE setScreenWrapper NOTIFY screenWrapperChanged) |
4778 | -public: |
4779 | - ScreenWindow(QWindow *parent = 0); |
4780 | - |
4781 | - Screen *screenWrapper() const; |
4782 | - void setScreenWrapper(Screen *screen); |
4783 | - |
4784 | -Q_SIGNALS: |
4785 | - void screenWrapperChanged(); |
4786 | - |
4787 | -private: |
4788 | - QPointer<Screen> m_screen; |
4789 | -}; |
4790 | - |
4791 | -#endif // SCREENWINDOW_H |
4792 | |
4793 | === added directory 'tests/mocks/WindowManager' |
4794 | === added file 'tests/mocks/WindowManager/CMakeLists.txt' |
4795 | --- tests/mocks/WindowManager/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
4796 | +++ tests/mocks/WindowManager/CMakeLists.txt 2017-04-05 11:48:54 +0000 |
4797 | @@ -0,0 +1,61 @@ |
4798 | +include_directories( |
4799 | + SYSTEM |
4800 | + ${QTMIRSERVER_INCLUDE_DIRS} |
4801 | + ${Qt5Gui_PRIVATE_INCLUDE_DIRS} |
4802 | +) |
4803 | + |
4804 | +include_directories( |
4805 | + ${CMAKE_CURRENT_SOURCE_DIR} |
4806 | + ${CMAKE_CURRENT_BINARY_DIR} |
4807 | + ${CMAKE_SOURCE_DIR}/plugins/WindowManager |
4808 | + ${libunity8-private_SOURCE_DIR} |
4809 | +) |
4810 | + |
4811 | +add_library(mockwindowmanagmentpolicy SHARED |
4812 | + WindowManagementPolicy.cpp |
4813 | +) |
4814 | +target_link_libraries(mockwindowmanagmentpolicy |
4815 | + ${MIRAL_LDFLAGS} |
4816 | + unity8-private |
4817 | +) |
4818 | +qt5_use_modules(mockwindowmanagmentpolicy Core) |
4819 | + |
4820 | +install(TARGETS mockwindowmanagmentpolicy |
4821 | + DESTINATION ${SHELL_INSTALL_QML}/mocks/WindowManager |
4822 | + ) |
4823 | + |
4824 | +set(WINDOWMANAGER_SRC |
4825 | + ${CMAKE_SOURCE_DIR}/plugins/WindowManager/AvailableDesktopArea.cpp |
4826 | + ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Screen.cpp |
4827 | + ${CMAKE_SOURCE_DIR}/plugins/WindowManager/ScreenAttached.cpp |
4828 | + ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Screens.cpp |
4829 | + ${CMAKE_SOURCE_DIR}/plugins/WindowManager/ScreenWindow.cpp |
4830 | + ${CMAKE_SOURCE_DIR}/plugins/WindowManager/TopLevelWindowModel.cpp |
4831 | + ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Window.cpp |
4832 | + ${CMAKE_SOURCE_DIR}/plugins/WindowManager/WindowMargins.cpp |
4833 | + ${CMAKE_SOURCE_DIR}/plugins/WindowManager/WindowManagerObjects.cpp |
4834 | + ${CMAKE_SOURCE_DIR}/plugins/WindowManager/WorkspaceManager.cpp |
4835 | + ${CMAKE_SOURCE_DIR}/plugins/WindowManager/WorkspaceModel.cpp |
4836 | + ${CMAKE_SOURCE_DIR}/plugins/WindowManager/Workspace.cpp |
4837 | + MockScreens.cpp |
4838 | + MockScreenWindow.cpp |
4839 | + MockScreensConfiguration.cpp |
4840 | + WindowManagerPlugin.cpp |
4841 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h |
4842 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h |
4843 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h |
4844 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h |
4845 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceListInterface.h |
4846 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/SurfaceManagerInterface.h |
4847 | +) |
4848 | + |
4849 | +add_library(MockWindowManager-qml SHARED ${WINDOWMANAGER_SRC}) |
4850 | + |
4851 | +target_link_libraries(MockWindowManager-qml |
4852 | + ${QTMIRSERVER_LDFLAGS} |
4853 | + mockwindowmanagmentpolicy |
4854 | +) |
4855 | + |
4856 | +qt5_use_modules(MockWindowManager-qml Qml Quick Gui) |
4857 | + |
4858 | +add_unity8_mock(WindowManager 1.0 WindowManager TARGETS MockWindowManager-qml) |
4859 | |
4860 | === added file 'tests/mocks/WindowManager/MockScreenWindow.cpp' |
4861 | --- tests/mocks/WindowManager/MockScreenWindow.cpp 1970-01-01 00:00:00 +0000 |
4862 | +++ tests/mocks/WindowManager/MockScreenWindow.cpp 2017-04-05 11:48:54 +0000 |
4863 | @@ -0,0 +1,34 @@ |
4864 | +/* |
4865 | + * Copyright (C) 2016-2017 Canonical, Ltd. |
4866 | + * |
4867 | + * This program is free software: you can redistribute it and/or modify it under |
4868 | + * the terms of the GNU Lesser General Public License version 3, as published by |
4869 | + * the Free Software Foundation. |
4870 | + * |
4871 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
4872 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
4873 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
4874 | + * Lesser General Public License for more details. |
4875 | + * |
4876 | + * You should have received a copy of the GNU Lesser General Public License |
4877 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4878 | + */ |
4879 | + |
4880 | +#include "MockScreenWindow.h" |
4881 | +#include "MockScreens.h" |
4882 | + |
4883 | +// Qt |
4884 | +#include <QGuiApplication> |
4885 | +#include <QDebug> |
4886 | + |
4887 | +MockScreenWindow::MockScreenWindow(QQuickWindow *parent) |
4888 | + : ScreenWindow(parent) |
4889 | +{ |
4890 | + connect(this, &ScreenWindow::screenWrapperChanged, this, [this]() { |
4891 | + MockScreens::instance()->connectWindow(this); |
4892 | + }); |
4893 | +} |
4894 | + |
4895 | +MockScreenWindow::~MockScreenWindow() |
4896 | +{ |
4897 | +} |
4898 | |
4899 | === added file 'tests/mocks/WindowManager/MockScreenWindow.h' |
4900 | --- tests/mocks/WindowManager/MockScreenWindow.h 1970-01-01 00:00:00 +0000 |
4901 | +++ tests/mocks/WindowManager/MockScreenWindow.h 2017-04-05 11:48:54 +0000 |
4902 | @@ -0,0 +1,30 @@ |
4903 | +/* |
4904 | + * Copyright (C) 2016-2017 Canonical, Ltd. |
4905 | + * |
4906 | + * This program is free software: you can redistribute it and/or modify it under |
4907 | + * the terms of the GNU Lesser General Public License version 3, as published by |
4908 | + * the Free Software Foundation. |
4909 | + * |
4910 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
4911 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
4912 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
4913 | + * Lesser General Public License for more details. |
4914 | + * |
4915 | + * You should have received a copy of the GNU Lesser General Public License |
4916 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4917 | + */ |
4918 | + |
4919 | +#ifndef MOCK_SCREENWINDOW_H |
4920 | +#define MOCK_SCREENWINDOW_H |
4921 | + |
4922 | +#include "ScreenWindow.h" |
4923 | + |
4924 | +class MockScreenWindow : public ScreenWindow |
4925 | +{ |
4926 | + Q_OBJECT |
4927 | +public: |
4928 | + explicit MockScreenWindow(QQuickWindow *parent = 0); |
4929 | + ~MockScreenWindow(); |
4930 | +}; |
4931 | + |
4932 | +#endif // MOCK_SCREENWINDOW_H |
4933 | |
4934 | === added file 'tests/mocks/WindowManager/MockScreens.cpp' |
4935 | --- tests/mocks/WindowManager/MockScreens.cpp 1970-01-01 00:00:00 +0000 |
4936 | +++ tests/mocks/WindowManager/MockScreens.cpp 2017-04-05 11:48:54 +0000 |
4937 | @@ -0,0 +1,227 @@ |
4938 | +/* |
4939 | + * Copyright (C) 2016-2017 Canonical, Ltd. |
4940 | + * |
4941 | + * This program is free software: you can redistribute it and/or modify it under |
4942 | + * the terms of the GNU Lesser General Public License version 3, as published by |
4943 | + * the Free Software Foundation. |
4944 | + * |
4945 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
4946 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
4947 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
4948 | + * Lesser General Public License for more details. |
4949 | + * |
4950 | + * You should have received a copy of the GNU Lesser General Public License |
4951 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4952 | + */ |
4953 | + |
4954 | +#include "MockScreens.h" |
4955 | +#include "ScreenWindow.h" |
4956 | + |
4957 | +// qtmirserver |
4958 | +#include <qtmir/screen.h> |
4959 | + |
4960 | +#include <QGuiApplication> |
4961 | +#include <QWindow> |
4962 | +#include <QWeakPointer> |
4963 | + |
4964 | +namespace { |
4965 | + |
4966 | +QWeakPointer<MockScreens> m_screens; |
4967 | + |
4968 | +class MockScreen : public qtmir::Screen |
4969 | +{ |
4970 | + Q_OBJECT |
4971 | +public: |
4972 | + MockScreen() |
4973 | + { |
4974 | + m_sizes.append(new qtmir::ScreenMode(50, QSize(640,480))); |
4975 | + m_sizes.append(new qtmir::ScreenMode(60, QSize(1280,1024))); |
4976 | + m_sizes.append(new qtmir::ScreenMode(60, QSize(1440,900))); |
4977 | + m_sizes.append(new qtmir::ScreenMode(60, QSize(1920,1080))); |
4978 | + m_physicalSize = QSize(800,568); |
4979 | + } |
4980 | + ~MockScreen() { |
4981 | + qDeleteAll(m_sizes); |
4982 | + m_sizes.clear(); |
4983 | + } |
4984 | + |
4985 | + void connectToWindow(QWindow* w) |
4986 | + { |
4987 | + if (m_connectedWindow == w) return; |
4988 | + |
4989 | + if (m_connectedWindow) { |
4990 | + disconnect(m_connectedWindow.data()); |
4991 | + m_sizes.takeFirst()->deleteLater(); |
4992 | + } |
4993 | + |
4994 | + m_connectedWindow = w; |
4995 | + |
4996 | + if (w) { |
4997 | + connect(w, &QWindow::heightChanged, this, [this](int height) { |
4998 | + if (height == 0 || height == m_sizes.first()->size.rheight()) { |
4999 | + return; |
5000 | + } |
FAILED: Continuous integration, rev:2836 /unity8- jenkins. ubuntu. com/job/ lp-unity8- ci/3553/ /unity8- jenkins. ubuntu. com/job/ build/4713 /unity8- jenkins. ubuntu. com/job/ test-0- autopkgtest/ label=amd64, release= xenial+ overlay, testname= qmluitests. sh/2863 /unity8- jenkins. ubuntu. com/job/ test-0- autopkgtest/ label=amd64, release= zesty,testname= qmluitests. sh/2863/ console /unity8- jenkins. ubuntu. com/job/ build-0- fetch/4741 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 4564 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 4564/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= zesty/4564 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= zesty/4564/ artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 4564 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 4564/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= zesty/4564 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= zesty/4564/ artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 4564 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 4564/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= zesty/4564 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= zesty/4564/ artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /unity8- jenkins. ubuntu. com/job/ lp-unity8- ci/3553/ rebuild
https:/