Merge lp:~ci-train-bot/qtmir/qtmir-ubuntu-xenial-landing-064 into lp:qtmir
- qtmir-ubuntu-xenial-landing-064
- Merge into trunk
Proposed by
Michał Sawicz
Status: | Merged |
---|---|
Merged at revision: | 462 |
Proposed branch: | lp:~ci-train-bot/qtmir/qtmir-ubuntu-xenial-landing-064 |
Merge into: | lp:qtmir |
Diff against target: |
4345 lines (+3483/-201) 42 files modified
debian/changelog (+30/-0) debian/tests/control (+0/-5) debian/tests/run-tests (+0/-10) src/modules/Unity/Application/mirsurface.cpp (+5/-0) src/modules/Unity/Application/mirsurfacemanager.cpp (+15/-0) src/modules/Unity/Application/mirsurfacemanager.h (+5/-1) src/platforms/mirserver/CMakeLists.txt (+2/-0) src/platforms/mirserver/argvHelper.h (+52/-0) src/platforms/mirserver/miropenglcontext.cpp (+7/-2) src/platforms/mirserver/miropenglcontext.h (+2/-0) src/platforms/mirserver/mirserver.cpp (+24/-11) src/platforms/mirserver/mirserver.h (+1/-1) src/platforms/mirserver/mirserverintegration.cpp (+2/-2) src/platforms/mirserver/mirserverintegration.h (+1/-1) src/platforms/mirserver/plugin.cpp (+4/-8) src/platforms/mirserver/plugin.h (+1/-2) src/platforms/mirserver/qmirserver.cpp (+2/-11) src/platforms/mirserver/qmirserver.h (+1/-1) src/platforms/mirserver/screen.cpp (+24/-4) src/platforms/mirserver/screen.h (+3/-1) src/platforms/mirserver/screenwindow.cpp (+1/-1) src/platforms/mirserver/wm-wip/CMakeLists.txt (+22/-0) src/platforms/mirserver/wm-wip/README (+5/-0) src/platforms/mirserver/wm-wip/server_example_basic_window_manager.cpp (+312/-0) src/platforms/mirserver/wm-wip/server_example_basic_window_manager.h (+252/-0) src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.cpp (+946/-0) src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.h (+132/-0) src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.cpp (+640/-0) src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.h (+124/-0) src/platforms/mirserver/wm-wip/server_example_window_management.cpp (+155/-0) src/platforms/mirserver/wm-wip/server_example_window_management.h (+33/-0) src/platforms/mirserver/wm-wip/server_example_window_management_info.cpp (+406/-0) src/platforms/mirserver/wm-wip/server_example_window_management_info.h (+103/-0) tests/framework/mock_proc_info.cpp (+2/-0) tests/framework/mock_session.cpp (+1/-0) tests/framework/mock_task_controller.cpp (+4/-4) tests/framework/qtmir_test.cpp (+2/-2) tests/mirserver/ArgvHelper/CMakeLists.txt (+18/-0) tests/mirserver/ArgvHelper/argvHelper_test.cpp (+72/-0) tests/mirserver/CMakeLists.txt (+1/-0) tests/mirserver/Screen/screen_test.cpp (+17/-3) tests/modules/ApplicationManager/application_manager_test.cpp (+54/-131) |
To merge this branch: | bzr merge lp:~ci-train-bot/qtmir/qtmir-ubuntu-xenial-landing-064 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir development team | Pending | ||
Review via email: mp+288756@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/changelog' | |||
2 | --- debian/changelog 2016-02-19 10:41:19 +0000 | |||
3 | +++ debian/changelog 2016-03-11 11:36:44 +0000 | |||
4 | @@ -1,3 +1,33 @@ | |||
5 | 1 | qtmir (0.4.7+16.04.20160310.1-0ubuntu1) xenial; urgency=medium | ||
6 | 2 | |||
7 | 3 | [ Alan Griffiths ] | ||
8 | 4 | * Copy the Window Management work-in-progress from Mir examples. | ||
9 | 5 | |||
10 | 6 | [ Alberto Aguirre ] | ||
11 | 7 | * Hook MirOpenGLContext::doneCurrent to Screen::doneCurrent | ||
12 | 8 | |||
13 | 9 | [ Daniel d'Andrada ] | ||
14 | 10 | * Ensure QmlEngine doesn't delete our MirSurfaces | ||
15 | 11 | |||
16 | 12 | [ Gerry Boland ] | ||
17 | 13 | * Allow Mir remove command line arguments it understands, before | ||
18 | 14 | letting Qt process them. | ||
19 | 15 | * Ensure ScreenWindow geometry correctly set and used after moving | ||
20 | 16 | Screen (LP: #1545286) | ||
21 | 17 | * Screen: only enable orientation sensor for internal display. (LP: | ||
22 | 18 | #1545286) | ||
23 | 19 | |||
24 | 20 | [ Michael Terry ] | ||
25 | 21 | * Fix some mocks to use more realistic code paths. | ||
26 | 22 | |||
27 | 23 | [ Michael Zanetti ] | ||
28 | 24 | * Add a dedicated property for the inputMethodSurface (LP: #1545286) | ||
29 | 25 | |||
30 | 26 | [ Michał Sawicz ] | ||
31 | 27 | * Drop dummy autopkgtest | ||
32 | 28 | |||
33 | 29 | -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 10 Mar 2016 09:29:49 +0000 | ||
34 | 30 | |||
35 | 1 | qtmir (0.4.7+16.04.20160219-0ubuntu1) xenial; urgency=medium | 31 | qtmir (0.4.7+16.04.20160219-0ubuntu1) xenial; urgency=medium |
36 | 2 | 32 | ||
37 | 3 | * Mir 0.20 Release | 33 | * Mir 0.20 Release |
38 | 4 | 34 | ||
39 | === removed directory 'debian/tests' | |||
40 | === removed file 'debian/tests/control' | |||
41 | --- debian/tests/control 2015-10-27 15:53:28 +0000 | |||
42 | +++ debian/tests/control 1970-01-01 00:00:00 +0000 | |||
43 | @@ -1,5 +0,0 @@ | |||
44 | 1 | Tests: run-tests | ||
45 | 2 | Restrictions: build-needed | ||
46 | 3 | Depends: qtdeclarative5-qtmir-plugin, | ||
47 | 4 | qtmir-desktop, | ||
48 | 5 | qtmir-tests, | ||
49 | 6 | 0 | ||
50 | === removed file 'debian/tests/run-tests' | |||
51 | --- debian/tests/run-tests 2015-06-15 15:57:04 +0000 | |||
52 | +++ debian/tests/run-tests 1970-01-01 00:00:00 +0000 | |||
53 | @@ -1,10 +0,0 @@ | |||
54 | 1 | #!/bin/sh | ||
55 | 2 | |||
56 | 3 | set -ex | ||
57 | 4 | |||
58 | 5 | # Do nothing here. We don't need to run the tests multiple times, and they | ||
59 | 6 | # are already being run during the build phase of the autopkgtest, as we | ||
60 | 7 | # require a built tree to run them, and the tests are run as part of the | ||
61 | 8 | # normal package build process. We do want to test that things install, though | ||
62 | 9 | # and at least one test is actually required, for autopkgtest to work. | ||
63 | 10 | |||
64 | 11 | 0 | ||
65 | === modified file 'src/modules/Unity/Application/mirsurface.cpp' | |||
66 | --- src/modules/Unity/Application/mirsurface.cpp 2016-02-11 11:58:16 +0000 | |||
67 | +++ src/modules/Unity/Application/mirsurface.cpp 2016-03-11 11:36:44 +0000 | |||
68 | @@ -32,6 +32,9 @@ | |||
69 | 32 | // mirserver | 32 | // mirserver |
70 | 33 | #include <logging.h> | 33 | #include <logging.h> |
71 | 34 | 34 | ||
72 | 35 | // Qt | ||
73 | 36 | #include <QQmlEngine> | ||
74 | 37 | |||
75 | 35 | using namespace qtmir; | 38 | using namespace qtmir; |
76 | 36 | 39 | ||
77 | 37 | #define DEBUG_MSG qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << (void*)this << "," << appId() <<"]::" << __func__ | 40 | #define DEBUG_MSG qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << (void*)this << "," << appId() <<"]::" << __func__ |
78 | @@ -223,6 +226,8 @@ | |||
79 | 223 | // in practice rarely happen. | 226 | // in practice rarely happen. |
80 | 224 | m_frameDropperTimer.setInterval(200); | 227 | m_frameDropperTimer.setInterval(200); |
81 | 225 | m_frameDropperTimer.setSingleShot(false); | 228 | m_frameDropperTimer.setSingleShot(false); |
82 | 229 | |||
83 | 230 | QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); | ||
84 | 226 | } | 231 | } |
85 | 227 | 232 | ||
86 | 228 | MirSurface::~MirSurface() | 233 | MirSurface::~MirSurface() |
87 | 229 | 234 | ||
88 | === modified file 'src/modules/Unity/Application/mirsurfacemanager.cpp' | |||
89 | --- src/modules/Unity/Application/mirsurfacemanager.cpp 2016-02-11 11:58:16 +0000 | |||
90 | +++ src/modules/Unity/Application/mirsurfacemanager.cpp 2016-03-11 11:36:44 +0000 | |||
91 | @@ -114,6 +114,11 @@ | |||
92 | 114 | if (session) | 114 | if (session) |
93 | 115 | session->registerSurface(qmlSurface); | 115 | session->registerSurface(qmlSurface); |
94 | 116 | 116 | ||
95 | 117 | if (qmlSurface->type() == Mir::InputMethodType) { | ||
96 | 118 | m_inputMethodSurface = qmlSurface; | ||
97 | 119 | Q_EMIT inputMethodSurfaceChanged(); | ||
98 | 120 | } | ||
99 | 121 | |||
100 | 117 | // Only notify QML of surface creation once it has drawn its first frame. | 122 | // Only notify QML of surface creation once it has drawn its first frame. |
101 | 118 | connect(qmlSurface, &MirSurfaceInterface::firstFrameDrawn, this, [=]() { | 123 | connect(qmlSurface, &MirSurfaceInterface::firstFrameDrawn, this, [=]() { |
102 | 119 | tracepoint(qtmir, firstFrameDrawn); | 124 | tracepoint(qtmir, firstFrameDrawn); |
103 | @@ -155,8 +160,18 @@ | |||
104 | 155 | } | 160 | } |
105 | 156 | } | 161 | } |
106 | 157 | 162 | ||
107 | 163 | if (qmlSurface->type() == Mir::InputMethodType) { | ||
108 | 164 | m_inputMethodSurface = nullptr; | ||
109 | 165 | Q_EMIT inputMethodSurfaceChanged(); | ||
110 | 166 | } | ||
111 | 167 | |||
112 | 158 | qmlSurface->setLive(false); | 168 | qmlSurface->setLive(false); |
113 | 159 | Q_EMIT surfaceDestroyed(qmlSurface); | 169 | Q_EMIT surfaceDestroyed(qmlSurface); |
114 | 160 | } | 170 | } |
115 | 161 | 171 | ||
116 | 172 | MirSurfaceInterface* MirSurfaceManager::inputMethodSurface() const | ||
117 | 173 | { | ||
118 | 174 | return m_inputMethodSurface; | ||
119 | 175 | } | ||
120 | 176 | |||
121 | 162 | } // namespace qtmir | 177 | } // namespace qtmir |
122 | 163 | 178 | ||
123 | === modified file 'src/modules/Unity/Application/mirsurfacemanager.h' | |||
124 | --- src/modules/Unity/Application/mirsurfacemanager.h 2016-02-11 11:58:16 +0000 | |||
125 | +++ src/modules/Unity/Application/mirsurfacemanager.h 2016-03-11 11:36:44 +0000 | |||
126 | @@ -54,7 +54,7 @@ | |||
127 | 54 | class MirSurfaceManager : public QObject | 54 | class MirSurfaceManager : public QObject |
128 | 55 | { | 55 | { |
129 | 56 | Q_OBJECT | 56 | Q_OBJECT |
131 | 57 | 57 | Q_PROPERTY(MirSurfaceInterface* inputMethodSurface READ inputMethodSurface NOTIFY inputMethodSurfaceChanged) | |
132 | 58 | public: | 58 | public: |
133 | 59 | explicit MirSurfaceManager( | 59 | explicit MirSurfaceManager( |
134 | 60 | const QSharedPointer<MirServer>& mirServer, | 60 | const QSharedPointer<MirServer>& mirServer, |
135 | @@ -66,7 +66,10 @@ | |||
136 | 66 | 66 | ||
137 | 67 | static MirSurfaceManager* singleton(); | 67 | static MirSurfaceManager* singleton(); |
138 | 68 | 68 | ||
139 | 69 | MirSurfaceInterface* inputMethodSurface() const; | ||
140 | 70 | |||
141 | 69 | Q_SIGNALS: | 71 | Q_SIGNALS: |
142 | 72 | void inputMethodSurfaceChanged(); | ||
143 | 70 | void surfaceCreated(MirSurfaceInterface* surface); | 73 | void surfaceCreated(MirSurfaceInterface* surface); |
144 | 71 | void surfaceDestroyed(MirSurfaceInterface* surface); | 74 | void surfaceDestroyed(MirSurfaceInterface* surface); |
145 | 72 | 75 | ||
146 | @@ -86,6 +89,7 @@ | |||
147 | 86 | mir::shell::Shell *const m_shell; | 89 | mir::shell::Shell *const m_shell; |
148 | 87 | SessionManager* m_sessionManager; | 90 | SessionManager* m_sessionManager; |
149 | 88 | static MirSurfaceManager *instance; | 91 | static MirSurfaceManager *instance; |
150 | 92 | MirSurfaceInterface* m_inputMethodSurface = nullptr; | ||
151 | 89 | }; | 93 | }; |
152 | 90 | 94 | ||
153 | 91 | } // namespace qtmir | 95 | } // namespace qtmir |
154 | 92 | 96 | ||
155 | === modified file 'src/platforms/mirserver/CMakeLists.txt' | |||
156 | --- src/platforms/mirserver/CMakeLists.txt 2016-02-11 11:58:16 +0000 | |||
157 | +++ src/platforms/mirserver/CMakeLists.txt 2016-03-11 11:36:44 +0000 | |||
158 | @@ -36,6 +36,8 @@ | |||
159 | 36 | ${APPLICATION_API_INCLUDE_DIRS} | 36 | ${APPLICATION_API_INCLUDE_DIRS} |
160 | 37 | ) | 37 | ) |
161 | 38 | 38 | ||
162 | 39 | add_subdirectory(wm-wip) | ||
163 | 40 | |||
164 | 39 | # We have to remove -pedantic for tracepoints.c | 41 | # We have to remove -pedantic for tracepoints.c |
165 | 40 | string (REPLACE " -pedantic " " " CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) | 42 | string (REPLACE " -pedantic " " " CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) |
166 | 41 | # Needed to compile tracepoints in C99 mode. | 43 | # Needed to compile tracepoints in C99 mode. |
167 | 42 | 44 | ||
168 | === added file 'src/platforms/mirserver/argvHelper.h' | |||
169 | --- src/platforms/mirserver/argvHelper.h 1970-01-01 00:00:00 +0000 | |||
170 | +++ src/platforms/mirserver/argvHelper.h 2016-03-11 11:36:44 +0000 | |||
171 | @@ -0,0 +1,52 @@ | |||
172 | 1 | /* | ||
173 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
174 | 3 | * | ||
175 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
176 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
177 | 6 | * the Free Software Foundation. | ||
178 | 7 | * | ||
179 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
180 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
181 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
182 | 11 | * Lesser General Public License for more details. | ||
183 | 12 | * | ||
184 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
185 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
186 | 15 | */ | ||
187 | 16 | |||
188 | 17 | #ifndef ARGVHELPER_P_H | ||
189 | 18 | #define ARGVHELPER_P_H | ||
190 | 19 | |||
191 | 20 | #include <cassert> | ||
192 | 21 | |||
193 | 22 | namespace qtmir { | ||
194 | 23 | |||
195 | 24 | // Function to edit argv to strip out unmatched entries of targetArray, so both arrays have identical contents | ||
196 | 25 | // Note: Mir parses out arguments that it understands, but it also removes argv[0] (bug pad.lv/1511509) | ||
197 | 26 | // so need to ensure argv[0] is the binary name as usual. | ||
198 | 27 | void editArgvToMatch(int &argcToEdit, char** argvToEdit, int targetCount, const char* const targetArray[]) | ||
199 | 28 | { | ||
200 | 29 | // Make copy of the argv array of pointers, as we will be editing the original | ||
201 | 30 | const size_t arraySize = (argcToEdit + 1) * sizeof(char*); | ||
202 | 31 | char** argvCopy = static_cast<char**>(malloc(arraySize)); | ||
203 | 32 | memcpy(argvCopy, argvToEdit, arraySize); | ||
204 | 33 | |||
205 | 34 | int k=1; // index of argv we want to edit - note we'll leave argv[0] alone | ||
206 | 35 | for (int i=0; i<targetCount; i++) { // taking each argument Mir did not parse out | ||
207 | 36 | for (int j=1; j<argcToEdit; j++) { // find pointer to same argument in argvCopy (leave arg[0] out) | ||
208 | 37 | if (strcmp(targetArray[i], argvCopy[j]) == 0) { | ||
209 | 38 | argvToEdit[k] = const_cast<char*>(argvCopy[j]); // edit argv to position that argument to match argv2. | ||
210 | 39 | k++; | ||
211 | 40 | break; | ||
212 | 41 | } | ||
213 | 42 | } | ||
214 | 43 | } | ||
215 | 44 | assert(k == targetCount+1); | ||
216 | 45 | argvToEdit[k] = nullptr; | ||
217 | 46 | free(argvCopy); | ||
218 | 47 | argcToEdit = targetCount+1; // now argv and targetArray should have list the same strings. | ||
219 | 48 | } | ||
220 | 49 | |||
221 | 50 | } // namespace qtmir | ||
222 | 51 | |||
223 | 52 | #endif // ARGVHELPER_P_H | ||
224 | 0 | 53 | ||
225 | === modified file 'src/platforms/mirserver/miropenglcontext.cpp' | |||
226 | --- src/platforms/mirserver/miropenglcontext.cpp 2015-09-14 22:38:20 +0000 | |||
227 | +++ src/platforms/mirserver/miropenglcontext.cpp 2016-03-11 11:36:44 +0000 | |||
228 | @@ -36,8 +36,9 @@ | |||
229 | 36 | // (i.e. individual display output buffers) to use as a common base context. | 36 | // (i.e. individual display output buffers) to use as a common base context. |
230 | 37 | 37 | ||
231 | 38 | MirOpenGLContext::MirOpenGLContext(const QSharedPointer<MirServer> &server, const QSurfaceFormat &format) | 38 | MirOpenGLContext::MirOpenGLContext(const QSharedPointer<MirServer> &server, const QSurfaceFormat &format) |
232 | 39 | : m_currentWindow(nullptr) | ||
233 | 39 | #ifndef QT_NO_DEBUG | 40 | #ifndef QT_NO_DEBUG |
235 | 40 | : m_logger(new QOpenGLDebugLogger(this)) | 41 | , m_logger(new QOpenGLDebugLogger(this)) |
236 | 41 | #endif | 42 | #endif |
237 | 42 | { | 43 | { |
238 | 43 | auto display = server->the_display(); | 44 | auto display = server->the_display(); |
239 | @@ -131,6 +132,7 @@ | |||
240 | 131 | // ultimately calls Mir's DisplayBuffer::make_current() | 132 | // ultimately calls Mir's DisplayBuffer::make_current() |
241 | 132 | ScreenWindow *screenWindow = static_cast<ScreenWindow*>(surface); | 133 | ScreenWindow *screenWindow = static_cast<ScreenWindow*>(surface); |
242 | 133 | if (screenWindow) { | 134 | if (screenWindow) { |
243 | 135 | m_currentWindow = screenWindow; | ||
244 | 134 | screenWindow->makeCurrent(); | 136 | screenWindow->makeCurrent(); |
245 | 135 | 137 | ||
246 | 136 | #ifndef QT_NO_DEBUG | 138 | #ifndef QT_NO_DEBUG |
247 | @@ -148,7 +150,10 @@ | |||
248 | 148 | 150 | ||
249 | 149 | void MirOpenGLContext::doneCurrent() | 151 | void MirOpenGLContext::doneCurrent() |
250 | 150 | { | 152 | { |
252 | 151 | // FIXME: create a temporary GL context just to release? Would be better to get existing one. | 153 | if (m_currentWindow) { |
253 | 154 | m_currentWindow->doneCurrent(); | ||
254 | 155 | m_currentWindow = nullptr; | ||
255 | 156 | } | ||
256 | 152 | } | 157 | } |
257 | 153 | 158 | ||
258 | 154 | QFunctionPointer MirOpenGLContext::getProcAddress(const QByteArray &procName) | 159 | QFunctionPointer MirOpenGLContext::getProcAddress(const QByteArray &procName) |
259 | 155 | 160 | ||
260 | === modified file 'src/platforms/mirserver/miropenglcontext.h' | |||
261 | --- src/platforms/mirserver/miropenglcontext.h 2015-09-14 22:38:20 +0000 | |||
262 | +++ src/platforms/mirserver/miropenglcontext.h 2016-03-11 11:36:44 +0000 | |||
263 | @@ -25,6 +25,7 @@ | |||
264 | 25 | 25 | ||
265 | 26 | 26 | ||
266 | 27 | class MirServer; | 27 | class MirServer; |
267 | 28 | class ScreenWindow; | ||
268 | 28 | 29 | ||
269 | 29 | class MirOpenGLContext : public QObject, public QPlatformOpenGLContext | 30 | class MirOpenGLContext : public QObject, public QPlatformOpenGLContext |
270 | 30 | { | 31 | { |
271 | @@ -49,6 +50,7 @@ | |||
272 | 49 | 50 | ||
273 | 50 | private: | 51 | private: |
274 | 51 | QSurfaceFormat m_format; | 52 | QSurfaceFormat m_format; |
275 | 53 | ScreenWindow *m_currentWindow; | ||
276 | 52 | #ifndef QT_NO_DEBUG | 54 | #ifndef QT_NO_DEBUG |
277 | 53 | QOpenGLDebugLogger *m_logger; | 55 | QOpenGLDebugLogger *m_logger; |
278 | 54 | #endif | 56 | #endif |
279 | 55 | 57 | ||
280 | === modified file 'src/platforms/mirserver/mirserver.cpp' | |||
281 | --- src/platforms/mirserver/mirserver.cpp 2016-02-11 11:58:16 +0000 | |||
282 | +++ src/platforms/mirserver/mirserver.cpp 2016-03-11 11:36:44 +0000 | |||
283 | @@ -19,6 +19,7 @@ | |||
284 | 19 | #include "mirserver.h" | 19 | #include "mirserver.h" |
285 | 20 | 20 | ||
286 | 21 | // local | 21 | // local |
287 | 22 | #include "argvHelper.h" | ||
288 | 22 | #include "mircursorimages.h" | 23 | #include "mircursorimages.h" |
289 | 23 | #include "mirwindowmanager.h" | 24 | #include "mirwindowmanager.h" |
290 | 24 | #include "mirglconfig.h" | 25 | #include "mirglconfig.h" |
291 | @@ -47,22 +48,24 @@ | |||
292 | 47 | namespace msh = mir::shell; | 48 | namespace msh = mir::shell; |
293 | 48 | namespace ms = mir::scene; | 49 | namespace ms = mir::scene; |
294 | 49 | 50 | ||
295 | 50 | namespace | ||
296 | 51 | { | ||
297 | 52 | void ignore_unparsed_arguments(int /*argc*/, char const* const/*argv*/[]) | ||
298 | 53 | { | ||
299 | 54 | } | ||
300 | 55 | } | ||
301 | 56 | |||
302 | 57 | Q_LOGGING_CATEGORY(QTMIR_MIR_MESSAGES, "qtmir.mir") | 51 | Q_LOGGING_CATEGORY(QTMIR_MIR_MESSAGES, "qtmir.mir") |
303 | 58 | 52 | ||
305 | 59 | MirServer::MirServer(int argc, char const* argv[], | 53 | |
306 | 54 | MirServer::MirServer(int &argc, char **argv, | ||
307 | 60 | const QSharedPointer<ScreenController> &screenController, QObject* parent) | 55 | const QSharedPointer<ScreenController> &screenController, QObject* parent) |
308 | 61 | : QObject(parent) | 56 | : QObject(parent) |
309 | 62 | , m_screenController(screenController) | 57 | , m_screenController(screenController) |
310 | 63 | { | 58 | { |
313 | 64 | set_command_line_handler(&ignore_unparsed_arguments); | 59 | bool unknownArgsFound = false; |
314 | 65 | set_command_line(argc, argv); | 60 | set_command_line_handler([&argc, &argv, &unknownArgsFound](int filteredCount, const char* const filteredArgv[]) { |
315 | 61 | unknownArgsFound = true; | ||
316 | 62 | // Want to edit argv to match that which Mir returns, as those are for to Qt alone to process. Edit existing | ||
317 | 63 | // argc as filteredArgv only defined in this scope. | ||
318 | 64 | qtmir::editArgvToMatch(argc, argv, filteredCount, filteredArgv); | ||
319 | 65 | }); | ||
320 | 66 | |||
321 | 67 | // Casting char** to be a const char** safe as Mir won't change it, nor will we | ||
322 | 68 | set_command_line(argc, const_cast<const char **>(argv)); | ||
323 | 66 | 69 | ||
324 | 67 | override_the_session_listener([] | 70 | override_the_session_listener([] |
325 | 68 | { | 71 | { |
326 | @@ -130,7 +133,16 @@ | |||
327 | 130 | screenController->init(the_display(), the_compositor()); | 133 | screenController->init(the_display(), the_compositor()); |
328 | 131 | }); | 134 | }); |
329 | 132 | 135 | ||
331 | 133 | apply_settings(); | 136 | try { |
332 | 137 | apply_settings(); | ||
333 | 138 | } catch (const std::exception &ex) { | ||
334 | 139 | qCritical() << ex.what(); | ||
335 | 140 | exit(1); | ||
336 | 141 | } | ||
337 | 142 | |||
338 | 143 | if (!unknownArgsFound) { // mir parsed all the arguments, so edit argv to pretend to have just argv[0] | ||
339 | 144 | argc = 1; | ||
340 | 145 | } | ||
341 | 134 | 146 | ||
342 | 135 | // We will draw our own cursor. | 147 | // We will draw our own cursor. |
343 | 136 | // FIXME: Call override_the_cusor() instead once this method becomes available in a | 148 | // FIXME: Call override_the_cusor() instead once this method becomes available in a |
344 | @@ -142,6 +154,7 @@ | |||
345 | 142 | }); | 154 | }); |
346 | 143 | 155 | ||
347 | 144 | qCDebug(QTMIR_MIR_MESSAGES) << "MirServer created"; | 156 | qCDebug(QTMIR_MIR_MESSAGES) << "MirServer created"; |
348 | 157 | qCDebug(QTMIR_MIR_MESSAGES) << "Command line arguments passed to Qt:" << QCoreApplication::arguments(); | ||
349 | 145 | } | 158 | } |
350 | 146 | 159 | ||
351 | 147 | // Override default implementation to ensure we terminate the ScreenController first. | 160 | // Override default implementation to ensure we terminate the ScreenController first. |
352 | 148 | 161 | ||
353 | === modified file 'src/platforms/mirserver/mirserver.h' | |||
354 | --- src/platforms/mirserver/mirserver.h 2016-02-11 11:54:59 +0000 | |||
355 | +++ src/platforms/mirserver/mirserver.h 2016-03-11 11:36:44 +0000 | |||
356 | @@ -41,7 +41,7 @@ | |||
357 | 41 | Q_PROPERTY(PromptSessionListener* promptSessionListener READ promptSessionListener CONSTANT) | 41 | Q_PROPERTY(PromptSessionListener* promptSessionListener READ promptSessionListener CONSTANT) |
358 | 42 | 42 | ||
359 | 43 | public: | 43 | public: |
361 | 44 | MirServer(int argc, char const* argv[], const QSharedPointer<ScreenController> &, QObject* parent = 0); | 44 | MirServer(int &argc, char **argv, const QSharedPointer<ScreenController> &, QObject* parent = 0); |
362 | 45 | ~MirServer() = default; | 45 | ~MirServer() = default; |
363 | 46 | 46 | ||
364 | 47 | /* mir specific */ | 47 | /* mir specific */ |
365 | 48 | 48 | ||
366 | === modified file 'src/platforms/mirserver/mirserverintegration.cpp' | |||
367 | --- src/platforms/mirserver/mirserverintegration.cpp 2015-10-21 11:46:33 +0000 | |||
368 | +++ src/platforms/mirserver/mirserverintegration.cpp 2016-03-11 11:36:44 +0000 | |||
369 | @@ -51,11 +51,11 @@ | |||
370 | 51 | namespace mg = mir::graphics; | 51 | namespace mg = mir::graphics; |
371 | 52 | using qtmir::Clipboard; | 52 | using qtmir::Clipboard; |
372 | 53 | 53 | ||
374 | 54 | MirServerIntegration::MirServerIntegration() | 54 | MirServerIntegration::MirServerIntegration(int &argc, char **argv) |
375 | 55 | : m_accessibility(new QPlatformAccessibility()) | 55 | : m_accessibility(new QPlatformAccessibility()) |
376 | 56 | , m_fontDb(new QGenericUnixFontDatabase()) | 56 | , m_fontDb(new QGenericUnixFontDatabase()) |
377 | 57 | , m_services(new Services) | 57 | , m_services(new Services) |
379 | 58 | , m_mirServer(new QMirServer(QCoreApplication::arguments())) | 58 | , m_mirServer(new QMirServer(argc, argv)) |
380 | 59 | , m_nativeInterface(nullptr) | 59 | , m_nativeInterface(nullptr) |
381 | 60 | , m_clipboard(new Clipboard) | 60 | , m_clipboard(new Clipboard) |
382 | 61 | { | 61 | { |
383 | 62 | 62 | ||
384 | === modified file 'src/platforms/mirserver/mirserverintegration.h' | |||
385 | --- src/platforms/mirserver/mirserverintegration.h 2015-08-20 10:16:54 +0000 | |||
386 | +++ src/platforms/mirserver/mirserverintegration.h 2016-03-11 11:36:44 +0000 | |||
387 | @@ -31,7 +31,7 @@ | |||
388 | 31 | class MirServerIntegration : public QPlatformIntegration | 31 | class MirServerIntegration : public QPlatformIntegration |
389 | 32 | { | 32 | { |
390 | 33 | public: | 33 | public: |
392 | 34 | MirServerIntegration(); | 34 | MirServerIntegration(int &argc, char **argv); |
393 | 35 | ~MirServerIntegration(); | 35 | ~MirServerIntegration(); |
394 | 36 | 36 | ||
395 | 37 | bool hasCapability(QPlatformIntegration::Capability cap) const override; | 37 | bool hasCapability(QPlatformIntegration::Capability cap) const override; |
396 | 38 | 38 | ||
397 | === modified file 'src/platforms/mirserver/plugin.cpp' | |||
398 | --- src/platforms/mirserver/plugin.cpp 2015-08-11 12:08:32 +0000 | |||
399 | +++ src/platforms/mirserver/plugin.cpp 2016-03-11 11:36:44 +0000 | |||
400 | @@ -17,14 +17,10 @@ | |||
401 | 17 | #include "plugin.h" | 17 | #include "plugin.h" |
402 | 18 | #include "mirserverintegration.h" | 18 | #include "mirserverintegration.h" |
403 | 19 | 19 | ||
411 | 20 | QStringList MirServerIntegrationPlugin::keys() const { | 20 | QPlatformIntegration *MirServerIntegrationPlugin::create(const QString &system, const QStringList &/*paramList*/, |
412 | 21 | QStringList list; | 21 | int &argc, char **argv) |
413 | 22 | list << "mirserver"; | 22 | { |
407 | 23 | return list; | ||
408 | 24 | } | ||
409 | 25 | |||
410 | 26 | QPlatformIntegration* MirServerIntegrationPlugin::create(const QString &system, const QStringList &) { | ||
414 | 27 | if (system.toLower() == "mirserver") | 23 | if (system.toLower() == "mirserver") |
416 | 28 | return new MirServerIntegration; | 24 | return new MirServerIntegration(argc, argv); |
417 | 29 | return 0; | 25 | return 0; |
418 | 30 | } | 26 | } |
419 | 31 | 27 | ||
420 | === modified file 'src/platforms/mirserver/plugin.h' | |||
421 | --- src/platforms/mirserver/plugin.h 2015-08-11 12:08:32 +0000 | |||
422 | +++ src/platforms/mirserver/plugin.h 2016-03-11 11:36:44 +0000 | |||
423 | @@ -25,8 +25,7 @@ | |||
424 | 25 | Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "mirserver.json") | 25 | Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "mirserver.json") |
425 | 26 | 26 | ||
426 | 27 | public: | 27 | public: |
429 | 28 | QStringList keys() const; | 28 | QPlatformIntegration *create(const QString &system, const QStringList ¶mList, int &argc, char **argv) override; |
428 | 29 | QPlatformIntegration* create(const QString&, const QStringList&); | ||
430 | 30 | }; | 29 | }; |
431 | 31 | 30 | ||
432 | 32 | #endif // PLUGIN_H | 31 | #endif // PLUGIN_H |
433 | 33 | 32 | ||
434 | === modified file 'src/platforms/mirserver/qmirserver.cpp' | |||
435 | --- src/platforms/mirserver/qmirserver.cpp 2015-11-19 12:55:57 +0000 | |||
436 | +++ src/platforms/mirserver/qmirserver.cpp 2016-03-11 11:36:44 +0000 | |||
437 | @@ -26,24 +26,15 @@ | |||
438 | 26 | #include "screencontroller.h" | 26 | #include "screencontroller.h" |
439 | 27 | #include "screen.h" | 27 | #include "screen.h" |
440 | 28 | 28 | ||
442 | 29 | QMirServer::QMirServer(const QStringList &arguments, QObject *parent) | 29 | QMirServer::QMirServer(int &argc, char **argv, QObject *parent) |
443 | 30 | : QObject(parent) | 30 | : QObject(parent) |
444 | 31 | , d_ptr(new QMirServerPrivate()) | 31 | , d_ptr(new QMirServerPrivate()) |
445 | 32 | { | 32 | { |
446 | 33 | Q_D(QMirServer); | 33 | Q_D(QMirServer); |
447 | 34 | 34 | ||
448 | 35 | // convert arguments back into argc-argv form that Mir wants | ||
449 | 36 | int argc = arguments.size(); | ||
450 | 37 | char **argv = new char*[argc + 1]; | ||
451 | 38 | for (int i = 0; i < argc; i++) { | ||
452 | 39 | argv[i] = new char[strlen(arguments.at(i).toStdString().c_str())+1]; | ||
453 | 40 | memcpy(argv[i], arguments.at(i).toStdString().c_str(), strlen(arguments.at(i).toStdString().c_str())+1); | ||
454 | 41 | } | ||
455 | 42 | argv[argc] = nullptr; | ||
456 | 43 | |||
457 | 44 | d->screenController = QSharedPointer<ScreenController>(new ScreenController()); | 35 | d->screenController = QSharedPointer<ScreenController>(new ScreenController()); |
458 | 45 | 36 | ||
460 | 46 | d->server = QSharedPointer<MirServer>(new MirServer(argc, const_cast<const char**>(argv), d->screenController)); | 37 | d->server = QSharedPointer<MirServer>(new MirServer(argc, argv, d->screenController)); |
461 | 47 | 38 | ||
462 | 48 | d->serverThread = new MirServerThread(d->server); | 39 | d->serverThread = new MirServerThread(d->server); |
463 | 49 | 40 | ||
464 | 50 | 41 | ||
465 | === modified file 'src/platforms/mirserver/qmirserver.h' | |||
466 | --- src/platforms/mirserver/qmirserver.h 2015-08-20 10:16:54 +0000 | |||
467 | +++ src/platforms/mirserver/qmirserver.h 2016-03-11 11:36:44 +0000 | |||
468 | @@ -30,7 +30,7 @@ | |||
469 | 30 | Q_OBJECT | 30 | Q_OBJECT |
470 | 31 | 31 | ||
471 | 32 | public: | 32 | public: |
473 | 33 | QMirServer(const QStringList &arguments, QObject* parent=0); | 33 | QMirServer(int &argc, char **argv, QObject* parent=0); |
474 | 34 | virtual ~QMirServer(); | 34 | virtual ~QMirServer(); |
475 | 35 | 35 | ||
476 | 36 | bool start(); | 36 | bool start(); |
477 | 37 | 37 | ||
478 | === modified file 'src/platforms/mirserver/screen.cpp' | |||
479 | --- src/platforms/mirserver/screen.cpp 2015-10-14 22:59:04 +0000 | |||
480 | +++ src/platforms/mirserver/screen.cpp 2016-03-11 11:36:44 +0000 | |||
481 | @@ -135,9 +135,11 @@ | |||
482 | 135 | ? Qt::LandscapeOrientation : Qt::PortraitOrientation; | 135 | ? Qt::LandscapeOrientation : Qt::PortraitOrientation; |
483 | 136 | qCDebug(QTMIR_SENSOR_MESSAGES) << "Screen - initial currentOrientation is:" << m_currentOrientation; | 136 | qCDebug(QTMIR_SENSOR_MESSAGES) << "Screen - initial currentOrientation is:" << m_currentOrientation; |
484 | 137 | 137 | ||
488 | 138 | QObject::connect(m_orientationSensor, &QOrientationSensor::readingChanged, | 138 | if (internalDisplay()) { // only enable orientation sensor for device-internal display |
489 | 139 | this, &Screen::onOrientationReadingChanged); | 139 | QObject::connect(m_orientationSensor, &QOrientationSensor::readingChanged, |
490 | 140 | m_orientationSensor->start(); | 140 | this, &Screen::onOrientationReadingChanged); |
491 | 141 | m_orientationSensor->start(); | ||
492 | 142 | } | ||
493 | 141 | 143 | ||
494 | 142 | if (!skipDBusRegistration) { | 144 | if (!skipDBusRegistration) { |
495 | 143 | // FIXME This is a unity8 specific dbus call and shouldn't be in qtmir | 145 | // FIXME This is a unity8 specific dbus call and shouldn't be in qtmir |
496 | @@ -171,7 +173,9 @@ | |||
497 | 171 | void Screen::onDisplayPowerStateChanged(int status, int reason) | 173 | void Screen::onDisplayPowerStateChanged(int status, int reason) |
498 | 172 | { | 174 | { |
499 | 173 | Q_UNUSED(reason); | 175 | Q_UNUSED(reason); |
501 | 174 | toggleSensors(status); | 176 | if (internalDisplay()) { |
502 | 177 | toggleSensors(status); | ||
503 | 178 | } | ||
504 | 175 | } | 179 | } |
505 | 176 | 180 | ||
506 | 177 | void Screen::setMirDisplayConfiguration(const mir::graphics::DisplayConfigurationOutput &screen) | 181 | void Screen::setMirDisplayConfiguration(const mir::graphics::DisplayConfigurationOutput &screen) |
507 | @@ -297,6 +301,13 @@ | |||
508 | 297 | qCDebug(QTMIR_SENSOR_MESSAGES) << "Screen::setWindow - overwriting existing ScreenWindow"; | 301 | qCDebug(QTMIR_SENSOR_MESSAGES) << "Screen::setWindow - overwriting existing ScreenWindow"; |
509 | 298 | } | 302 | } |
510 | 299 | m_screenWindow = window; | 303 | m_screenWindow = window; |
511 | 304 | |||
512 | 305 | if (m_screenWindow) { | ||
513 | 306 | if (m_screenWindow->geometry() != geometry()) { | ||
514 | 307 | qCDebug(QTMIR_SCREENS) << "Screen::setWindow - new geometry for shell surface" << window->window() << geometry(); | ||
515 | 308 | m_screenWindow->setGeometry(geometry()); | ||
516 | 309 | } | ||
517 | 310 | } | ||
518 | 300 | } | 311 | } |
519 | 301 | 312 | ||
520 | 302 | void Screen::setMirDisplayBuffer(mir::graphics::DisplayBuffer *buffer, mir::graphics::DisplaySyncGroup *group) | 313 | void Screen::setMirDisplayBuffer(mir::graphics::DisplayBuffer *buffer, mir::graphics::DisplaySyncGroup *group) |
521 | @@ -334,3 +345,12 @@ | |||
522 | 334 | { | 345 | { |
523 | 335 | m_renderTarget->release_current(); | 346 | m_renderTarget->release_current(); |
524 | 336 | } | 347 | } |
525 | 348 | |||
526 | 349 | bool Screen::internalDisplay() const | ||
527 | 350 | { | ||
528 | 351 | using namespace mir::graphics; | ||
529 | 352 | if (m_type == DisplayConfigurationOutputType::lvds || m_type == DisplayConfigurationOutputType::edp) { | ||
530 | 353 | return true; | ||
531 | 354 | } | ||
532 | 355 | return false; | ||
533 | 356 | } | ||
534 | 337 | 357 | ||
535 | === modified file 'src/platforms/mirserver/screen.h' | |||
536 | --- src/platforms/mirserver/screen.h 2015-10-14 22:59:04 +0000 | |||
537 | +++ src/platforms/mirserver/screen.h 2016-03-11 11:36:44 +0000 | |||
538 | @@ -53,7 +53,6 @@ | |||
539 | 53 | Qt::ScreenOrientation orientation() const override { return m_currentOrientation; } | 53 | Qt::ScreenOrientation orientation() const override { return m_currentOrientation; } |
540 | 54 | QPlatformCursor *cursor() const override; | 54 | QPlatformCursor *cursor() const override; |
541 | 55 | 55 | ||
542 | 56 | void toggleSensors(const bool enable) const; | ||
543 | 57 | mir::graphics::DisplayConfigurationOutputType outputType() const { return m_type; } | 56 | mir::graphics::DisplayConfigurationOutputType outputType() const { return m_type; } |
544 | 58 | 57 | ||
545 | 59 | ScreenWindow* window() const; | 58 | ScreenWindow* window() const; |
546 | @@ -79,6 +78,9 @@ | |||
547 | 79 | void doneCurrent(); | 78 | void doneCurrent(); |
548 | 80 | 79 | ||
549 | 81 | private: | 80 | private: |
550 | 81 | void toggleSensors(const bool enable) const; | ||
551 | 82 | bool internalDisplay() const; | ||
552 | 83 | |||
553 | 82 | QRect m_geometry; | 84 | QRect m_geometry; |
554 | 83 | int m_depth; | 85 | int m_depth; |
555 | 84 | QImage::Format m_format; | 86 | QImage::Format m_format; |
556 | 85 | 87 | ||
557 | === modified file 'src/platforms/mirserver/screenwindow.cpp' | |||
558 | --- src/platforms/mirserver/screenwindow.cpp 2015-10-15 07:05:16 +0000 | |||
559 | +++ src/platforms/mirserver/screenwindow.cpp 2016-03-11 11:36:44 +0000 | |||
560 | @@ -89,7 +89,7 @@ | |||
561 | 89 | auto renderer = QSGRenderLoop::instance(); | 89 | auto renderer = QSGRenderLoop::instance(); |
562 | 90 | if (exposed) { | 90 | if (exposed) { |
563 | 91 | renderer->show(quickWindow); | 91 | renderer->show(quickWindow); |
565 | 92 | QWindowSystemInterface::handleExposeEvent(window(), QRegion()); // else it won't redraw | 92 | QWindowSystemInterface::handleExposeEvent(window(), geometry()); // else it won't redraw |
566 | 93 | } else { | 93 | } else { |
567 | 94 | quickWindow->setPersistentOpenGLContext(false); | 94 | quickWindow->setPersistentOpenGLContext(false); |
568 | 95 | quickWindow->setPersistentSceneGraph(false); | 95 | quickWindow->setPersistentSceneGraph(false); |
569 | 96 | 96 | ||
570 | === added directory 'src/platforms/mirserver/wm-wip' | |||
571 | === added file 'src/platforms/mirserver/wm-wip/CMakeLists.txt' | |||
572 | --- src/platforms/mirserver/wm-wip/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
573 | +++ src/platforms/mirserver/wm-wip/CMakeLists.txt 2016-03-11 11:36:44 +0000 | |||
574 | @@ -0,0 +1,22 @@ | |||
575 | 1 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -fPIC") | ||
576 | 2 | |||
577 | 3 | add_library(experimentalwindowmanager STATIC | ||
578 | 4 | server_example_basic_window_manager.cpp | ||
579 | 5 | server_example_basic_window_manager.h | ||
580 | 6 | server_example_window_management_info.cpp | ||
581 | 7 | server_example_window_management_info.h | ||
582 | 8 | ) | ||
583 | 9 | |||
584 | 10 | |||
585 | 11 | if (EXAMPLE_MIR_WINDOW_MANAGERS) | ||
586 | 12 | |||
587 | 13 | add_library(examplewindowmanager STATIC | ||
588 | 14 | server_example_canonical_window_manager.h | ||
589 | 15 | server_example_tiling_window_manager.h | ||
590 | 16 | server_example_window_management.h | ||
591 | 17 | server_example_canonical_window_manager.cpp | ||
592 | 18 | server_example_tiling_window_manager.cpp | ||
593 | 19 | server_example_window_management.cpp | ||
594 | 20 | ) | ||
595 | 21 | |||
596 | 22 | endif() | ||
597 | 0 | 23 | ||
598 | === added file 'src/platforms/mirserver/wm-wip/README' | |||
599 | --- src/platforms/mirserver/wm-wip/README 1970-01-01 00:00:00 +0000 | |||
600 | +++ src/platforms/mirserver/wm-wip/README 2016-03-11 11:36:44 +0000 | |||
601 | @@ -0,0 +1,5 @@ | |||
602 | 1 | examples for mir clients. you should have package 'libmirclient-dev' installed | ||
603 | 2 | |||
604 | 3 | you can compile with a command like: | ||
605 | 4 | g++ -std=c++0x -o mir_demo_client_scroll `pkg-config --libs --cflags mirclient` demo_client_scroll.cpp graphics_utils.cpp | ||
606 | 5 | gcc -o mir_demo_client_flicker `pkg-config --libs --cflags mirclient` demo_client_flicker.c | ||
607 | 0 | 6 | ||
608 | === added file 'src/platforms/mirserver/wm-wip/server_example_basic_window_manager.cpp' | |||
609 | --- src/platforms/mirserver/wm-wip/server_example_basic_window_manager.cpp 1970-01-01 00:00:00 +0000 | |||
610 | +++ src/platforms/mirserver/wm-wip/server_example_basic_window_manager.cpp 2016-03-11 11:36:44 +0000 | |||
611 | @@ -0,0 +1,312 @@ | |||
612 | 1 | /* | ||
613 | 2 | * Copyright © 2015 Canonical Ltd. | ||
614 | 3 | * | ||
615 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
616 | 5 | * under the terms of the GNU General Public License version 3, | ||
617 | 6 | * as published by the Free Software Foundation. | ||
618 | 7 | * | ||
619 | 8 | * This program is distributed in the hope that it will be useful, | ||
620 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
621 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
622 | 11 | * GNU General Public License for more details. | ||
623 | 12 | * | ||
624 | 13 | * You should have received a copy of the GNU General Public License | ||
625 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
626 | 15 | * | ||
627 | 16 | * Authored by: Alan Griffiths <alan@octopull.co.uk> | ||
628 | 17 | */ | ||
629 | 18 | |||
630 | 19 | #include "server_example_basic_window_manager.h" | ||
631 | 20 | |||
632 | 21 | #include "mir/scene/session.h" | ||
633 | 22 | #include "mir/scene/surface.h" | ||
634 | 23 | #include "mir/scene/surface_creation_parameters.h" | ||
635 | 24 | |||
636 | 25 | namespace me = mir::examples; | ||
637 | 26 | |||
638 | 27 | me::BasicWindowManager::BasicWindowManager( | ||
639 | 28 | shell::FocusController* focus_controller, | ||
640 | 29 | std::unique_ptr<WindowManagementPolicy> policy) : | ||
641 | 30 | focus_controller(focus_controller), | ||
642 | 31 | policy(std::move(policy)) | ||
643 | 32 | { | ||
644 | 33 | } | ||
645 | 34 | |||
646 | 35 | void me::BasicWindowManager::add_session(std::shared_ptr<scene::Session> const& session) | ||
647 | 36 | { | ||
648 | 37 | std::lock_guard<decltype(mutex)> lock(mutex); | ||
649 | 38 | session_info[session] = SessionInfo(); | ||
650 | 39 | policy->handle_session_info_updated(session_info, displays); | ||
651 | 40 | } | ||
652 | 41 | |||
653 | 42 | void me::BasicWindowManager::remove_session(std::shared_ptr<scene::Session> const& session) | ||
654 | 43 | { | ||
655 | 44 | std::lock_guard<decltype(mutex)> lock(mutex); | ||
656 | 45 | session_info.erase(session); | ||
657 | 46 | policy->handle_session_info_updated(session_info, displays); | ||
658 | 47 | } | ||
659 | 48 | |||
660 | 49 | auto me::BasicWindowManager::add_surface( | ||
661 | 50 | std::shared_ptr<scene::Session> const& session, | ||
662 | 51 | scene::SurfaceCreationParameters const& params, | ||
663 | 52 | std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build) | ||
664 | 53 | -> frontend::SurfaceId | ||
665 | 54 | { | ||
666 | 55 | std::lock_guard<decltype(mutex)> lock(mutex); | ||
667 | 56 | scene::SurfaceCreationParameters const placed_params = policy->handle_place_new_surface(session, params); | ||
668 | 57 | auto const result = build(session, placed_params); | ||
669 | 58 | auto const surface = session->surface(result); | ||
670 | 59 | surface_info.emplace(surface, SurfaceInfo{session, surface, placed_params}); | ||
671 | 60 | policy->handle_new_surface(session, surface); | ||
672 | 61 | policy->generate_decorations_for(session, surface, surface_info, build); | ||
673 | 62 | return result; | ||
674 | 63 | } | ||
675 | 64 | |||
676 | 65 | void me::BasicWindowManager::modify_surface( | ||
677 | 66 | std::shared_ptr<scene::Session> const& session, | ||
678 | 67 | std::shared_ptr<scene::Surface> const& surface, | ||
679 | 68 | shell::SurfaceSpecification const& modifications) | ||
680 | 69 | { | ||
681 | 70 | std::lock_guard<decltype(mutex)> lock(mutex); | ||
682 | 71 | policy->handle_modify_surface(session, surface, modifications); | ||
683 | 72 | } | ||
684 | 73 | |||
685 | 74 | void me::BasicWindowManager::remove_surface( | ||
686 | 75 | std::shared_ptr<scene::Session> const& session, | ||
687 | 76 | std::weak_ptr<scene::Surface> const& surface) | ||
688 | 77 | { | ||
689 | 78 | std::lock_guard<decltype(mutex)> lock(mutex); | ||
690 | 79 | policy->handle_delete_surface(session, surface); | ||
691 | 80 | |||
692 | 81 | surface_info.erase(surface); | ||
693 | 82 | } | ||
694 | 83 | |||
695 | 84 | void me::BasicWindowManager::forget(std::weak_ptr<scene::Surface> const& surface) | ||
696 | 85 | { | ||
697 | 86 | surface_info.erase(surface); | ||
698 | 87 | } | ||
699 | 88 | |||
700 | 89 | void me::BasicWindowManager::add_display(geometry::Rectangle const& area) | ||
701 | 90 | { | ||
702 | 91 | std::lock_guard<decltype(mutex)> lock(mutex); | ||
703 | 92 | displays.add(area); | ||
704 | 93 | policy->handle_displays_updated(session_info, displays); | ||
705 | 94 | } | ||
706 | 95 | |||
707 | 96 | void me::BasicWindowManager::remove_display(geometry::Rectangle const& area) | ||
708 | 97 | { | ||
709 | 98 | std::lock_guard<decltype(mutex)> lock(mutex); | ||
710 | 99 | displays.remove(area); | ||
711 | 100 | policy->handle_displays_updated(session_info, displays); | ||
712 | 101 | } | ||
713 | 102 | |||
714 | 103 | bool me::BasicWindowManager::handle_keyboard_event(MirKeyboardEvent const* event) | ||
715 | 104 | { | ||
716 | 105 | std::lock_guard<decltype(mutex)> lock(mutex); | ||
717 | 106 | update_event_timestamp(event); | ||
718 | 107 | return policy->handle_keyboard_event(event); | ||
719 | 108 | } | ||
720 | 109 | |||
721 | 110 | bool me::BasicWindowManager::handle_touch_event(MirTouchEvent const* event) | ||
722 | 111 | { | ||
723 | 112 | std::lock_guard<decltype(mutex)> lock(mutex); | ||
724 | 113 | update_event_timestamp(event); | ||
725 | 114 | return policy->handle_touch_event(event); | ||
726 | 115 | } | ||
727 | 116 | |||
728 | 117 | bool me::BasicWindowManager::handle_pointer_event(MirPointerEvent const* event) | ||
729 | 118 | { | ||
730 | 119 | std::lock_guard<decltype(mutex)> lock(mutex); | ||
731 | 120 | update_event_timestamp(event); | ||
732 | 121 | |||
733 | 122 | cursor = { | ||
734 | 123 | mir_pointer_event_axis_value(event, mir_pointer_axis_x), | ||
735 | 124 | mir_pointer_event_axis_value(event, mir_pointer_axis_y)}; | ||
736 | 125 | |||
737 | 126 | return policy->handle_pointer_event(event); | ||
738 | 127 | } | ||
739 | 128 | |||
740 | 129 | void me::BasicWindowManager::handle_raise_surface( | ||
741 | 130 | std::shared_ptr<scene::Session> const& session, | ||
742 | 131 | std::shared_ptr<scene::Surface> const& surface, | ||
743 | 132 | uint64_t timestamp) | ||
744 | 133 | { | ||
745 | 134 | std::lock_guard<decltype(mutex)> lock(mutex); | ||
746 | 135 | if (timestamp >= last_input_event_timestamp) | ||
747 | 136 | policy->handle_raise_surface(session, surface); | ||
748 | 137 | } | ||
749 | 138 | |||
750 | 139 | int me::BasicWindowManager::set_surface_attribute( | ||
751 | 140 | std::shared_ptr<scene::Session> const& /*session*/, | ||
752 | 141 | std::shared_ptr<scene::Surface> const& surface, | ||
753 | 142 | MirSurfaceAttrib attrib, | ||
754 | 143 | int value) | ||
755 | 144 | { | ||
756 | 145 | std::lock_guard<decltype(mutex)> lock(mutex); | ||
757 | 146 | switch (attrib) | ||
758 | 147 | { | ||
759 | 148 | case mir_surface_attrib_state: | ||
760 | 149 | { | ||
761 | 150 | auto const state = policy->handle_set_state(surface, MirSurfaceState(value)); | ||
762 | 151 | return surface->configure(attrib, state); | ||
763 | 152 | } | ||
764 | 153 | default: | ||
765 | 154 | return surface->configure(attrib, value); | ||
766 | 155 | } | ||
767 | 156 | } | ||
768 | 157 | |||
769 | 158 | auto me::BasicWindowManager::find_session(std::function<bool(SessionInfo const& info)> const& predicate) | ||
770 | 159 | -> std::shared_ptr<scene::Session> | ||
771 | 160 | { | ||
772 | 161 | for(auto& info : session_info) | ||
773 | 162 | { | ||
774 | 163 | if (predicate(info.second)) | ||
775 | 164 | { | ||
776 | 165 | return info.first.lock(); | ||
777 | 166 | } | ||
778 | 167 | } | ||
779 | 168 | |||
780 | 169 | return std::shared_ptr<scene::Session>{}; | ||
781 | 170 | } | ||
782 | 171 | |||
783 | 172 | auto me::BasicWindowManager::info_for(std::weak_ptr<scene::Session> const& session) const | ||
784 | 173 | -> SessionInfo& | ||
785 | 174 | { | ||
786 | 175 | return const_cast<SessionInfo&>(session_info.at(session)); | ||
787 | 176 | } | ||
788 | 177 | |||
789 | 178 | auto me::BasicWindowManager::info_for(std::weak_ptr<scene::Surface> const& surface) const | ||
790 | 179 | -> SurfaceInfo& | ||
791 | 180 | { | ||
792 | 181 | return const_cast<SurfaceInfo&>(surface_info.at(surface)); | ||
793 | 182 | } | ||
794 | 183 | |||
795 | 184 | auto me::BasicWindowManager::focused_session() const | ||
796 | 185 | -> std::shared_ptr<scene::Session> | ||
797 | 186 | { | ||
798 | 187 | return focus_controller->focused_session(); | ||
799 | 188 | } | ||
800 | 189 | |||
801 | 190 | auto me::BasicWindowManager::focused_surface() const | ||
802 | 191 | ->std::shared_ptr<scene::Surface> | ||
803 | 192 | { | ||
804 | 193 | return focus_controller->focused_surface(); | ||
805 | 194 | } | ||
806 | 195 | |||
807 | 196 | void me::BasicWindowManager::focus_next_session() | ||
808 | 197 | { | ||
809 | 198 | focus_controller->focus_next_session(); | ||
810 | 199 | } | ||
811 | 200 | |||
812 | 201 | void me::BasicWindowManager::set_focus_to( | ||
813 | 202 | std::shared_ptr<scene::Session> const& focus, | ||
814 | 203 | std::shared_ptr<scene::Surface> const& surface) | ||
815 | 204 | { | ||
816 | 205 | focus_controller->set_focus_to(focus, surface); | ||
817 | 206 | } | ||
818 | 207 | |||
819 | 208 | auto me::BasicWindowManager::surface_at(geometry::Point cursor) const | ||
820 | 209 | -> std::shared_ptr<scene::Surface> | ||
821 | 210 | { | ||
822 | 211 | return focus_controller->surface_at(cursor); | ||
823 | 212 | } | ||
824 | 213 | |||
825 | 214 | auto me::BasicWindowManager::active_display() | ||
826 | 215 | -> geometry::Rectangle const | ||
827 | 216 | { | ||
828 | 217 | geometry::Rectangle result; | ||
829 | 218 | |||
830 | 219 | // 1. If a window has input focus, whichever display contains the largest | ||
831 | 220 | // proportion of the area of that window. | ||
832 | 221 | if (auto const surface = focused_surface()) | ||
833 | 222 | { | ||
834 | 223 | auto const surface_rect = surface->input_bounds(); | ||
835 | 224 | int max_overlap_area = -1; | ||
836 | 225 | |||
837 | 226 | for (auto const& display : displays) | ||
838 | 227 | { | ||
839 | 228 | auto const intersection = surface_rect.intersection_with(display).size; | ||
840 | 229 | if (intersection.width.as_int()*intersection.height.as_int() > max_overlap_area) | ||
841 | 230 | { | ||
842 | 231 | max_overlap_area = intersection.width.as_int()*intersection.height.as_int(); | ||
843 | 232 | result = display; | ||
844 | 233 | } | ||
845 | 234 | } | ||
846 | 235 | return result; | ||
847 | 236 | } | ||
848 | 237 | |||
849 | 238 | // 2. Otherwise, if any window previously had input focus, for the window that had | ||
850 | 239 | // it most recently, the display that contained the largest proportion of the | ||
851 | 240 | // area of that window at the moment it closed, as long as that display is still | ||
852 | 241 | // available. | ||
853 | 242 | |||
854 | 243 | // 3. Otherwise, the display that contains the pointer, if there is one. | ||
855 | 244 | for (auto const& display : displays) | ||
856 | 245 | { | ||
857 | 246 | if (display.contains(cursor)) | ||
858 | 247 | { | ||
859 | 248 | // Ignore the (unspecified) possiblity of overlapping displays | ||
860 | 249 | return display; | ||
861 | 250 | } | ||
862 | 251 | } | ||
863 | 252 | |||
864 | 253 | // 4. Otherwise, the primary display, if there is one (for example, the laptop display). | ||
865 | 254 | |||
866 | 255 | // 5. Otherwise, the first display. | ||
867 | 256 | if (displays.size()) | ||
868 | 257 | result = *displays.begin(); | ||
869 | 258 | |||
870 | 259 | return result; | ||
871 | 260 | } | ||
872 | 261 | |||
873 | 262 | void me::BasicWindowManager::raise_tree(std::shared_ptr<scene::Surface> const& root) | ||
874 | 263 | { | ||
875 | 264 | SurfaceSet surfaces; | ||
876 | 265 | std::function<void(std::weak_ptr<scene::Surface> const& surface)> const add_children = | ||
877 | 266 | [&,this](std::weak_ptr<scene::Surface> const& surface) | ||
878 | 267 | { | ||
879 | 268 | auto const& info = info_for(surface); | ||
880 | 269 | surfaces.insert(begin(info.children), end(info.children)); | ||
881 | 270 | for (auto const& child : info.children) | ||
882 | 271 | add_children(child); | ||
883 | 272 | }; | ||
884 | 273 | |||
885 | 274 | surfaces.insert(root); | ||
886 | 275 | add_children(root); | ||
887 | 276 | |||
888 | 277 | focus_controller->raise(surfaces); | ||
889 | 278 | } | ||
890 | 279 | |||
891 | 280 | void me::BasicWindowManager::update_event_timestamp(MirKeyboardEvent const* kev) | ||
892 | 281 | { | ||
893 | 282 | auto iev = mir_keyboard_event_input_event(kev); | ||
894 | 283 | last_input_event_timestamp = mir_input_event_get_event_time(iev); | ||
895 | 284 | } | ||
896 | 285 | |||
897 | 286 | void me::BasicWindowManager::update_event_timestamp(MirPointerEvent const* pev) | ||
898 | 287 | { | ||
899 | 288 | auto iev = mir_pointer_event_input_event(pev); | ||
900 | 289 | auto pointer_action = mir_pointer_event_action(pev); | ||
901 | 290 | |||
902 | 291 | if (pointer_action == mir_pointer_action_button_up || | ||
903 | 292 | pointer_action == mir_pointer_action_button_down) | ||
904 | 293 | { | ||
905 | 294 | last_input_event_timestamp = mir_input_event_get_event_time(iev); | ||
906 | 295 | } | ||
907 | 296 | } | ||
908 | 297 | |||
909 | 298 | void me::BasicWindowManager::update_event_timestamp(MirTouchEvent const* tev) | ||
910 | 299 | { | ||
911 | 300 | auto iev = mir_touch_event_input_event(tev); | ||
912 | 301 | auto touch_count = mir_touch_event_point_count(tev); | ||
913 | 302 | for (unsigned i = 0; i < touch_count; i++) | ||
914 | 303 | { | ||
915 | 304 | auto touch_action = mir_touch_event_action(tev, i); | ||
916 | 305 | if (touch_action == mir_touch_action_up || | ||
917 | 306 | touch_action == mir_touch_action_down) | ||
918 | 307 | { | ||
919 | 308 | last_input_event_timestamp = mir_input_event_get_event_time(iev); | ||
920 | 309 | break; | ||
921 | 310 | } | ||
922 | 311 | } | ||
923 | 312 | } | ||
924 | 0 | 313 | ||
925 | === added file 'src/platforms/mirserver/wm-wip/server_example_basic_window_manager.h' | |||
926 | --- src/platforms/mirserver/wm-wip/server_example_basic_window_manager.h 1970-01-01 00:00:00 +0000 | |||
927 | +++ src/platforms/mirserver/wm-wip/server_example_basic_window_manager.h 2016-03-11 11:36:44 +0000 | |||
928 | @@ -0,0 +1,252 @@ | |||
929 | 1 | /* | ||
930 | 2 | * Copyright © 2015 Canonical Ltd. | ||
931 | 3 | * | ||
932 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
933 | 5 | * under the terms of the GNU General Public License version 3, | ||
934 | 6 | * as published by the Free Software Foundation. | ||
935 | 7 | * | ||
936 | 8 | * This program is distributed in the hope that it will be useful, | ||
937 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
938 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
939 | 11 | * GNU General Public License for more details. | ||
940 | 12 | * | ||
941 | 13 | * You should have received a copy of the GNU General Public License | ||
942 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
943 | 15 | * | ||
944 | 16 | * Authored By: Alan Griffiths <alan@octopull.co.uk> | ||
945 | 17 | */ | ||
946 | 18 | |||
947 | 19 | #ifndef MIR_EXAMPLE_BASIC_WINDOW_MANAGER_H_ | ||
948 | 20 | #define MIR_EXAMPLE_BASIC_WINDOW_MANAGER_H_ | ||
949 | 21 | |||
950 | 22 | #include "server_example_window_management_info.h" | ||
951 | 23 | |||
952 | 24 | #include "mir/geometry/rectangles.h" | ||
953 | 25 | #include "mir/shell/abstract_shell.h" | ||
954 | 26 | #include "mir/shell/window_manager.h" | ||
955 | 27 | |||
956 | 28 | #include <map> | ||
957 | 29 | #include <mutex> | ||
958 | 30 | |||
959 | 31 | ///\example server_example_basic_window_manager.h | ||
960 | 32 | /// A generic policy-based window manager implementation | ||
961 | 33 | |||
962 | 34 | namespace mir | ||
963 | 35 | { | ||
964 | 36 | namespace examples | ||
965 | 37 | { | ||
966 | 38 | using shell::SurfaceSet; | ||
967 | 39 | |||
968 | 40 | /// The interface through which the policy instructs the controller. | ||
969 | 41 | /// These functions assume that the BasicWindowManager data structures can be accessed freely. | ||
970 | 42 | /// I.e. should only be invoked by the policy handle_... methods (where any necessary locks are held). | ||
971 | 43 | class WindowManagerTools | ||
972 | 44 | { | ||
973 | 45 | public: | ||
974 | 46 | using SurfaceInfoMap = std::map<std::weak_ptr<scene::Surface>, SurfaceInfo, std::owner_less<std::weak_ptr<scene::Surface>>>; | ||
975 | 47 | using SessionInfoMap = std::map<std::weak_ptr<scene::Session>, SessionInfo, std::owner_less<std::weak_ptr<scene::Session>>>; | ||
976 | 48 | |||
977 | 49 | virtual auto find_session(std::function<bool(SessionInfo const& info)> const& predicate) | ||
978 | 50 | -> std::shared_ptr<scene::Session> = 0; | ||
979 | 51 | |||
980 | 52 | virtual auto info_for(std::weak_ptr<scene::Session> const& session) const -> SessionInfo& = 0; | ||
981 | 53 | |||
982 | 54 | virtual auto info_for(std::weak_ptr<scene::Surface> const& surface) const -> SurfaceInfo& = 0; | ||
983 | 55 | |||
984 | 56 | virtual std::shared_ptr<scene::Session> focused_session() const = 0; | ||
985 | 57 | |||
986 | 58 | virtual std::shared_ptr<scene::Surface> focused_surface() const = 0; | ||
987 | 59 | |||
988 | 60 | virtual void focus_next_session() = 0; | ||
989 | 61 | |||
990 | 62 | virtual void set_focus_to( | ||
991 | 63 | std::shared_ptr<scene::Session> const& focus, | ||
992 | 64 | std::shared_ptr<scene::Surface> const& surface) = 0; | ||
993 | 65 | |||
994 | 66 | virtual auto surface_at(geometry::Point cursor) const -> std::shared_ptr<scene::Surface> = 0; | ||
995 | 67 | |||
996 | 68 | virtual auto active_display() -> geometry::Rectangle const = 0; | ||
997 | 69 | |||
998 | 70 | virtual void forget(std::weak_ptr<scene::Surface> const& surface) = 0; | ||
999 | 71 | |||
1000 | 72 | virtual void raise_tree(std::shared_ptr<scene::Surface> const& root) = 0; | ||
1001 | 73 | |||
1002 | 74 | virtual ~WindowManagerTools() = default; | ||
1003 | 75 | WindowManagerTools() = default; | ||
1004 | 76 | WindowManagerTools(WindowManagerTools const&) = delete; | ||
1005 | 77 | WindowManagerTools& operator=(WindowManagerTools const&) = delete; | ||
1006 | 78 | }; | ||
1007 | 79 | |||
1008 | 80 | class WindowManagementPolicy | ||
1009 | 81 | { | ||
1010 | 82 | public: | ||
1011 | 83 | using SessionInfoMap = typename WindowManagerTools::SessionInfoMap; | ||
1012 | 84 | using SurfaceInfoMap = typename WindowManagerTools::SurfaceInfoMap; | ||
1013 | 85 | |||
1014 | 86 | virtual void handle_session_info_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays) = 0; | ||
1015 | 87 | |||
1016 | 88 | virtual void handle_displays_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays) = 0; | ||
1017 | 89 | |||
1018 | 90 | virtual auto handle_place_new_surface( | ||
1019 | 91 | std::shared_ptr<scene::Session> const& session, | ||
1020 | 92 | scene::SurfaceCreationParameters const& request_parameters) | ||
1021 | 93 | -> scene::SurfaceCreationParameters = 0; | ||
1022 | 94 | |||
1023 | 95 | virtual void handle_new_surface(std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface) = 0; | ||
1024 | 96 | |||
1025 | 97 | virtual void handle_modify_surface( | ||
1026 | 98 | std::shared_ptr<scene::Session> const& session, | ||
1027 | 99 | std::shared_ptr<scene::Surface> const& surface, | ||
1028 | 100 | shell::SurfaceSpecification const& modifications) = 0; | ||
1029 | 101 | |||
1030 | 102 | virtual void handle_delete_surface(std::shared_ptr<scene::Session> const& session, std::weak_ptr<scene::Surface> const& surface) = 0; | ||
1031 | 103 | |||
1032 | 104 | virtual int handle_set_state(std::shared_ptr<scene::Surface> const& surface, MirSurfaceState value) = 0; | ||
1033 | 105 | |||
1034 | 106 | virtual void generate_decorations_for( | ||
1035 | 107 | std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface, | ||
1036 | 108 | SurfaceInfoMap& surface_info, | ||
1037 | 109 | std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const&, scene::SurfaceCreationParameters const&)> const& build) = 0; | ||
1038 | 110 | |||
1039 | 111 | virtual bool handle_keyboard_event(MirKeyboardEvent const* event) = 0; | ||
1040 | 112 | |||
1041 | 113 | virtual bool handle_touch_event(MirTouchEvent const* event) = 0; | ||
1042 | 114 | |||
1043 | 115 | virtual bool handle_pointer_event(MirPointerEvent const* event) = 0; | ||
1044 | 116 | |||
1045 | 117 | virtual void handle_raise_surface( | ||
1046 | 118 | std::shared_ptr<scene::Session> const& session, | ||
1047 | 119 | std::shared_ptr<scene::Surface> const& surface) = 0; | ||
1048 | 120 | |||
1049 | 121 | virtual ~WindowManagementPolicy() = default; | ||
1050 | 122 | WindowManagementPolicy() = default; | ||
1051 | 123 | WindowManagementPolicy(WindowManagementPolicy const&) = delete; | ||
1052 | 124 | WindowManagementPolicy& operator=(WindowManagementPolicy const&) = delete; | ||
1053 | 125 | }; | ||
1054 | 126 | |||
1055 | 127 | /// A policy based window manager. | ||
1056 | 128 | /// This takes care of the management of any meta implementation held for the sessions and surfaces. | ||
1057 | 129 | class BasicWindowManager : public virtual shell::WindowManager, | ||
1058 | 130 | protected WindowManagerTools | ||
1059 | 131 | { | ||
1060 | 132 | protected: | ||
1061 | 133 | BasicWindowManager( | ||
1062 | 134 | shell::FocusController* focus_controller, | ||
1063 | 135 | std::unique_ptr<WindowManagementPolicy> policy); | ||
1064 | 136 | |||
1065 | 137 | public: | ||
1066 | 138 | using typename WindowManagerTools::SurfaceInfoMap; | ||
1067 | 139 | using typename WindowManagerTools::SessionInfoMap; | ||
1068 | 140 | |||
1069 | 141 | void add_session(std::shared_ptr<scene::Session> const& session) override; | ||
1070 | 142 | |||
1071 | 143 | void remove_session(std::shared_ptr<scene::Session> const& session) override; | ||
1072 | 144 | |||
1073 | 145 | auto add_surface( | ||
1074 | 146 | std::shared_ptr<scene::Session> const& session, | ||
1075 | 147 | scene::SurfaceCreationParameters const& params, | ||
1076 | 148 | std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build) | ||
1077 | 149 | -> frontend::SurfaceId override; | ||
1078 | 150 | |||
1079 | 151 | void modify_surface( | ||
1080 | 152 | std::shared_ptr<scene::Session> const& session, | ||
1081 | 153 | std::shared_ptr<scene::Surface> const& surface, | ||
1082 | 154 | shell::SurfaceSpecification const& modifications) override; | ||
1083 | 155 | |||
1084 | 156 | void remove_surface( | ||
1085 | 157 | std::shared_ptr<scene::Session> const& session, | ||
1086 | 158 | std::weak_ptr<scene::Surface> const& surface) override; | ||
1087 | 159 | |||
1088 | 160 | void forget(std::weak_ptr<scene::Surface> const& surface) override; | ||
1089 | 161 | |||
1090 | 162 | void add_display(geometry::Rectangle const& area) override; | ||
1091 | 163 | |||
1092 | 164 | void remove_display(geometry::Rectangle const& area) override; | ||
1093 | 165 | |||
1094 | 166 | bool handle_keyboard_event(MirKeyboardEvent const* event) override; | ||
1095 | 167 | |||
1096 | 168 | bool handle_touch_event(MirTouchEvent const* event) override; | ||
1097 | 169 | |||
1098 | 170 | bool handle_pointer_event(MirPointerEvent const* event) override; | ||
1099 | 171 | |||
1100 | 172 | void handle_raise_surface( | ||
1101 | 173 | std::shared_ptr<scene::Session> const& session, | ||
1102 | 174 | std::shared_ptr<scene::Surface> const& surface, | ||
1103 | 175 | uint64_t timestamp) override; | ||
1104 | 176 | |||
1105 | 177 | int set_surface_attribute( | ||
1106 | 178 | std::shared_ptr<scene::Session> const& /*session*/, | ||
1107 | 179 | std::shared_ptr<scene::Surface> const& surface, | ||
1108 | 180 | MirSurfaceAttrib attrib, | ||
1109 | 181 | int value) override; | ||
1110 | 182 | |||
1111 | 183 | auto find_session(std::function<bool(SessionInfo const& info)> const& predicate) | ||
1112 | 184 | -> std::shared_ptr<scene::Session> override; | ||
1113 | 185 | |||
1114 | 186 | auto info_for(std::weak_ptr<scene::Session> const& session) const -> SessionInfo& override; | ||
1115 | 187 | |||
1116 | 188 | auto info_for(std::weak_ptr<scene::Surface> const& surface) const -> SurfaceInfo& override; | ||
1117 | 189 | |||
1118 | 190 | std::shared_ptr<scene::Session> focused_session() const override; | ||
1119 | 191 | |||
1120 | 192 | std::shared_ptr<scene::Surface> focused_surface() const override; | ||
1121 | 193 | |||
1122 | 194 | void focus_next_session() override; | ||
1123 | 195 | |||
1124 | 196 | void set_focus_to( | ||
1125 | 197 | std::shared_ptr<scene::Session> const& focus, | ||
1126 | 198 | std::shared_ptr<scene::Surface> const& surface) override; | ||
1127 | 199 | |||
1128 | 200 | auto surface_at(geometry::Point cursor) const -> std::shared_ptr<scene::Surface> override; | ||
1129 | 201 | |||
1130 | 202 | auto active_display() -> geometry::Rectangle const override; | ||
1131 | 203 | |||
1132 | 204 | void raise_tree(std::shared_ptr<scene::Surface> const& root) override; | ||
1133 | 205 | |||
1134 | 206 | private: | ||
1135 | 207 | shell::FocusController* const focus_controller; | ||
1136 | 208 | std::unique_ptr<WindowManagementPolicy> const policy; | ||
1137 | 209 | |||
1138 | 210 | std::mutex mutex; | ||
1139 | 211 | SessionInfoMap session_info; | ||
1140 | 212 | SurfaceInfoMap surface_info; | ||
1141 | 213 | geometry::Rectangles displays; | ||
1142 | 214 | geometry::Point cursor; | ||
1143 | 215 | uint64_t last_input_event_timestamp{0}; | ||
1144 | 216 | |||
1145 | 217 | void update_event_timestamp(MirKeyboardEvent const* kev); | ||
1146 | 218 | void update_event_timestamp(MirPointerEvent const* pev); | ||
1147 | 219 | void update_event_timestamp(MirTouchEvent const* tev); | ||
1148 | 220 | }; | ||
1149 | 221 | |||
1150 | 222 | /// A policy based window manager. This exists to initialize BasicWindowManager and | ||
1151 | 223 | /// the WMPolicy (in an awkward manner). | ||
1152 | 224 | /// TODO revisit this initialization sequence. | ||
1153 | 225 | template<typename WMPolicy> | ||
1154 | 226 | class WindowManagerBuilder : public BasicWindowManager | ||
1155 | 227 | { | ||
1156 | 228 | public: | ||
1157 | 229 | |||
1158 | 230 | template <typename... PolicyArgs> | ||
1159 | 231 | WindowManagerBuilder( | ||
1160 | 232 | shell::FocusController* focus_controller, | ||
1161 | 233 | PolicyArgs&&... policy_args) : | ||
1162 | 234 | BasicWindowManager( | ||
1163 | 235 | focus_controller, | ||
1164 | 236 | build_policy(std::forward<PolicyArgs>(policy_args)...)) | ||
1165 | 237 | { | ||
1166 | 238 | } | ||
1167 | 239 | |||
1168 | 240 | private: | ||
1169 | 241 | template <typename... PolicyArgs> | ||
1170 | 242 | auto build_policy(PolicyArgs&&... policy_args) | ||
1171 | 243 | -> std::unique_ptr<WMPolicy> | ||
1172 | 244 | { | ||
1173 | 245 | return std::unique_ptr<WMPolicy>( | ||
1174 | 246 | new WMPolicy(this, std::forward<PolicyArgs>(policy_args)...)); | ||
1175 | 247 | } | ||
1176 | 248 | }; | ||
1177 | 249 | } | ||
1178 | 250 | } | ||
1179 | 251 | |||
1180 | 252 | #endif /* MIR_EXAMPLE_BASIC_WINDOW_MANAGER_H_ */ | ||
1181 | 0 | 253 | ||
1182 | === added file 'src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.cpp' | |||
1183 | --- src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.cpp 1970-01-01 00:00:00 +0000 | |||
1184 | +++ src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.cpp 2016-03-11 11:36:44 +0000 | |||
1185 | @@ -0,0 +1,946 @@ | |||
1186 | 1 | /* | ||
1187 | 2 | * Copyright © 2015 Canonical Ltd. | ||
1188 | 3 | * | ||
1189 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
1190 | 5 | * under the terms of the GNU General Public License version 3, | ||
1191 | 6 | * as published by the Free Software Foundation. | ||
1192 | 7 | * | ||
1193 | 8 | * This program is distributed in the hope that it will be useful, | ||
1194 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1195 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1196 | 11 | * GNU General Public License for more details. | ||
1197 | 12 | * | ||
1198 | 13 | * You should have received a copy of the GNU General Public License | ||
1199 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1200 | 15 | * | ||
1201 | 16 | * Authored By: Alan Griffiths <alan@octopull.co.uk> | ||
1202 | 17 | */ | ||
1203 | 18 | |||
1204 | 19 | #include "server_example_canonical_window_manager.h" | ||
1205 | 20 | |||
1206 | 21 | #include "mir/scene/session.h" | ||
1207 | 22 | #include "mir/scene/surface.h" | ||
1208 | 23 | #include "mir/scene/surface_creation_parameters.h" | ||
1209 | 24 | #include "mir/shell/surface_ready_observer.h" | ||
1210 | 25 | #include "mir/shell/display_layout.h" | ||
1211 | 26 | |||
1212 | 27 | #include <linux/input.h> | ||
1213 | 28 | #include <csignal> | ||
1214 | 29 | #include <algorithm> | ||
1215 | 30 | |||
1216 | 31 | namespace me = mir::examples; | ||
1217 | 32 | namespace ms = mir::scene; | ||
1218 | 33 | using namespace mir::geometry; | ||
1219 | 34 | |||
1220 | 35 | ///\example server_example_canonical_window_manager.cpp | ||
1221 | 36 | // Based on "Mir and Unity: Surfaces, input, and displays (v0.3)" | ||
1222 | 37 | |||
1223 | 38 | namespace | ||
1224 | 39 | { | ||
1225 | 40 | int const title_bar_height = 10; | ||
1226 | 41 | Size titlebar_size_for_window(Size window_size) | ||
1227 | 42 | { | ||
1228 | 43 | return {window_size.width, Height{title_bar_height}}; | ||
1229 | 44 | } | ||
1230 | 45 | |||
1231 | 46 | Point titlebar_position_for_window(Point window_position) | ||
1232 | 47 | { | ||
1233 | 48 | return { | ||
1234 | 49 | window_position.x, | ||
1235 | 50 | window_position.y - DeltaY(title_bar_height) | ||
1236 | 51 | }; | ||
1237 | 52 | } | ||
1238 | 53 | } | ||
1239 | 54 | |||
1240 | 55 | me::CanonicalWindowManagerPolicyCopy::CanonicalWindowManagerPolicyCopy( | ||
1241 | 56 | WindowManagerTools* const tools, | ||
1242 | 57 | std::shared_ptr<shell::DisplayLayout> const& display_layout) : | ||
1243 | 58 | tools{tools}, | ||
1244 | 59 | display_layout{display_layout} | ||
1245 | 60 | { | ||
1246 | 61 | } | ||
1247 | 62 | |||
1248 | 63 | void me::CanonicalWindowManagerPolicyCopy::click(Point cursor) | ||
1249 | 64 | { | ||
1250 | 65 | if (auto const surface = tools->surface_at(cursor)) | ||
1251 | 66 | select_active_surface(surface); | ||
1252 | 67 | } | ||
1253 | 68 | |||
1254 | 69 | void me::CanonicalWindowManagerPolicyCopy::handle_session_info_updated(SessionInfoMap& /*session_info*/, Rectangles const& /*displays*/) | ||
1255 | 70 | { | ||
1256 | 71 | } | ||
1257 | 72 | |||
1258 | 73 | void me::CanonicalWindowManagerPolicyCopy::handle_displays_updated(SessionInfoMap& /*session_info*/, Rectangles const& displays) | ||
1259 | 74 | { | ||
1260 | 75 | display_area = displays.bounding_rectangle(); | ||
1261 | 76 | |||
1262 | 77 | for (auto const weak_surface : fullscreen_surfaces) | ||
1263 | 78 | { | ||
1264 | 79 | if (auto const surface = weak_surface.lock()) | ||
1265 | 80 | { | ||
1266 | 81 | auto const& info = tools->info_for(weak_surface); | ||
1267 | 82 | Rectangle rect{surface->top_left(), surface->size()}; | ||
1268 | 83 | |||
1269 | 84 | display_layout->place_in_output(info.output_id.value(), rect); | ||
1270 | 85 | surface->move_to(rect.top_left); | ||
1271 | 86 | surface->resize(rect.size); | ||
1272 | 87 | } | ||
1273 | 88 | } | ||
1274 | 89 | } | ||
1275 | 90 | |||
1276 | 91 | void me::CanonicalWindowManagerPolicyCopy::resize(Point cursor) | ||
1277 | 92 | { | ||
1278 | 93 | select_active_surface(tools->surface_at(old_cursor)); | ||
1279 | 94 | resize(active_surface(), cursor, old_cursor, display_area); | ||
1280 | 95 | } | ||
1281 | 96 | |||
1282 | 97 | auto me::CanonicalWindowManagerPolicyCopy::handle_place_new_surface( | ||
1283 | 98 | std::shared_ptr<ms::Session> const& session, | ||
1284 | 99 | ms::SurfaceCreationParameters const& request_parameters) | ||
1285 | 100 | -> ms::SurfaceCreationParameters | ||
1286 | 101 | { | ||
1287 | 102 | auto parameters = request_parameters; | ||
1288 | 103 | auto surf_type = parameters.type.is_set() ? parameters.type.value() : mir_surface_type_normal; | ||
1289 | 104 | bool const needs_titlebar = SurfaceInfo::needs_titlebar(surf_type); | ||
1290 | 105 | |||
1291 | 106 | if (needs_titlebar) | ||
1292 | 107 | parameters.size.height = parameters.size.height + DeltaY{title_bar_height}; | ||
1293 | 108 | |||
1294 | 109 | if (!parameters.state.is_set()) | ||
1295 | 110 | parameters.state = mir_surface_state_restored; | ||
1296 | 111 | |||
1297 | 112 | auto const active_display = tools->active_display(); | ||
1298 | 113 | |||
1299 | 114 | auto const width = parameters.size.width.as_int(); | ||
1300 | 115 | auto const height = parameters.size.height.as_int(); | ||
1301 | 116 | |||
1302 | 117 | bool positioned = false; | ||
1303 | 118 | |||
1304 | 119 | auto const parent = parameters.parent.lock(); | ||
1305 | 120 | |||
1306 | 121 | if (parameters.output_id != mir::graphics::DisplayConfigurationOutputId{0}) | ||
1307 | 122 | { | ||
1308 | 123 | Rectangle rect{parameters.top_left, parameters.size}; | ||
1309 | 124 | display_layout->place_in_output(parameters.output_id, rect); | ||
1310 | 125 | parameters.top_left = rect.top_left; | ||
1311 | 126 | parameters.size = rect.size; | ||
1312 | 127 | parameters.state = mir_surface_state_fullscreen; | ||
1313 | 128 | positioned = true; | ||
1314 | 129 | } | ||
1315 | 130 | else if (!parent) // No parent => client can't suggest positioning | ||
1316 | 131 | { | ||
1317 | 132 | if (auto const default_surface = session->default_surface()) | ||
1318 | 133 | { | ||
1319 | 134 | static Displacement const offset{title_bar_height, title_bar_height}; | ||
1320 | 135 | |||
1321 | 136 | parameters.top_left = default_surface->top_left() + offset; | ||
1322 | 137 | |||
1323 | 138 | geometry::Rectangle display_for_app{default_surface->top_left(), default_surface->size()}; | ||
1324 | 139 | |||
1325 | 140 | display_layout->size_to_output(display_for_app); | ||
1326 | 141 | |||
1327 | 142 | positioned = display_for_app.overlaps(Rectangle{parameters.top_left, parameters.size}); | ||
1328 | 143 | } | ||
1329 | 144 | } | ||
1330 | 145 | |||
1331 | 146 | if (parent && parameters.aux_rect.is_set() && parameters.edge_attachment.is_set()) | ||
1332 | 147 | { | ||
1333 | 148 | auto const edge_attachment = parameters.edge_attachment.value(); | ||
1334 | 149 | auto const aux_rect = parameters.aux_rect.value(); | ||
1335 | 150 | auto const parent_top_left = parent->top_left(); | ||
1336 | 151 | auto const top_left = aux_rect.top_left -Point{} + parent_top_left; | ||
1337 | 152 | auto const top_right= aux_rect.top_right() -Point{} + parent_top_left; | ||
1338 | 153 | auto const bot_left = aux_rect.bottom_left()-Point{} + parent_top_left; | ||
1339 | 154 | |||
1340 | 155 | if (edge_attachment & mir_edge_attachment_vertical) | ||
1341 | 156 | { | ||
1342 | 157 | if (active_display.contains(top_right + Displacement{width, height})) | ||
1343 | 158 | { | ||
1344 | 159 | parameters.top_left = top_right; | ||
1345 | 160 | positioned = true; | ||
1346 | 161 | } | ||
1347 | 162 | else if (active_display.contains(top_left + Displacement{-width, height})) | ||
1348 | 163 | { | ||
1349 | 164 | parameters.top_left = top_left + Displacement{-width, 0}; | ||
1350 | 165 | positioned = true; | ||
1351 | 166 | } | ||
1352 | 167 | } | ||
1353 | 168 | |||
1354 | 169 | if (edge_attachment & mir_edge_attachment_horizontal) | ||
1355 | 170 | { | ||
1356 | 171 | if (active_display.contains(bot_left + Displacement{width, height})) | ||
1357 | 172 | { | ||
1358 | 173 | parameters.top_left = bot_left; | ||
1359 | 174 | positioned = true; | ||
1360 | 175 | } | ||
1361 | 176 | else if (active_display.contains(top_left + Displacement{width, -height})) | ||
1362 | 177 | { | ||
1363 | 178 | parameters.top_left = top_left + Displacement{0, -height}; | ||
1364 | 179 | positioned = true; | ||
1365 | 180 | } | ||
1366 | 181 | } | ||
1367 | 182 | } | ||
1368 | 183 | else if (parent) | ||
1369 | 184 | { | ||
1370 | 185 | // o Otherwise, if the dialog is not the same as any previous dialog for the | ||
1371 | 186 | // same parent window, and/or it does not have user-customized position: | ||
1372 | 187 | // o It should be optically centered relative to its parent, unless this | ||
1373 | 188 | // would overlap or cover the title bar of the parent. | ||
1374 | 189 | // o Otherwise, it should be cascaded vertically (but not horizontally) | ||
1375 | 190 | // relative to its parent, unless, this would cause at least part of | ||
1376 | 191 | // it to extend into shell space. | ||
1377 | 192 | auto const parent_top_left = parent->top_left(); | ||
1378 | 193 | auto const centred = parent_top_left | ||
1379 | 194 | + 0.5*(as_displacement(parent->size()) - as_displacement(parameters.size)) | ||
1380 | 195 | - DeltaY{(parent->size().height.as_int()-height)/6}; | ||
1381 | 196 | |||
1382 | 197 | parameters.top_left = centred; | ||
1383 | 198 | positioned = true; | ||
1384 | 199 | } | ||
1385 | 200 | |||
1386 | 201 | if (!positioned) | ||
1387 | 202 | { | ||
1388 | 203 | auto const centred = active_display.top_left | ||
1389 | 204 | + 0.5*(as_displacement(active_display.size) - as_displacement(parameters.size)) | ||
1390 | 205 | - DeltaY{(active_display.size.height.as_int()-height)/6}; | ||
1391 | 206 | |||
1392 | 207 | switch (parameters.state.value()) | ||
1393 | 208 | { | ||
1394 | 209 | case mir_surface_state_fullscreen: | ||
1395 | 210 | case mir_surface_state_maximized: | ||
1396 | 211 | parameters.top_left = active_display.top_left; | ||
1397 | 212 | parameters.size = active_display.size; | ||
1398 | 213 | break; | ||
1399 | 214 | |||
1400 | 215 | case mir_surface_state_vertmaximized: | ||
1401 | 216 | parameters.top_left = centred; | ||
1402 | 217 | parameters.top_left.y = active_display.top_left.y; | ||
1403 | 218 | parameters.size.height = active_display.size.height; | ||
1404 | 219 | break; | ||
1405 | 220 | |||
1406 | 221 | case mir_surface_state_horizmaximized: | ||
1407 | 222 | parameters.top_left = centred; | ||
1408 | 223 | parameters.top_left.x = active_display.top_left.x; | ||
1409 | 224 | parameters.size.width = active_display.size.width; | ||
1410 | 225 | break; | ||
1411 | 226 | |||
1412 | 227 | default: | ||
1413 | 228 | parameters.top_left = centred; | ||
1414 | 229 | } | ||
1415 | 230 | |||
1416 | 231 | if (parameters.top_left.y < display_area.top_left.y) | ||
1417 | 232 | parameters.top_left.y = display_area.top_left.y; | ||
1418 | 233 | } | ||
1419 | 234 | |||
1420 | 235 | if (parameters.state != mir_surface_state_fullscreen && needs_titlebar) | ||
1421 | 236 | { | ||
1422 | 237 | parameters.top_left.y = parameters.top_left.y + DeltaY{title_bar_height}; | ||
1423 | 238 | parameters.size.height = parameters.size.height - DeltaY{title_bar_height}; | ||
1424 | 239 | } | ||
1425 | 240 | |||
1426 | 241 | return parameters; | ||
1427 | 242 | } | ||
1428 | 243 | |||
1429 | 244 | void me::CanonicalWindowManagerPolicyCopy::generate_decorations_for( | ||
1430 | 245 | std::shared_ptr<scene::Session> const& session, | ||
1431 | 246 | std::shared_ptr<scene::Surface> const& surface, | ||
1432 | 247 | SurfaceInfoMap& surface_map, | ||
1433 | 248 | std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build) | ||
1434 | 249 | { | ||
1435 | 250 | if (!SurfaceInfo::needs_titlebar(surface->type())) | ||
1436 | 251 | return; | ||
1437 | 252 | |||
1438 | 253 | auto format = mir_pixel_format_xrgb_8888; | ||
1439 | 254 | ms::SurfaceCreationParameters params; | ||
1440 | 255 | params.of_size(titlebar_size_for_window(surface->size())) | ||
1441 | 256 | .of_name("decoration") | ||
1442 | 257 | .of_pixel_format(format) | ||
1443 | 258 | .of_buffer_usage(mir::graphics::BufferUsage::software) | ||
1444 | 259 | .of_position(titlebar_position_for_window(surface->top_left())) | ||
1445 | 260 | .of_type(mir_surface_type_gloss); | ||
1446 | 261 | auto id = build(session, params); | ||
1447 | 262 | auto titlebar = session->surface(id); | ||
1448 | 263 | titlebar->set_alpha(0.9); | ||
1449 | 264 | |||
1450 | 265 | auto& surface_info = tools->info_for(surface); | ||
1451 | 266 | surface_info.titlebar = titlebar; | ||
1452 | 267 | surface_info.titlebar_id = id; | ||
1453 | 268 | surface_info.children.push_back(titlebar); | ||
1454 | 269 | |||
1455 | 270 | SurfaceInfo& titlebar_info = | ||
1456 | 271 | surface_map.emplace(titlebar, SurfaceInfo{session, titlebar, {}}).first->second; | ||
1457 | 272 | titlebar_info.is_titlebar = true; | ||
1458 | 273 | titlebar_info.parent = surface; | ||
1459 | 274 | titlebar_info.init_titlebar(titlebar); | ||
1460 | 275 | } | ||
1461 | 276 | |||
1462 | 277 | void me::CanonicalWindowManagerPolicyCopy::handle_new_surface(std::shared_ptr<ms::Session> const& session, std::shared_ptr<ms::Surface> const& surface) | ||
1463 | 278 | { | ||
1464 | 279 | auto& surface_info = tools->info_for(surface); | ||
1465 | 280 | if (auto const parent = surface_info.parent.lock()) | ||
1466 | 281 | { | ||
1467 | 282 | tools->info_for(parent).children.push_back(surface); | ||
1468 | 283 | } | ||
1469 | 284 | |||
1470 | 285 | tools->info_for(session).surfaces.push_back(surface); | ||
1471 | 286 | |||
1472 | 287 | if (surface_info.can_be_active()) | ||
1473 | 288 | { | ||
1474 | 289 | surface->add_observer(std::make_shared<shell::SurfaceReadyObserver>( | ||
1475 | 290 | [this](std::shared_ptr<scene::Session> const& /*session*/, | ||
1476 | 291 | std::shared_ptr<scene::Surface> const& surface) | ||
1477 | 292 | { | ||
1478 | 293 | select_active_surface(surface); | ||
1479 | 294 | }, | ||
1480 | 295 | session, | ||
1481 | 296 | surface)); | ||
1482 | 297 | } | ||
1483 | 298 | |||
1484 | 299 | if (surface_info.state == mir_surface_state_fullscreen) | ||
1485 | 300 | fullscreen_surfaces.insert(surface); | ||
1486 | 301 | } | ||
1487 | 302 | |||
1488 | 303 | void me::CanonicalWindowManagerPolicyCopy::handle_modify_surface( | ||
1489 | 304 | std::shared_ptr<scene::Session> const& session, | ||
1490 | 305 | std::shared_ptr<scene::Surface> const& surface, | ||
1491 | 306 | shell::SurfaceSpecification const& modifications) | ||
1492 | 307 | { | ||
1493 | 308 | auto& surface_info_old = tools->info_for(surface); | ||
1494 | 309 | |||
1495 | 310 | auto surface_info = surface_info_old; | ||
1496 | 311 | |||
1497 | 312 | if (modifications.parent.is_set()) | ||
1498 | 313 | surface_info.parent = modifications.parent.value(); | ||
1499 | 314 | |||
1500 | 315 | if (modifications.type.is_set() && | ||
1501 | 316 | surface_info.type != modifications.type.value()) | ||
1502 | 317 | { | ||
1503 | 318 | auto const new_type = modifications.type.value(); | ||
1504 | 319 | |||
1505 | 320 | if (!surface_info.can_morph_to(new_type)) | ||
1506 | 321 | { | ||
1507 | 322 | throw std::runtime_error("Unsupported surface type change"); | ||
1508 | 323 | } | ||
1509 | 324 | |||
1510 | 325 | surface_info.type = new_type; | ||
1511 | 326 | |||
1512 | 327 | if (surface_info.must_not_have_parent()) | ||
1513 | 328 | { | ||
1514 | 329 | if (modifications.parent.is_set()) | ||
1515 | 330 | throw std::runtime_error("Target surface type does not support parent"); | ||
1516 | 331 | |||
1517 | 332 | surface_info.parent.reset(); | ||
1518 | 333 | } | ||
1519 | 334 | else if (surface_info.must_have_parent()) | ||
1520 | 335 | { | ||
1521 | 336 | if (!surface_info.parent.lock()) | ||
1522 | 337 | throw std::runtime_error("Target surface type requires parent"); | ||
1523 | 338 | } | ||
1524 | 339 | |||
1525 | 340 | surface->configure(mir_surface_attrib_type, new_type); | ||
1526 | 341 | } | ||
1527 | 342 | |||
1528 | 343 | #define COPY_IF_SET(field)\ | ||
1529 | 344 | if (modifications.field.is_set())\ | ||
1530 | 345 | surface_info.field = modifications.field.value() | ||
1531 | 346 | |||
1532 | 347 | COPY_IF_SET(min_width); | ||
1533 | 348 | COPY_IF_SET(min_height); | ||
1534 | 349 | COPY_IF_SET(max_width); | ||
1535 | 350 | COPY_IF_SET(max_height); | ||
1536 | 351 | COPY_IF_SET(min_width); | ||
1537 | 352 | COPY_IF_SET(width_inc); | ||
1538 | 353 | COPY_IF_SET(height_inc); | ||
1539 | 354 | COPY_IF_SET(min_aspect); | ||
1540 | 355 | COPY_IF_SET(max_aspect); | ||
1541 | 356 | COPY_IF_SET(output_id); | ||
1542 | 357 | |||
1543 | 358 | #undef COPY_IF_SET | ||
1544 | 359 | |||
1545 | 360 | std::swap(surface_info, surface_info_old); | ||
1546 | 361 | |||
1547 | 362 | if (modifications.name.is_set()) | ||
1548 | 363 | surface->rename(modifications.name.value()); | ||
1549 | 364 | |||
1550 | 365 | if (modifications.streams.is_set()) | ||
1551 | 366 | { | ||
1552 | 367 | auto v = modifications.streams.value(); | ||
1553 | 368 | std::vector<shell::StreamSpecification> l (v.begin(), v.end()); | ||
1554 | 369 | session->configure_streams(*surface, l); | ||
1555 | 370 | } | ||
1556 | 371 | |||
1557 | 372 | if (modifications.input_shape.is_set()) | ||
1558 | 373 | { | ||
1559 | 374 | surface->set_input_region(modifications.input_shape.value()); | ||
1560 | 375 | } | ||
1561 | 376 | |||
1562 | 377 | if (modifications.width.is_set() || modifications.height.is_set()) | ||
1563 | 378 | { | ||
1564 | 379 | auto new_size = surface->size(); | ||
1565 | 380 | |||
1566 | 381 | if (modifications.width.is_set()) | ||
1567 | 382 | new_size.width = modifications.width.value(); | ||
1568 | 383 | |||
1569 | 384 | if (modifications.height.is_set()) | ||
1570 | 385 | new_size.height = modifications.height.value(); | ||
1571 | 386 | |||
1572 | 387 | auto top_left = surface->top_left(); | ||
1573 | 388 | |||
1574 | 389 | surface_info.constrain_resize( | ||
1575 | 390 | surface, | ||
1576 | 391 | top_left, | ||
1577 | 392 | new_size, | ||
1578 | 393 | false, | ||
1579 | 394 | false, | ||
1580 | 395 | display_area); | ||
1581 | 396 | |||
1582 | 397 | apply_resize(surface, surface_info.titlebar, top_left, new_size); | ||
1583 | 398 | } | ||
1584 | 399 | |||
1585 | 400 | if (modifications.state.is_set()) | ||
1586 | 401 | { | ||
1587 | 402 | auto const state = handle_set_state(surface, modifications.state.value()); | ||
1588 | 403 | surface->configure(mir_surface_attrib_state, state); | ||
1589 | 404 | } | ||
1590 | 405 | } | ||
1591 | 406 | |||
1592 | 407 | void me::CanonicalWindowManagerPolicyCopy::handle_delete_surface(std::shared_ptr<ms::Session> const& session, std::weak_ptr<ms::Surface> const& surface) | ||
1593 | 408 | { | ||
1594 | 409 | fullscreen_surfaces.erase(surface); | ||
1595 | 410 | |||
1596 | 411 | auto& info = tools->info_for(surface); | ||
1597 | 412 | |||
1598 | 413 | if (auto const parent = info.parent.lock()) | ||
1599 | 414 | { | ||
1600 | 415 | auto& siblings = tools->info_for(parent).children; | ||
1601 | 416 | |||
1602 | 417 | for (auto i = begin(siblings); i != end(siblings); ++i) | ||
1603 | 418 | { | ||
1604 | 419 | if (surface.lock() == i->lock()) | ||
1605 | 420 | { | ||
1606 | 421 | siblings.erase(i); | ||
1607 | 422 | break; | ||
1608 | 423 | } | ||
1609 | 424 | } | ||
1610 | 425 | } | ||
1611 | 426 | |||
1612 | 427 | session->destroy_surface(surface); | ||
1613 | 428 | if (info.titlebar) | ||
1614 | 429 | { | ||
1615 | 430 | session->destroy_surface(info.titlebar_id); | ||
1616 | 431 | tools->forget(info.titlebar); | ||
1617 | 432 | } | ||
1618 | 433 | |||
1619 | 434 | auto& surfaces = tools->info_for(session).surfaces; | ||
1620 | 435 | |||
1621 | 436 | for (auto i = begin(surfaces); i != end(surfaces); ++i) | ||
1622 | 437 | { | ||
1623 | 438 | if (surface.lock() == i->lock()) | ||
1624 | 439 | { | ||
1625 | 440 | surfaces.erase(i); | ||
1626 | 441 | break; | ||
1627 | 442 | } | ||
1628 | 443 | } | ||
1629 | 444 | |||
1630 | 445 | if (surfaces.empty() && session == tools->focused_session()) | ||
1631 | 446 | { | ||
1632 | 447 | active_surface_.reset(); | ||
1633 | 448 | tools->focus_next_session(); | ||
1634 | 449 | select_active_surface(tools->focused_surface()); | ||
1635 | 450 | } | ||
1636 | 451 | } | ||
1637 | 452 | |||
1638 | 453 | int me::CanonicalWindowManagerPolicyCopy::handle_set_state(std::shared_ptr<ms::Surface> const& surface, MirSurfaceState value) | ||
1639 | 454 | { | ||
1640 | 455 | auto& info = tools->info_for(surface); | ||
1641 | 456 | |||
1642 | 457 | switch (value) | ||
1643 | 458 | { | ||
1644 | 459 | case mir_surface_state_restored: | ||
1645 | 460 | case mir_surface_state_maximized: | ||
1646 | 461 | case mir_surface_state_vertmaximized: | ||
1647 | 462 | case mir_surface_state_horizmaximized: | ||
1648 | 463 | case mir_surface_state_fullscreen: | ||
1649 | 464 | case mir_surface_state_hidden: | ||
1650 | 465 | case mir_surface_state_minimized: | ||
1651 | 466 | break; | ||
1652 | 467 | |||
1653 | 468 | default: | ||
1654 | 469 | return info.state; | ||
1655 | 470 | } | ||
1656 | 471 | |||
1657 | 472 | if (info.state == mir_surface_state_restored) | ||
1658 | 473 | { | ||
1659 | 474 | info.restore_rect = {surface->top_left(), surface->size()}; | ||
1660 | 475 | } | ||
1661 | 476 | |||
1662 | 477 | if (info.state != mir_surface_state_fullscreen) | ||
1663 | 478 | { | ||
1664 | 479 | info.output_id = decltype(info.output_id){}; | ||
1665 | 480 | fullscreen_surfaces.erase(surface); | ||
1666 | 481 | } | ||
1667 | 482 | else | ||
1668 | 483 | { | ||
1669 | 484 | fullscreen_surfaces.insert(surface); | ||
1670 | 485 | } | ||
1671 | 486 | |||
1672 | 487 | if (info.state == value) | ||
1673 | 488 | { | ||
1674 | 489 | return info.state; | ||
1675 | 490 | } | ||
1676 | 491 | |||
1677 | 492 | auto const old_pos = surface->top_left(); | ||
1678 | 493 | Displacement movement; | ||
1679 | 494 | |||
1680 | 495 | switch (value) | ||
1681 | 496 | { | ||
1682 | 497 | case mir_surface_state_restored: | ||
1683 | 498 | movement = info.restore_rect.top_left - old_pos; | ||
1684 | 499 | surface->resize(info.restore_rect.size); | ||
1685 | 500 | if (info.titlebar) | ||
1686 | 501 | { | ||
1687 | 502 | info.titlebar->resize(titlebar_size_for_window(info.restore_rect.size)); | ||
1688 | 503 | info.titlebar->show(); | ||
1689 | 504 | } | ||
1690 | 505 | break; | ||
1691 | 506 | |||
1692 | 507 | case mir_surface_state_maximized: | ||
1693 | 508 | movement = display_area.top_left - old_pos; | ||
1694 | 509 | surface->resize(display_area.size); | ||
1695 | 510 | if (info.titlebar) | ||
1696 | 511 | info.titlebar->hide(); | ||
1697 | 512 | break; | ||
1698 | 513 | |||
1699 | 514 | case mir_surface_state_horizmaximized: | ||
1700 | 515 | movement = Point{display_area.top_left.x, info.restore_rect.top_left.y} - old_pos; | ||
1701 | 516 | surface->resize({display_area.size.width, info.restore_rect.size.height}); | ||
1702 | 517 | if (info.titlebar) | ||
1703 | 518 | { | ||
1704 | 519 | info.titlebar->resize(titlebar_size_for_window({display_area.size.width, info.restore_rect.size.height})); | ||
1705 | 520 | info.titlebar->show(); | ||
1706 | 521 | } | ||
1707 | 522 | break; | ||
1708 | 523 | |||
1709 | 524 | case mir_surface_state_vertmaximized: | ||
1710 | 525 | movement = Point{info.restore_rect.top_left.x, display_area.top_left.y} - old_pos; | ||
1711 | 526 | surface->resize({info.restore_rect.size.width, display_area.size.height}); | ||
1712 | 527 | if (info.titlebar) | ||
1713 | 528 | info.titlebar->hide(); | ||
1714 | 529 | break; | ||
1715 | 530 | |||
1716 | 531 | case mir_surface_state_fullscreen: | ||
1717 | 532 | { | ||
1718 | 533 | Rectangle rect{old_pos, surface->size()}; | ||
1719 | 534 | |||
1720 | 535 | if (info.output_id.is_set()) | ||
1721 | 536 | { | ||
1722 | 537 | display_layout->place_in_output(info.output_id.value(), rect); | ||
1723 | 538 | } | ||
1724 | 539 | else | ||
1725 | 540 | { | ||
1726 | 541 | display_layout->size_to_output(rect); | ||
1727 | 542 | } | ||
1728 | 543 | |||
1729 | 544 | movement = rect.top_left - old_pos; | ||
1730 | 545 | surface->resize(rect.size); | ||
1731 | 546 | break; | ||
1732 | 547 | } | ||
1733 | 548 | |||
1734 | 549 | case mir_surface_state_hidden: | ||
1735 | 550 | case mir_surface_state_minimized: | ||
1736 | 551 | if (info.titlebar) | ||
1737 | 552 | info.titlebar->hide(); | ||
1738 | 553 | surface->hide(); | ||
1739 | 554 | return info.state = value; | ||
1740 | 555 | |||
1741 | 556 | default: | ||
1742 | 557 | break; | ||
1743 | 558 | } | ||
1744 | 559 | |||
1745 | 560 | // TODO It is rather simplistic to move a tree WRT the top_left of the root | ||
1746 | 561 | // TODO when resizing. But for more sophistication we would need to encode | ||
1747 | 562 | // TODO some sensible layout rules. | ||
1748 | 563 | move_tree(surface, movement); | ||
1749 | 564 | |||
1750 | 565 | info.state = value; | ||
1751 | 566 | |||
1752 | 567 | if (info.is_visible()) | ||
1753 | 568 | surface->show(); | ||
1754 | 569 | |||
1755 | 570 | return info.state; | ||
1756 | 571 | } | ||
1757 | 572 | |||
1758 | 573 | void me::CanonicalWindowManagerPolicyCopy::drag(Point cursor) | ||
1759 | 574 | { | ||
1760 | 575 | select_active_surface(tools->surface_at(old_cursor)); | ||
1761 | 576 | drag(active_surface(), cursor, old_cursor, display_area); | ||
1762 | 577 | } | ||
1763 | 578 | |||
1764 | 579 | void me::CanonicalWindowManagerPolicyCopy::handle_raise_surface( | ||
1765 | 580 | std::shared_ptr<ms::Session> const& /*session*/, | ||
1766 | 581 | std::shared_ptr<ms::Surface> const& surface) | ||
1767 | 582 | { | ||
1768 | 583 | select_active_surface(surface); | ||
1769 | 584 | } | ||
1770 | 585 | |||
1771 | 586 | bool me::CanonicalWindowManagerPolicyCopy::handle_keyboard_event(MirKeyboardEvent const* event) | ||
1772 | 587 | { | ||
1773 | 588 | auto const action = mir_keyboard_event_action(event); | ||
1774 | 589 | auto const scan_code = mir_keyboard_event_scan_code(event); | ||
1775 | 590 | auto const modifiers = mir_keyboard_event_modifiers(event) & modifier_mask; | ||
1776 | 591 | |||
1777 | 592 | if (action == mir_keyboard_action_down && scan_code == KEY_F11) | ||
1778 | 593 | { | ||
1779 | 594 | switch (modifiers) | ||
1780 | 595 | { | ||
1781 | 596 | case mir_input_event_modifier_alt: | ||
1782 | 597 | toggle(mir_surface_state_maximized); | ||
1783 | 598 | return true; | ||
1784 | 599 | |||
1785 | 600 | case mir_input_event_modifier_shift: | ||
1786 | 601 | toggle(mir_surface_state_vertmaximized); | ||
1787 | 602 | return true; | ||
1788 | 603 | |||
1789 | 604 | case mir_input_event_modifier_ctrl: | ||
1790 | 605 | toggle(mir_surface_state_horizmaximized); | ||
1791 | 606 | return true; | ||
1792 | 607 | |||
1793 | 608 | default: | ||
1794 | 609 | break; | ||
1795 | 610 | } | ||
1796 | 611 | } | ||
1797 | 612 | else if (action == mir_keyboard_action_down && scan_code == KEY_F4) | ||
1798 | 613 | { | ||
1799 | 614 | if (auto const session = tools->focused_session()) | ||
1800 | 615 | { | ||
1801 | 616 | switch (modifiers) | ||
1802 | 617 | { | ||
1803 | 618 | case mir_input_event_modifier_alt: | ||
1804 | 619 | kill(session->process_id(), SIGTERM); | ||
1805 | 620 | return true; | ||
1806 | 621 | |||
1807 | 622 | case mir_input_event_modifier_ctrl: | ||
1808 | 623 | if (auto const surf = session->default_surface()) | ||
1809 | 624 | { | ||
1810 | 625 | surf->request_client_surface_close(); | ||
1811 | 626 | return true; | ||
1812 | 627 | } | ||
1813 | 628 | |||
1814 | 629 | default: | ||
1815 | 630 | break; | ||
1816 | 631 | } | ||
1817 | 632 | } | ||
1818 | 633 | } | ||
1819 | 634 | else if (action == mir_keyboard_action_down && | ||
1820 | 635 | modifiers == mir_input_event_modifier_alt && | ||
1821 | 636 | scan_code == KEY_TAB) | ||
1822 | 637 | { | ||
1823 | 638 | tools->focus_next_session(); | ||
1824 | 639 | if (auto const surface = tools->focused_surface()) | ||
1825 | 640 | select_active_surface(surface); | ||
1826 | 641 | |||
1827 | 642 | return true; | ||
1828 | 643 | } | ||
1829 | 644 | else if (action == mir_keyboard_action_down && | ||
1830 | 645 | modifiers == mir_input_event_modifier_alt && | ||
1831 | 646 | scan_code == KEY_GRAVE) | ||
1832 | 647 | { | ||
1833 | 648 | if (auto const prev = tools->focused_surface()) | ||
1834 | 649 | { | ||
1835 | 650 | if (auto const app = tools->focused_session()) | ||
1836 | 651 | select_active_surface(app->surface_after(prev)); | ||
1837 | 652 | } | ||
1838 | 653 | |||
1839 | 654 | return true; | ||
1840 | 655 | } | ||
1841 | 656 | |||
1842 | 657 | return false; | ||
1843 | 658 | } | ||
1844 | 659 | |||
1845 | 660 | bool me::CanonicalWindowManagerPolicyCopy::handle_touch_event(MirTouchEvent const* event) | ||
1846 | 661 | { | ||
1847 | 662 | auto const count = mir_touch_event_point_count(event); | ||
1848 | 663 | |||
1849 | 664 | long total_x = 0; | ||
1850 | 665 | long total_y = 0; | ||
1851 | 666 | |||
1852 | 667 | for (auto i = 0U; i != count; ++i) | ||
1853 | 668 | { | ||
1854 | 669 | total_x += mir_touch_event_axis_value(event, i, mir_touch_axis_x); | ||
1855 | 670 | total_y += mir_touch_event_axis_value(event, i, mir_touch_axis_y); | ||
1856 | 671 | } | ||
1857 | 672 | |||
1858 | 673 | Point const cursor{total_x/count, total_y/count}; | ||
1859 | 674 | |||
1860 | 675 | bool is_drag = true; | ||
1861 | 676 | for (auto i = 0U; i != count; ++i) | ||
1862 | 677 | { | ||
1863 | 678 | switch (mir_touch_event_action(event, i)) | ||
1864 | 679 | { | ||
1865 | 680 | case mir_touch_action_up: | ||
1866 | 681 | return false; | ||
1867 | 682 | |||
1868 | 683 | case mir_touch_action_down: | ||
1869 | 684 | is_drag = false; | ||
1870 | 685 | |||
1871 | 686 | case mir_touch_action_change: | ||
1872 | 687 | continue; | ||
1873 | 688 | } | ||
1874 | 689 | } | ||
1875 | 690 | |||
1876 | 691 | bool consumes_event = false; | ||
1877 | 692 | if (is_drag) | ||
1878 | 693 | { | ||
1879 | 694 | switch (count) | ||
1880 | 695 | { | ||
1881 | 696 | case 2: | ||
1882 | 697 | resize(cursor); | ||
1883 | 698 | consumes_event = true; | ||
1884 | 699 | break; | ||
1885 | 700 | |||
1886 | 701 | case 3: | ||
1887 | 702 | drag(cursor); | ||
1888 | 703 | consumes_event = true; | ||
1889 | 704 | break; | ||
1890 | 705 | } | ||
1891 | 706 | } | ||
1892 | 707 | |||
1893 | 708 | old_cursor = cursor; | ||
1894 | 709 | return consumes_event; | ||
1895 | 710 | } | ||
1896 | 711 | |||
1897 | 712 | bool me::CanonicalWindowManagerPolicyCopy::handle_pointer_event(MirPointerEvent const* event) | ||
1898 | 713 | { | ||
1899 | 714 | auto const action = mir_pointer_event_action(event); | ||
1900 | 715 | auto const modifiers = mir_pointer_event_modifiers(event) & modifier_mask; | ||
1901 | 716 | Point const cursor{ | ||
1902 | 717 | mir_pointer_event_axis_value(event, mir_pointer_axis_x), | ||
1903 | 718 | mir_pointer_event_axis_value(event, mir_pointer_axis_y)}; | ||
1904 | 719 | |||
1905 | 720 | bool consumes_event = false; | ||
1906 | 721 | |||
1907 | 722 | if (action == mir_pointer_action_button_down) | ||
1908 | 723 | { | ||
1909 | 724 | click(cursor); | ||
1910 | 725 | } | ||
1911 | 726 | else if (action == mir_pointer_action_motion && | ||
1912 | 727 | modifiers == mir_input_event_modifier_alt) | ||
1913 | 728 | { | ||
1914 | 729 | if (mir_pointer_event_button_state(event, mir_pointer_button_primary)) | ||
1915 | 730 | { | ||
1916 | 731 | drag(cursor); | ||
1917 | 732 | consumes_event = true; | ||
1918 | 733 | } | ||
1919 | 734 | |||
1920 | 735 | if (mir_pointer_event_button_state(event, mir_pointer_button_tertiary)) | ||
1921 | 736 | { | ||
1922 | 737 | resize(cursor); | ||
1923 | 738 | consumes_event = true; | ||
1924 | 739 | } | ||
1925 | 740 | } | ||
1926 | 741 | else if (action == mir_pointer_action_motion && !modifiers) | ||
1927 | 742 | { | ||
1928 | 743 | if (mir_pointer_event_button_state(event, mir_pointer_button_primary)) | ||
1929 | 744 | { | ||
1930 | 745 | if (auto const possible_titlebar = tools->surface_at(old_cursor)) | ||
1931 | 746 | { | ||
1932 | 747 | if (tools->info_for(possible_titlebar).is_titlebar) | ||
1933 | 748 | { | ||
1934 | 749 | drag(cursor); | ||
1935 | 750 | consumes_event = true; | ||
1936 | 751 | } | ||
1937 | 752 | } | ||
1938 | 753 | } | ||
1939 | 754 | } | ||
1940 | 755 | |||
1941 | 756 | old_cursor = cursor; | ||
1942 | 757 | return consumes_event; | ||
1943 | 758 | } | ||
1944 | 759 | |||
1945 | 760 | void me::CanonicalWindowManagerPolicyCopy::toggle(MirSurfaceState state) | ||
1946 | 761 | { | ||
1947 | 762 | if (auto const surface = active_surface()) | ||
1948 | 763 | { | ||
1949 | 764 | auto& info = tools->info_for(surface); | ||
1950 | 765 | |||
1951 | 766 | if (info.state == state) | ||
1952 | 767 | state = mir_surface_state_restored; | ||
1953 | 768 | |||
1954 | 769 | auto const value = handle_set_state(surface, MirSurfaceState(state)); | ||
1955 | 770 | surface->configure(mir_surface_attrib_state, value); | ||
1956 | 771 | } | ||
1957 | 772 | } | ||
1958 | 773 | |||
1959 | 774 | void me::CanonicalWindowManagerPolicyCopy::select_active_surface(std::shared_ptr<ms::Surface> const& surface) | ||
1960 | 775 | { | ||
1961 | 776 | if (surface == active_surface_.lock()) | ||
1962 | 777 | return; | ||
1963 | 778 | |||
1964 | 779 | if (!surface) | ||
1965 | 780 | { | ||
1966 | 781 | if (auto const active_surface = active_surface_.lock()) | ||
1967 | 782 | { | ||
1968 | 783 | if (auto const titlebar = tools->info_for(active_surface).titlebar) | ||
1969 | 784 | { | ||
1970 | 785 | tools->info_for(titlebar).paint_titlebar(0x3F); | ||
1971 | 786 | } | ||
1972 | 787 | } | ||
1973 | 788 | |||
1974 | 789 | if (active_surface_.lock()) | ||
1975 | 790 | tools->set_focus_to({}, {}); | ||
1976 | 791 | |||
1977 | 792 | active_surface_.reset(); | ||
1978 | 793 | return; | ||
1979 | 794 | } | ||
1980 | 795 | |||
1981 | 796 | auto const& info_for = tools->info_for(surface); | ||
1982 | 797 | |||
1983 | 798 | if (info_for.can_be_active()) | ||
1984 | 799 | { | ||
1985 | 800 | if (auto const active_surface = active_surface_.lock()) | ||
1986 | 801 | { | ||
1987 | 802 | if (auto const titlebar = tools->info_for(active_surface).titlebar) | ||
1988 | 803 | { | ||
1989 | 804 | tools->info_for(titlebar).paint_titlebar(0x3F); | ||
1990 | 805 | } | ||
1991 | 806 | } | ||
1992 | 807 | if (auto const titlebar = tools->info_for(surface).titlebar) | ||
1993 | 808 | { | ||
1994 | 809 | tools->info_for(titlebar).paint_titlebar(0xFF); | ||
1995 | 810 | } | ||
1996 | 811 | tools->set_focus_to(info_for.session.lock(), surface); | ||
1997 | 812 | tools->raise_tree(surface); | ||
1998 | 813 | active_surface_ = surface; | ||
1999 | 814 | } | ||
2000 | 815 | else | ||
2001 | 816 | { | ||
2002 | 817 | // Cannot have input focus - try the parent | ||
2003 | 818 | if (auto const parent = info_for.parent.lock()) | ||
2004 | 819 | select_active_surface(parent); | ||
2005 | 820 | } | ||
2006 | 821 | } | ||
2007 | 822 | |||
2008 | 823 | auto me::CanonicalWindowManagerPolicyCopy::active_surface() const | ||
2009 | 824 | -> std::shared_ptr<ms::Surface> | ||
2010 | 825 | { | ||
2011 | 826 | if (auto const surface = active_surface_.lock()) | ||
2012 | 827 | return surface; | ||
2013 | 828 | |||
2014 | 829 | if (auto const session = tools->focused_session()) | ||
2015 | 830 | { | ||
2016 | 831 | if (auto const surface = session->default_surface()) | ||
2017 | 832 | return surface; | ||
2018 | 833 | } | ||
2019 | 834 | |||
2020 | 835 | return std::shared_ptr<ms::Surface>{}; | ||
2021 | 836 | } | ||
2022 | 837 | |||
2023 | 838 | bool me::CanonicalWindowManagerPolicyCopy::resize(std::shared_ptr<ms::Surface> const& surface, Point cursor, Point old_cursor, Rectangle bounds) | ||
2024 | 839 | { | ||
2025 | 840 | if (!surface || !surface->input_area_contains(old_cursor)) | ||
2026 | 841 | return false; | ||
2027 | 842 | |||
2028 | 843 | auto const top_left = surface->top_left(); | ||
2029 | 844 | Rectangle const old_pos{top_left, surface->size()}; | ||
2030 | 845 | |||
2031 | 846 | auto anchor = top_left; | ||
2032 | 847 | |||
2033 | 848 | for (auto const& corner : { | ||
2034 | 849 | old_pos.top_right(), | ||
2035 | 850 | old_pos.bottom_left(), | ||
2036 | 851 | old_pos.bottom_right()}) | ||
2037 | 852 | { | ||
2038 | 853 | if ((old_cursor - anchor).length_squared() < | ||
2039 | 854 | (old_cursor - corner).length_squared()) | ||
2040 | 855 | { | ||
2041 | 856 | anchor = corner; | ||
2042 | 857 | } | ||
2043 | 858 | } | ||
2044 | 859 | |||
2045 | 860 | bool const left_resize = anchor.x != top_left.x; | ||
2046 | 861 | bool const top_resize = anchor.y != top_left.y; | ||
2047 | 862 | int const x_sign = left_resize? -1 : 1; | ||
2048 | 863 | int const y_sign = top_resize? -1 : 1; | ||
2049 | 864 | |||
2050 | 865 | auto const delta = cursor-old_cursor; | ||
2051 | 866 | |||
2052 | 867 | Size new_size{old_pos.size.width + x_sign*delta.dx, old_pos.size.height + y_sign*delta.dy}; | ||
2053 | 868 | |||
2054 | 869 | Point new_pos = top_left + left_resize*delta.dx + top_resize*delta.dy; | ||
2055 | 870 | |||
2056 | 871 | |||
2057 | 872 | auto const& surface_info = tools->info_for(surface); | ||
2058 | 873 | |||
2059 | 874 | surface_info.constrain_resize(surface, new_pos, new_size, left_resize, top_resize, bounds); | ||
2060 | 875 | |||
2061 | 876 | apply_resize(surface, surface_info.titlebar, new_pos, new_size); | ||
2062 | 877 | |||
2063 | 878 | return true; | ||
2064 | 879 | } | ||
2065 | 880 | |||
2066 | 881 | void me::CanonicalWindowManagerPolicyCopy::apply_resize( | ||
2067 | 882 | std::shared_ptr<ms::Surface> const& surface, | ||
2068 | 883 | std::shared_ptr<ms::Surface> const& titlebar, | ||
2069 | 884 | Point const& new_pos, | ||
2070 | 885 | Size const& new_size) const | ||
2071 | 886 | { | ||
2072 | 887 | if (titlebar) | ||
2073 | 888 | titlebar->resize({new_size.width, Height{title_bar_height}}); | ||
2074 | 889 | |||
2075 | 890 | surface->resize(new_size); | ||
2076 | 891 | |||
2077 | 892 | move_tree(surface, new_pos-surface->top_left()); | ||
2078 | 893 | } | ||
2079 | 894 | |||
2080 | 895 | bool me::CanonicalWindowManagerPolicyCopy::drag(std::shared_ptr<ms::Surface> surface, Point to, Point from, Rectangle /*bounds*/) | ||
2081 | 896 | { | ||
2082 | 897 | if (!surface) | ||
2083 | 898 | return false; | ||
2084 | 899 | |||
2085 | 900 | if (!surface->input_area_contains(from) && !tools->info_for(surface).titlebar) | ||
2086 | 901 | return false; | ||
2087 | 902 | |||
2088 | 903 | auto movement = to - from; | ||
2089 | 904 | |||
2090 | 905 | // placeholder - constrain onscreen | ||
2091 | 906 | |||
2092 | 907 | switch (tools->info_for(surface).state) | ||
2093 | 908 | { | ||
2094 | 909 | case mir_surface_state_restored: | ||
2095 | 910 | break; | ||
2096 | 911 | |||
2097 | 912 | // "A vertically maximised surface is anchored to the top and bottom of | ||
2098 | 913 | // the available workspace and can have any width." | ||
2099 | 914 | case mir_surface_state_vertmaximized: | ||
2100 | 915 | movement.dy = DeltaY(0); | ||
2101 | 916 | break; | ||
2102 | 917 | |||
2103 | 918 | // "A horizontally maximised surface is anchored to the left and right of | ||
2104 | 919 | // the available workspace and can have any height" | ||
2105 | 920 | case mir_surface_state_horizmaximized: | ||
2106 | 921 | movement.dx = DeltaX(0); | ||
2107 | 922 | break; | ||
2108 | 923 | |||
2109 | 924 | // "A maximised surface is anchored to the top, bottom, left and right of the | ||
2110 | 925 | // available workspace. For example, if the launcher is always-visible then | ||
2111 | 926 | // the left-edge of the surface is anchored to the right-edge of the launcher." | ||
2112 | 927 | case mir_surface_state_maximized: | ||
2113 | 928 | case mir_surface_state_fullscreen: | ||
2114 | 929 | default: | ||
2115 | 930 | return true; | ||
2116 | 931 | } | ||
2117 | 932 | |||
2118 | 933 | move_tree(surface, movement); | ||
2119 | 934 | |||
2120 | 935 | return true; | ||
2121 | 936 | } | ||
2122 | 937 | |||
2123 | 938 | void me::CanonicalWindowManagerPolicyCopy::move_tree(std::shared_ptr<ms::Surface> const& root, Displacement movement) const | ||
2124 | 939 | { | ||
2125 | 940 | root->move_to(root->top_left() + movement); | ||
2126 | 941 | |||
2127 | 942 | for (auto const& child: tools->info_for(root).children) | ||
2128 | 943 | { | ||
2129 | 944 | move_tree(child.lock(), movement); | ||
2130 | 945 | } | ||
2131 | 946 | } | ||
2132 | 0 | 947 | ||
2133 | === added file 'src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.h' | |||
2134 | --- src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.h 1970-01-01 00:00:00 +0000 | |||
2135 | +++ src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.h 2016-03-11 11:36:44 +0000 | |||
2136 | @@ -0,0 +1,132 @@ | |||
2137 | 1 | /* | ||
2138 | 2 | * Copyright © 2015 Canonical Ltd. | ||
2139 | 3 | * | ||
2140 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
2141 | 5 | * under the terms of the GNU General Public License version 3, | ||
2142 | 6 | * as published by the Free Software Foundation. | ||
2143 | 7 | * | ||
2144 | 8 | * This program is distributed in the hope that it will be useful, | ||
2145 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2146 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2147 | 11 | * GNU General Public License for more details. | ||
2148 | 12 | * | ||
2149 | 13 | * You should have received a copy of the GNU General Public License | ||
2150 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2151 | 15 | * | ||
2152 | 16 | * Authored By: Alan Griffiths <alan@octopull.co.uk> | ||
2153 | 17 | */ | ||
2154 | 18 | |||
2155 | 19 | #ifndef MIR_EXAMPLE_CANONICAL_WINDOW_MANAGER_H_ | ||
2156 | 20 | #define MIR_EXAMPLE_CANONICAL_WINDOW_MANAGER_H_ | ||
2157 | 21 | |||
2158 | 22 | #include "server_example_basic_window_manager.h" | ||
2159 | 23 | |||
2160 | 24 | #include "mir/geometry/displacement.h" | ||
2161 | 25 | |||
2162 | 26 | #include <atomic> | ||
2163 | 27 | #include <set> | ||
2164 | 28 | |||
2165 | 29 | ///\example server_example_canonical_window_manager.h | ||
2166 | 30 | // Based on "Mir and Unity: Surfaces, input, and displays (v0.3)" | ||
2167 | 31 | |||
2168 | 32 | namespace mir | ||
2169 | 33 | { | ||
2170 | 34 | namespace shell { class DisplayLayout; } | ||
2171 | 35 | namespace examples | ||
2172 | 36 | { | ||
2173 | 37 | // standard window management algorithm: | ||
2174 | 38 | // o Switch apps: tap or click on the corresponding tile | ||
2175 | 39 | // o Move window: Alt-leftmousebutton drag (three finger drag) | ||
2176 | 40 | // o Resize window: Alt-middle_button drag (two finger drag) | ||
2177 | 41 | // o Maximize/restore current window (to display size): Alt-F11 | ||
2178 | 42 | // o Maximize/restore current window (to display height): Shift-F11 | ||
2179 | 43 | // o Maximize/restore current window (to display width): Ctrl-F11 | ||
2180 | 44 | // o client requests to maximize, vertically maximize & restore | ||
2181 | 45 | class CanonicalWindowManagerPolicyCopy : public WindowManagementPolicy | ||
2182 | 46 | { | ||
2183 | 47 | public: | ||
2184 | 48 | |||
2185 | 49 | explicit CanonicalWindowManagerPolicyCopy( | ||
2186 | 50 | WindowManagerTools* const tools, | ||
2187 | 51 | std::shared_ptr<shell::DisplayLayout> const& display_layout); | ||
2188 | 52 | |||
2189 | 53 | void click(geometry::Point cursor); | ||
2190 | 54 | |||
2191 | 55 | void handle_session_info_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays); | ||
2192 | 56 | |||
2193 | 57 | void handle_displays_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays); | ||
2194 | 58 | |||
2195 | 59 | void resize(geometry::Point cursor); | ||
2196 | 60 | |||
2197 | 61 | auto handle_place_new_surface( | ||
2198 | 62 | std::shared_ptr<scene::Session> const& session, | ||
2199 | 63 | scene::SurfaceCreationParameters const& request_parameters) | ||
2200 | 64 | -> scene::SurfaceCreationParameters; | ||
2201 | 65 | |||
2202 | 66 | void handle_new_surface(std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface); | ||
2203 | 67 | |||
2204 | 68 | void handle_modify_surface( | ||
2205 | 69 | std::shared_ptr<scene::Session> const& session, | ||
2206 | 70 | std::shared_ptr<scene::Surface> const& surface, | ||
2207 | 71 | shell::SurfaceSpecification const& modifications); | ||
2208 | 72 | |||
2209 | 73 | void handle_delete_surface(std::shared_ptr<scene::Session> const& session, std::weak_ptr<scene::Surface> const& surface); | ||
2210 | 74 | |||
2211 | 75 | int handle_set_state(std::shared_ptr<scene::Surface> const& surface, MirSurfaceState value); | ||
2212 | 76 | |||
2213 | 77 | void drag(geometry::Point cursor); | ||
2214 | 78 | |||
2215 | 79 | bool handle_keyboard_event(MirKeyboardEvent const* event); | ||
2216 | 80 | |||
2217 | 81 | bool handle_touch_event(MirTouchEvent const* event); | ||
2218 | 82 | |||
2219 | 83 | bool handle_pointer_event(MirPointerEvent const* event); | ||
2220 | 84 | |||
2221 | 85 | void handle_raise_surface( | ||
2222 | 86 | std::shared_ptr<scene::Session> const& session, | ||
2223 | 87 | std::shared_ptr<scene::Surface> const& surface); | ||
2224 | 88 | |||
2225 | 89 | void generate_decorations_for( | ||
2226 | 90 | std::shared_ptr<scene::Session> const& session, | ||
2227 | 91 | std::shared_ptr<scene::Surface> const& surface, | ||
2228 | 92 | SurfaceInfoMap& surface_map, | ||
2229 | 93 | std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build); | ||
2230 | 94 | |||
2231 | 95 | private: | ||
2232 | 96 | static const int modifier_mask = | ||
2233 | 97 | mir_input_event_modifier_alt | | ||
2234 | 98 | mir_input_event_modifier_shift | | ||
2235 | 99 | mir_input_event_modifier_sym | | ||
2236 | 100 | mir_input_event_modifier_ctrl | | ||
2237 | 101 | mir_input_event_modifier_meta; | ||
2238 | 102 | |||
2239 | 103 | void toggle(MirSurfaceState state); | ||
2240 | 104 | |||
2241 | 105 | // "Mir and Unity: Surfaces, input, and displays (v0.3)" talks about active | ||
2242 | 106 | // *window*,but Mir really only understands surfaces | ||
2243 | 107 | void select_active_surface(std::shared_ptr<scene::Surface> const& surface); | ||
2244 | 108 | auto active_surface() const -> std::shared_ptr<scene::Surface>; | ||
2245 | 109 | |||
2246 | 110 | bool resize(std::shared_ptr<scene::Surface> const& surface, geometry::Point cursor, geometry::Point old_cursor, geometry::Rectangle bounds); | ||
2247 | 111 | bool drag(std::shared_ptr<scene::Surface> surface, geometry::Point to, geometry::Point from, geometry::Rectangle bounds); | ||
2248 | 112 | void move_tree(std::shared_ptr<scene::Surface> const& root, geometry::Displacement movement) const; | ||
2249 | 113 | void apply_resize( | ||
2250 | 114 | std::shared_ptr<mir::scene::Surface> const& surface, | ||
2251 | 115 | std::shared_ptr<mir::scene::Surface> const& titlebar, | ||
2252 | 116 | geometry::Point const& new_pos, | ||
2253 | 117 | geometry::Size const& new_size) const; | ||
2254 | 118 | |||
2255 | 119 | WindowManagerTools* const tools; | ||
2256 | 120 | std::shared_ptr<shell::DisplayLayout> const display_layout; | ||
2257 | 121 | |||
2258 | 122 | geometry::Rectangle display_area; | ||
2259 | 123 | geometry::Point old_cursor{}; | ||
2260 | 124 | std::weak_ptr<scene::Surface> active_surface_; | ||
2261 | 125 | using FullscreenSurfaces = std::set<std::weak_ptr<scene::Surface>, std::owner_less<std::weak_ptr<scene::Surface>>>; | ||
2262 | 126 | |||
2263 | 127 | FullscreenSurfaces fullscreen_surfaces; | ||
2264 | 128 | }; | ||
2265 | 129 | } | ||
2266 | 130 | } | ||
2267 | 131 | |||
2268 | 132 | #endif /* MIR_EXAMPLE_CANONICAL_WINDOW_MANAGER_H_ */ | ||
2269 | 0 | 133 | ||
2270 | === added file 'src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.cpp' | |||
2271 | --- src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.cpp 1970-01-01 00:00:00 +0000 | |||
2272 | +++ src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.cpp 2016-03-11 11:36:44 +0000 | |||
2273 | @@ -0,0 +1,640 @@ | |||
2274 | 1 | /* | ||
2275 | 2 | * Copyright © 2015 Canonical Ltd. | ||
2276 | 3 | * | ||
2277 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
2278 | 5 | * under the terms of the GNU General Public License version 3, | ||
2279 | 6 | * as published by the Free Software Foundation. | ||
2280 | 7 | * | ||
2281 | 8 | * This program is distributed in the hope that it will be useful, | ||
2282 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2283 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2284 | 11 | * GNU General Public License for more details. | ||
2285 | 12 | * | ||
2286 | 13 | * You should have received a copy of the GNU General Public License | ||
2287 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2288 | 15 | * | ||
2289 | 16 | * Authored By: Alan Griffiths <alan@octopull.co.uk> | ||
2290 | 17 | */ | ||
2291 | 18 | |||
2292 | 19 | #include "server_example_tiling_window_manager.h" | ||
2293 | 20 | |||
2294 | 21 | #include "mir/scene/session.h" | ||
2295 | 22 | #include "mir/scene/surface.h" | ||
2296 | 23 | #include "mir/scene/surface_creation_parameters.h" | ||
2297 | 24 | #include "mir/shell/surface_specification.h" | ||
2298 | 25 | #include "mir/shell/surface_stack.h" | ||
2299 | 26 | #include "mir/shell/surface_ready_observer.h" | ||
2300 | 27 | #include "mir/geometry/displacement.h" | ||
2301 | 28 | |||
2302 | 29 | #include <linux/input.h> | ||
2303 | 30 | #include <csignal> | ||
2304 | 31 | |||
2305 | 32 | namespace me = mir::examples; | ||
2306 | 33 | namespace ms = mir::scene; | ||
2307 | 34 | namespace mf = mir::frontend; | ||
2308 | 35 | using namespace mir::geometry; | ||
2309 | 36 | |||
2310 | 37 | ///\example server_example_tiling_window_manager.cpp | ||
2311 | 38 | /// Demonstrate implementing a simple tiling algorithm | ||
2312 | 39 | |||
2313 | 40 | me::TilingWindowManagerPolicy::TilingWindowManagerPolicy(WindowManagerTools* const tools) : | ||
2314 | 41 | tools{tools} | ||
2315 | 42 | { | ||
2316 | 43 | } | ||
2317 | 44 | |||
2318 | 45 | void me::TilingWindowManagerPolicy::click(Point cursor) | ||
2319 | 46 | { | ||
2320 | 47 | auto const session = session_under(cursor); | ||
2321 | 48 | auto const surface = tools->surface_at(cursor); | ||
2322 | 49 | select_active_surface(session, surface); | ||
2323 | 50 | } | ||
2324 | 51 | |||
2325 | 52 | void me::TilingWindowManagerPolicy::handle_session_info_updated(SessionInfoMap& session_info, Rectangles const& displays) | ||
2326 | 53 | { | ||
2327 | 54 | update_tiles(session_info, displays); | ||
2328 | 55 | } | ||
2329 | 56 | |||
2330 | 57 | void me::TilingWindowManagerPolicy::handle_displays_updated(SessionInfoMap& session_info, Rectangles const& displays) | ||
2331 | 58 | { | ||
2332 | 59 | update_tiles(session_info, displays); | ||
2333 | 60 | } | ||
2334 | 61 | |||
2335 | 62 | void me::TilingWindowManagerPolicy::resize(Point cursor) | ||
2336 | 63 | { | ||
2337 | 64 | if (auto const session = session_under(cursor)) | ||
2338 | 65 | { | ||
2339 | 66 | if (session == session_under(old_cursor)) | ||
2340 | 67 | { | ||
2341 | 68 | if (auto const surface = select_active_surface(session, tools->surface_at(old_cursor))) | ||
2342 | 69 | { | ||
2343 | 70 | resize(surface, cursor, old_cursor, tools->info_for(session).tile); | ||
2344 | 71 | } | ||
2345 | 72 | } | ||
2346 | 73 | } | ||
2347 | 74 | } | ||
2348 | 75 | |||
2349 | 76 | auto me::TilingWindowManagerPolicy::handle_place_new_surface( | ||
2350 | 77 | std::shared_ptr<ms::Session> const& session, | ||
2351 | 78 | ms::SurfaceCreationParameters const& request_parameters) | ||
2352 | 79 | -> ms::SurfaceCreationParameters | ||
2353 | 80 | { | ||
2354 | 81 | auto parameters = request_parameters; | ||
2355 | 82 | |||
2356 | 83 | Rectangle const& tile = tools->info_for(session).tile; | ||
2357 | 84 | parameters.top_left = parameters.top_left + (tile.top_left - Point{0, 0}); | ||
2358 | 85 | |||
2359 | 86 | if (auto const parent = parameters.parent.lock()) | ||
2360 | 87 | { | ||
2361 | 88 | auto const width = parameters.size.width.as_int(); | ||
2362 | 89 | auto const height = parameters.size.height.as_int(); | ||
2363 | 90 | |||
2364 | 91 | if (parameters.aux_rect.is_set() && parameters.edge_attachment.is_set()) | ||
2365 | 92 | { | ||
2366 | 93 | auto const edge_attachment = parameters.edge_attachment.value(); | ||
2367 | 94 | auto const aux_rect = parameters.aux_rect.value(); | ||
2368 | 95 | auto const parent_top_left = parent->top_left(); | ||
2369 | 96 | auto const top_left = aux_rect.top_left -Point{} + parent_top_left; | ||
2370 | 97 | auto const top_right= aux_rect.top_right() -Point{} + parent_top_left; | ||
2371 | 98 | auto const bot_left = aux_rect.bottom_left()-Point{} + parent_top_left; | ||
2372 | 99 | |||
2373 | 100 | if (edge_attachment & mir_edge_attachment_vertical) | ||
2374 | 101 | { | ||
2375 | 102 | if (tile.contains(top_right + Displacement{width, height})) | ||
2376 | 103 | { | ||
2377 | 104 | parameters.top_left = top_right; | ||
2378 | 105 | } | ||
2379 | 106 | else if (tile.contains(top_left + Displacement{-width, height})) | ||
2380 | 107 | { | ||
2381 | 108 | parameters.top_left = top_left + Displacement{-width, 0}; | ||
2382 | 109 | } | ||
2383 | 110 | } | ||
2384 | 111 | |||
2385 | 112 | if (edge_attachment & mir_edge_attachment_horizontal) | ||
2386 | 113 | { | ||
2387 | 114 | if (tile.contains(bot_left + Displacement{width, height})) | ||
2388 | 115 | { | ||
2389 | 116 | parameters.top_left = bot_left; | ||
2390 | 117 | } | ||
2391 | 118 | else if (tile.contains(top_left + Displacement{width, -height})) | ||
2392 | 119 | { | ||
2393 | 120 | parameters.top_left = top_left + Displacement{0, -height}; | ||
2394 | 121 | } | ||
2395 | 122 | } | ||
2396 | 123 | } | ||
2397 | 124 | else | ||
2398 | 125 | { | ||
2399 | 126 | auto const parent_top_left = parent->top_left(); | ||
2400 | 127 | auto const centred = parent_top_left | ||
2401 | 128 | + 0.5*(as_displacement(parent->size()) - as_displacement(parameters.size)) | ||
2402 | 129 | - DeltaY{(parent->size().height.as_int()-height)/6}; | ||
2403 | 130 | |||
2404 | 131 | parameters.top_left = centred; | ||
2405 | 132 | } | ||
2406 | 133 | } | ||
2407 | 134 | |||
2408 | 135 | clip_to_tile(parameters, tile); | ||
2409 | 136 | return parameters; | ||
2410 | 137 | } | ||
2411 | 138 | |||
2412 | 139 | void me::TilingWindowManagerPolicy::generate_decorations_for( | ||
2413 | 140 | std::shared_ptr<ms::Session> const&, | ||
2414 | 141 | std::shared_ptr<ms::Surface> const&, | ||
2415 | 142 | SurfaceInfoMap&, | ||
2416 | 143 | std::function<mf::SurfaceId(std::shared_ptr<ms::Session> const&, ms::SurfaceCreationParameters const&)> const&) | ||
2417 | 144 | { | ||
2418 | 145 | } | ||
2419 | 146 | |||
2420 | 147 | void me::TilingWindowManagerPolicy::handle_new_surface(std::shared_ptr<ms::Session> const& session, std::shared_ptr<ms::Surface> const& surface) | ||
2421 | 148 | { | ||
2422 | 149 | tools->info_for(session).surfaces.push_back(surface); | ||
2423 | 150 | |||
2424 | 151 | auto& surface_info = tools->info_for(surface); | ||
2425 | 152 | if (auto const parent = surface_info.parent.lock()) | ||
2426 | 153 | { | ||
2427 | 154 | tools->info_for(parent).children.push_back(surface); | ||
2428 | 155 | } | ||
2429 | 156 | |||
2430 | 157 | if (surface_info.can_be_active()) | ||
2431 | 158 | { | ||
2432 | 159 | surface->add_observer(std::make_shared<shell::SurfaceReadyObserver>( | ||
2433 | 160 | [this](std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface) | ||
2434 | 161 | { select_active_surface(session, surface); }, | ||
2435 | 162 | session, | ||
2436 | 163 | surface)); | ||
2437 | 164 | } | ||
2438 | 165 | } | ||
2439 | 166 | |||
2440 | 167 | void me::TilingWindowManagerPolicy::handle_modify_surface( | ||
2441 | 168 | std::shared_ptr<scene::Session> const& /*session*/, | ||
2442 | 169 | std::shared_ptr<scene::Surface> const& surface, | ||
2443 | 170 | shell::SurfaceSpecification const& modifications) | ||
2444 | 171 | { | ||
2445 | 172 | if (modifications.name.is_set()) | ||
2446 | 173 | surface->rename(modifications.name.value()); | ||
2447 | 174 | } | ||
2448 | 175 | |||
2449 | 176 | void me::TilingWindowManagerPolicy::handle_delete_surface(std::shared_ptr<ms::Session> const& session, std::weak_ptr<ms::Surface> const& surface) | ||
2450 | 177 | { | ||
2451 | 178 | auto& info = tools->info_for(surface); | ||
2452 | 179 | |||
2453 | 180 | if (auto const parent = info.parent.lock()) | ||
2454 | 181 | { | ||
2455 | 182 | auto& siblings = tools->info_for(parent).children; | ||
2456 | 183 | |||
2457 | 184 | for (auto i = begin(siblings); i != end(siblings); ++i) | ||
2458 | 185 | { | ||
2459 | 186 | if (surface.lock() == i->lock()) | ||
2460 | 187 | { | ||
2461 | 188 | siblings.erase(i); | ||
2462 | 189 | break; | ||
2463 | 190 | } | ||
2464 | 191 | } | ||
2465 | 192 | } | ||
2466 | 193 | |||
2467 | 194 | auto& surfaces = tools->info_for(session).surfaces; | ||
2468 | 195 | |||
2469 | 196 | for (auto i = begin(surfaces); i != end(surfaces); ++i) | ||
2470 | 197 | { | ||
2471 | 198 | if (surface.lock() == i->lock()) | ||
2472 | 199 | { | ||
2473 | 200 | surfaces.erase(i); | ||
2474 | 201 | break; | ||
2475 | 202 | } | ||
2476 | 203 | } | ||
2477 | 204 | |||
2478 | 205 | session->destroy_surface(surface); | ||
2479 | 206 | |||
2480 | 207 | if (surfaces.empty() && session == tools->focused_session()) | ||
2481 | 208 | { | ||
2482 | 209 | tools->focus_next_session(); | ||
2483 | 210 | select_active_surface(tools->focused_session(), tools->focused_surface()); | ||
2484 | 211 | } | ||
2485 | 212 | } | ||
2486 | 213 | |||
2487 | 214 | int me::TilingWindowManagerPolicy::handle_set_state(std::shared_ptr<ms::Surface> const& surface, MirSurfaceState value) | ||
2488 | 215 | { | ||
2489 | 216 | auto& info = tools->info_for(surface); | ||
2490 | 217 | |||
2491 | 218 | switch (value) | ||
2492 | 219 | { | ||
2493 | 220 | case mir_surface_state_restored: | ||
2494 | 221 | case mir_surface_state_maximized: | ||
2495 | 222 | case mir_surface_state_vertmaximized: | ||
2496 | 223 | case mir_surface_state_horizmaximized: | ||
2497 | 224 | break; | ||
2498 | 225 | |||
2499 | 226 | default: | ||
2500 | 227 | return info.state; | ||
2501 | 228 | } | ||
2502 | 229 | |||
2503 | 230 | if (info.state == mir_surface_state_restored) | ||
2504 | 231 | { | ||
2505 | 232 | info.restore_rect = {surface->top_left(), surface->size()}; | ||
2506 | 233 | } | ||
2507 | 234 | |||
2508 | 235 | if (info.state == value) | ||
2509 | 236 | { | ||
2510 | 237 | return info.state; | ||
2511 | 238 | } | ||
2512 | 239 | |||
2513 | 240 | auto const& tile = tools->info_for(info.session).tile; | ||
2514 | 241 | |||
2515 | 242 | switch (value) | ||
2516 | 243 | { | ||
2517 | 244 | case mir_surface_state_restored: | ||
2518 | 245 | surface->resize(info.restore_rect.size); | ||
2519 | 246 | drag(surface, info.restore_rect.top_left, surface->top_left(), tile); | ||
2520 | 247 | break; | ||
2521 | 248 | |||
2522 | 249 | case mir_surface_state_maximized: | ||
2523 | 250 | surface->resize(tile.size); | ||
2524 | 251 | drag(surface, tile.top_left, surface->top_left(), tile); | ||
2525 | 252 | break; | ||
2526 | 253 | |||
2527 | 254 | case mir_surface_state_horizmaximized: | ||
2528 | 255 | surface->resize({tile.size.width, info.restore_rect.size.height}); | ||
2529 | 256 | drag(surface, {tile.top_left.x, info.restore_rect.top_left.y}, surface->top_left(), tile); | ||
2530 | 257 | break; | ||
2531 | 258 | |||
2532 | 259 | case mir_surface_state_vertmaximized: | ||
2533 | 260 | surface->resize({info.restore_rect.size.width, tile.size.height}); | ||
2534 | 261 | drag(surface, {info.restore_rect.top_left.x, tile.top_left.y}, surface->top_left(), tile); | ||
2535 | 262 | break; | ||
2536 | 263 | |||
2537 | 264 | default: | ||
2538 | 265 | break; | ||
2539 | 266 | } | ||
2540 | 267 | |||
2541 | 268 | return info.state = value; | ||
2542 | 269 | } | ||
2543 | 270 | |||
2544 | 271 | void me::TilingWindowManagerPolicy::drag(Point cursor) | ||
2545 | 272 | { | ||
2546 | 273 | if (auto const session = session_under(cursor)) | ||
2547 | 274 | { | ||
2548 | 275 | if (session == session_under(old_cursor)) | ||
2549 | 276 | { | ||
2550 | 277 | if (auto const surface = select_active_surface(session, tools->surface_at(old_cursor))) | ||
2551 | 278 | { | ||
2552 | 279 | drag(surface, cursor, old_cursor, tools->info_for(session).tile); | ||
2553 | 280 | } | ||
2554 | 281 | } | ||
2555 | 282 | } | ||
2556 | 283 | } | ||
2557 | 284 | |||
2558 | 285 | void me::TilingWindowManagerPolicy::handle_raise_surface( | ||
2559 | 286 | std::shared_ptr<ms::Session> const& session, | ||
2560 | 287 | std::shared_ptr<ms::Surface> const& surface) | ||
2561 | 288 | { | ||
2562 | 289 | select_active_surface(session, surface); | ||
2563 | 290 | } | ||
2564 | 291 | |||
2565 | 292 | bool me::TilingWindowManagerPolicy::handle_keyboard_event(MirKeyboardEvent const* event) | ||
2566 | 293 | { | ||
2567 | 294 | auto const action = mir_keyboard_event_action(event); | ||
2568 | 295 | auto const scan_code = mir_keyboard_event_scan_code(event); | ||
2569 | 296 | auto const modifiers = mir_keyboard_event_modifiers(event) & modifier_mask; | ||
2570 | 297 | |||
2571 | 298 | if (action == mir_keyboard_action_down && scan_code == KEY_F11) | ||
2572 | 299 | { | ||
2573 | 300 | switch (modifiers & modifier_mask) | ||
2574 | 301 | { | ||
2575 | 302 | case mir_input_event_modifier_alt: | ||
2576 | 303 | toggle(mir_surface_state_maximized); | ||
2577 | 304 | return true; | ||
2578 | 305 | |||
2579 | 306 | case mir_input_event_modifier_shift: | ||
2580 | 307 | toggle(mir_surface_state_vertmaximized); | ||
2581 | 308 | return true; | ||
2582 | 309 | |||
2583 | 310 | case mir_input_event_modifier_ctrl: | ||
2584 | 311 | toggle(mir_surface_state_horizmaximized); | ||
2585 | 312 | return true; | ||
2586 | 313 | |||
2587 | 314 | default: | ||
2588 | 315 | break; | ||
2589 | 316 | } | ||
2590 | 317 | } | ||
2591 | 318 | else if (action == mir_keyboard_action_down && scan_code == KEY_F4) | ||
2592 | 319 | { | ||
2593 | 320 | if (auto const session = tools->focused_session()) | ||
2594 | 321 | { | ||
2595 | 322 | switch (modifiers & modifier_mask) | ||
2596 | 323 | { | ||
2597 | 324 | case mir_input_event_modifier_alt: | ||
2598 | 325 | kill(session->process_id(), SIGTERM); | ||
2599 | 326 | return true; | ||
2600 | 327 | |||
2601 | 328 | case mir_input_event_modifier_ctrl: | ||
2602 | 329 | if (auto const surf = session->default_surface()) | ||
2603 | 330 | { | ||
2604 | 331 | surf->request_client_surface_close(); | ||
2605 | 332 | return true; | ||
2606 | 333 | } | ||
2607 | 334 | |||
2608 | 335 | default: | ||
2609 | 336 | break; | ||
2610 | 337 | } | ||
2611 | 338 | } | ||
2612 | 339 | } | ||
2613 | 340 | else if (action == mir_keyboard_action_down && | ||
2614 | 341 | modifiers == mir_input_event_modifier_alt && | ||
2615 | 342 | scan_code == KEY_TAB) | ||
2616 | 343 | { | ||
2617 | 344 | tools->focus_next_session(); | ||
2618 | 345 | select_active_surface(tools->focused_session(), tools->focused_surface()); | ||
2619 | 346 | |||
2620 | 347 | return true; | ||
2621 | 348 | } | ||
2622 | 349 | else if (action == mir_keyboard_action_down && | ||
2623 | 350 | modifiers == mir_input_event_modifier_alt && | ||
2624 | 351 | scan_code == KEY_GRAVE) | ||
2625 | 352 | { | ||
2626 | 353 | if (auto const prev = tools->focused_surface()) | ||
2627 | 354 | { | ||
2628 | 355 | if (auto const app = tools->focused_session()) | ||
2629 | 356 | if (auto const surface = app->surface_after(prev)) | ||
2630 | 357 | { | ||
2631 | 358 | select_active_surface(app, surface); | ||
2632 | 359 | } | ||
2633 | 360 | } | ||
2634 | 361 | |||
2635 | 362 | return true; | ||
2636 | 363 | } | ||
2637 | 364 | |||
2638 | 365 | return false; | ||
2639 | 366 | } | ||
2640 | 367 | |||
2641 | 368 | bool me::TilingWindowManagerPolicy::handle_touch_event(MirTouchEvent const* event) | ||
2642 | 369 | { | ||
2643 | 370 | auto const count = mir_touch_event_point_count(event); | ||
2644 | 371 | |||
2645 | 372 | long total_x = 0; | ||
2646 | 373 | long total_y = 0; | ||
2647 | 374 | |||
2648 | 375 | for (auto i = 0U; i != count; ++i) | ||
2649 | 376 | { | ||
2650 | 377 | total_x += mir_touch_event_axis_value(event, i, mir_touch_axis_x); | ||
2651 | 378 | total_y += mir_touch_event_axis_value(event, i, mir_touch_axis_y); | ||
2652 | 379 | } | ||
2653 | 380 | |||
2654 | 381 | Point const cursor{total_x/count, total_y/count}; | ||
2655 | 382 | |||
2656 | 383 | bool is_drag = true; | ||
2657 | 384 | for (auto i = 0U; i != count; ++i) | ||
2658 | 385 | { | ||
2659 | 386 | switch (mir_touch_event_action(event, i)) | ||
2660 | 387 | { | ||
2661 | 388 | case mir_touch_action_up: | ||
2662 | 389 | return false; | ||
2663 | 390 | |||
2664 | 391 | case mir_touch_action_down: | ||
2665 | 392 | is_drag = false; | ||
2666 | 393 | |||
2667 | 394 | case mir_touch_action_change: | ||
2668 | 395 | continue; | ||
2669 | 396 | } | ||
2670 | 397 | } | ||
2671 | 398 | |||
2672 | 399 | bool consumes_event = false; | ||
2673 | 400 | if (is_drag) | ||
2674 | 401 | { | ||
2675 | 402 | switch (count) | ||
2676 | 403 | { | ||
2677 | 404 | case 2: | ||
2678 | 405 | resize(cursor); | ||
2679 | 406 | consumes_event = true; | ||
2680 | 407 | break; | ||
2681 | 408 | |||
2682 | 409 | case 3: | ||
2683 | 410 | drag(cursor); | ||
2684 | 411 | consumes_event = true; | ||
2685 | 412 | break; | ||
2686 | 413 | } | ||
2687 | 414 | } | ||
2688 | 415 | |||
2689 | 416 | old_cursor = cursor; | ||
2690 | 417 | return consumes_event; | ||
2691 | 418 | } | ||
2692 | 419 | |||
2693 | 420 | bool me::TilingWindowManagerPolicy::handle_pointer_event(MirPointerEvent const* event) | ||
2694 | 421 | { | ||
2695 | 422 | auto const action = mir_pointer_event_action(event); | ||
2696 | 423 | auto const modifiers = mir_pointer_event_modifiers(event) & modifier_mask; | ||
2697 | 424 | Point const cursor{ | ||
2698 | 425 | mir_pointer_event_axis_value(event, mir_pointer_axis_x), | ||
2699 | 426 | mir_pointer_event_axis_value(event, mir_pointer_axis_y)}; | ||
2700 | 427 | |||
2701 | 428 | bool consumes_event = false; | ||
2702 | 429 | |||
2703 | 430 | if (action == mir_pointer_action_button_down) | ||
2704 | 431 | { | ||
2705 | 432 | click(cursor); | ||
2706 | 433 | } | ||
2707 | 434 | else if (action == mir_pointer_action_motion && | ||
2708 | 435 | modifiers == mir_input_event_modifier_alt) | ||
2709 | 436 | { | ||
2710 | 437 | if (mir_pointer_event_button_state(event, mir_pointer_button_primary)) | ||
2711 | 438 | { | ||
2712 | 439 | drag(cursor); | ||
2713 | 440 | consumes_event = true; | ||
2714 | 441 | } | ||
2715 | 442 | else if (mir_pointer_event_button_state(event, mir_pointer_button_tertiary)) | ||
2716 | 443 | { | ||
2717 | 444 | resize(cursor); | ||
2718 | 445 | consumes_event = true; | ||
2719 | 446 | } | ||
2720 | 447 | } | ||
2721 | 448 | |||
2722 | 449 | old_cursor = cursor; | ||
2723 | 450 | return consumes_event; | ||
2724 | 451 | } | ||
2725 | 452 | |||
2726 | 453 | void me::TilingWindowManagerPolicy::toggle(MirSurfaceState state) | ||
2727 | 454 | { | ||
2728 | 455 | if (auto const session = tools->focused_session()) | ||
2729 | 456 | { | ||
2730 | 457 | if (auto const surface = session->default_surface()) | ||
2731 | 458 | { | ||
2732 | 459 | if (surface->state() == state) | ||
2733 | 460 | state = mir_surface_state_restored; | ||
2734 | 461 | |||
2735 | 462 | auto const value = handle_set_state(surface, MirSurfaceState(state)); | ||
2736 | 463 | surface->configure(mir_surface_attrib_state, value); | ||
2737 | 464 | } | ||
2738 | 465 | } | ||
2739 | 466 | } | ||
2740 | 467 | |||
2741 | 468 | std::shared_ptr<ms::Session> me::TilingWindowManagerPolicy::session_under(Point position) | ||
2742 | 469 | { | ||
2743 | 470 | return tools->find_session([&](SessionInfo const& info) { return info.tile.contains(position);}); | ||
2744 | 471 | } | ||
2745 | 472 | |||
2746 | 473 | void me::TilingWindowManagerPolicy::update_tiles( | ||
2747 | 474 | SessionInfoMap& session_info, | ||
2748 | 475 | Rectangles const& displays) | ||
2749 | 476 | { | ||
2750 | 477 | if (session_info.size() < 1 || displays.size() < 1) return; | ||
2751 | 478 | |||
2752 | 479 | auto const sessions = session_info.size(); | ||
2753 | 480 | |||
2754 | 481 | auto const bounding_rect = displays.bounding_rectangle(); | ||
2755 | 482 | |||
2756 | 483 | auto const total_width = bounding_rect.size.width.as_int(); | ||
2757 | 484 | auto const total_height = bounding_rect.size.height.as_int(); | ||
2758 | 485 | |||
2759 | 486 | auto index = 0; | ||
2760 | 487 | |||
2761 | 488 | for (auto& info : session_info) | ||
2762 | 489 | { | ||
2763 | 490 | auto const x = (total_width*index)/sessions; | ||
2764 | 491 | ++index; | ||
2765 | 492 | auto const dx = (total_width*index)/sessions - x; | ||
2766 | 493 | |||
2767 | 494 | auto const old_tile = info.second.tile; | ||
2768 | 495 | Rectangle const new_tile{{x, 0}, {dx, total_height}}; | ||
2769 | 496 | |||
2770 | 497 | update_surfaces(info.first, old_tile, new_tile); | ||
2771 | 498 | |||
2772 | 499 | info.second.tile = new_tile; | ||
2773 | 500 | } | ||
2774 | 501 | } | ||
2775 | 502 | |||
2776 | 503 | void me::TilingWindowManagerPolicy::update_surfaces(std::weak_ptr<ms::Session> const& session, Rectangle const& old_tile, Rectangle const& new_tile) | ||
2777 | 504 | { | ||
2778 | 505 | auto displacement = new_tile.top_left - old_tile.top_left; | ||
2779 | 506 | auto& info = tools->info_for(session); | ||
2780 | 507 | |||
2781 | 508 | for (auto const& ps : info.surfaces) | ||
2782 | 509 | { | ||
2783 | 510 | if (auto const surface = ps.lock()) | ||
2784 | 511 | { | ||
2785 | 512 | auto const old_pos = surface->top_left(); | ||
2786 | 513 | surface->move_to(old_pos + displacement); | ||
2787 | 514 | |||
2788 | 515 | fit_to_new_tile(*surface, old_tile, new_tile); | ||
2789 | 516 | } | ||
2790 | 517 | } | ||
2791 | 518 | } | ||
2792 | 519 | |||
2793 | 520 | void me::TilingWindowManagerPolicy::clip_to_tile(ms::SurfaceCreationParameters& parameters, Rectangle const& tile) | ||
2794 | 521 | { | ||
2795 | 522 | auto const displacement = parameters.top_left - tile.top_left; | ||
2796 | 523 | |||
2797 | 524 | auto width = std::min(tile.size.width.as_int()-displacement.dx.as_int(), parameters.size.width.as_int()); | ||
2798 | 525 | auto height = std::min(tile.size.height.as_int()-displacement.dy.as_int(), parameters.size.height.as_int()); | ||
2799 | 526 | |||
2800 | 527 | parameters.size = Size{width, height}; | ||
2801 | 528 | } | ||
2802 | 529 | |||
2803 | 530 | void me::TilingWindowManagerPolicy::fit_to_new_tile(ms::Surface& surface, Rectangle const& old_tile, Rectangle const& new_tile) | ||
2804 | 531 | { | ||
2805 | 532 | auto const displacement = surface.top_left() - new_tile.top_left; | ||
2806 | 533 | |||
2807 | 534 | // For now just scale if was filling width/height of tile | ||
2808 | 535 | auto const old_size = surface.size(); | ||
2809 | 536 | auto const scaled_width = old_size.width == old_tile.size.width ? new_tile.size.width : old_size.width; | ||
2810 | 537 | auto const scaled_height = old_size.height == old_tile.size.height ? new_tile.size.height : old_size.height; | ||
2811 | 538 | |||
2812 | 539 | auto width = std::min(new_tile.size.width.as_int()-displacement.dx.as_int(), scaled_width.as_int()); | ||
2813 | 540 | auto height = std::min(new_tile.size.height.as_int()-displacement.dy.as_int(), scaled_height.as_int()); | ||
2814 | 541 | |||
2815 | 542 | surface.resize({width, height}); | ||
2816 | 543 | } | ||
2817 | 544 | |||
2818 | 545 | void me::TilingWindowManagerPolicy::drag(std::shared_ptr<ms::Surface> surface, Point to, Point from, Rectangle bounds) | ||
2819 | 546 | { | ||
2820 | 547 | if (surface && surface->input_area_contains(from)) | ||
2821 | 548 | { | ||
2822 | 549 | auto movement = to - from; | ||
2823 | 550 | |||
2824 | 551 | constrained_move(surface, movement, bounds); | ||
2825 | 552 | |||
2826 | 553 | for (auto const& child: tools->info_for(surface).children) | ||
2827 | 554 | { | ||
2828 | 555 | auto move = movement; | ||
2829 | 556 | constrained_move(child.lock(), move, bounds); | ||
2830 | 557 | } | ||
2831 | 558 | } | ||
2832 | 559 | } | ||
2833 | 560 | |||
2834 | 561 | void me::TilingWindowManagerPolicy::constrained_move( | ||
2835 | 562 | std::shared_ptr<scene::Surface> const& surface, | ||
2836 | 563 | Displacement& movement, | ||
2837 | 564 | Rectangle const& bounds) | ||
2838 | 565 | { | ||
2839 | 566 | auto const top_left = surface->top_left(); | ||
2840 | 567 | auto const surface_size = surface->size(); | ||
2841 | 568 | auto const bottom_right = top_left + as_displacement(surface_size); | ||
2842 | 569 | |||
2843 | 570 | if (movement.dx < DeltaX{0}) | ||
2844 | 571 | movement.dx = std::max(movement.dx, (bounds.top_left - top_left).dx); | ||
2845 | 572 | |||
2846 | 573 | if (movement.dy < DeltaY{0}) | ||
2847 | 574 | movement.dy = std::max(movement.dy, (bounds.top_left - top_left).dy); | ||
2848 | 575 | |||
2849 | 576 | if (movement.dx > DeltaX{0}) | ||
2850 | 577 | movement.dx = std::min(movement.dx, (bounds.bottom_right() - bottom_right).dx); | ||
2851 | 578 | |||
2852 | 579 | if (movement.dy > DeltaY{0}) | ||
2853 | 580 | movement.dy = std::min(movement.dy, (bounds.bottom_right() - bottom_right).dy); | ||
2854 | 581 | |||
2855 | 582 | auto new_pos = surface->top_left() + movement; | ||
2856 | 583 | |||
2857 | 584 | surface->move_to(new_pos); | ||
2858 | 585 | } | ||
2859 | 586 | |||
2860 | 587 | void me::TilingWindowManagerPolicy::resize(std::shared_ptr<ms::Surface> surface, Point cursor, Point old_cursor, Rectangle bounds) | ||
2861 | 588 | { | ||
2862 | 589 | if (surface && surface->input_area_contains(old_cursor)) | ||
2863 | 590 | { | ||
2864 | 591 | auto const top_left = surface->top_left(); | ||
2865 | 592 | |||
2866 | 593 | auto const old_displacement = old_cursor - top_left; | ||
2867 | 594 | auto const new_displacement = cursor - top_left; | ||
2868 | 595 | |||
2869 | 596 | auto const scale_x = new_displacement.dx.as_float()/std::max(1.0f, old_displacement.dx.as_float()); | ||
2870 | 597 | auto const scale_y = new_displacement.dy.as_float()/std::max(1.0f, old_displacement.dy.as_float()); | ||
2871 | 598 | |||
2872 | 599 | if (scale_x <= 0.0f || scale_y <= 0.0f) return; | ||
2873 | 600 | |||
2874 | 601 | auto const old_size = surface->size(); | ||
2875 | 602 | Size new_size{scale_x*old_size.width, scale_y*old_size.height}; | ||
2876 | 603 | |||
2877 | 604 | auto const size_limits = as_size(bounds.bottom_right() - top_left); | ||
2878 | 605 | |||
2879 | 606 | if (new_size.width > size_limits.width) | ||
2880 | 607 | new_size.width = size_limits.width; | ||
2881 | 608 | |||
2882 | 609 | if (new_size.height > size_limits.height) | ||
2883 | 610 | new_size.height = size_limits.height; | ||
2884 | 611 | |||
2885 | 612 | surface->resize(new_size); | ||
2886 | 613 | } | ||
2887 | 614 | } | ||
2888 | 615 | |||
2889 | 616 | std::shared_ptr<ms::Surface> me::TilingWindowManagerPolicy::select_active_surface(std::shared_ptr<ms::Session> const& session, std::shared_ptr<scene::Surface> const& surface) | ||
2890 | 617 | { | ||
2891 | 618 | if (!surface) | ||
2892 | 619 | { | ||
2893 | 620 | tools->set_focus_to({}, {}); | ||
2894 | 621 | return surface; | ||
2895 | 622 | } | ||
2896 | 623 | |||
2897 | 624 | auto const& info_for = tools->info_for(surface); | ||
2898 | 625 | |||
2899 | 626 | if (info_for.can_be_active()) | ||
2900 | 627 | { | ||
2901 | 628 | tools->set_focus_to(session, surface); | ||
2902 | 629 | tools->raise_tree(surface); | ||
2903 | 630 | return surface; | ||
2904 | 631 | } | ||
2905 | 632 | else | ||
2906 | 633 | { | ||
2907 | 634 | // Cannot have input focus - try the parent | ||
2908 | 635 | if (auto const parent = info_for.parent.lock()) | ||
2909 | 636 | return select_active_surface(session, parent); | ||
2910 | 637 | |||
2911 | 638 | return {}; | ||
2912 | 639 | } | ||
2913 | 640 | } | ||
2914 | 0 | 641 | ||
2915 | === added file 'src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.h' | |||
2916 | --- src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.h 1970-01-01 00:00:00 +0000 | |||
2917 | +++ src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.h 2016-03-11 11:36:44 +0000 | |||
2918 | @@ -0,0 +1,124 @@ | |||
2919 | 1 | /* | ||
2920 | 2 | * Copyright © 2015 Canonical Ltd. | ||
2921 | 3 | * | ||
2922 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
2923 | 5 | * under the terms of the GNU General Public License version 3, | ||
2924 | 6 | * as published by the Free Software Foundation. | ||
2925 | 7 | * | ||
2926 | 8 | * This program is distributed in the hope that it will be useful, | ||
2927 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2928 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2929 | 11 | * GNU General Public License for more details. | ||
2930 | 12 | * | ||
2931 | 13 | * You should have received a copy of the GNU General Public License | ||
2932 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2933 | 15 | * | ||
2934 | 16 | * Authored By: Alan Griffiths <alan@octopull.co.uk> | ||
2935 | 17 | */ | ||
2936 | 18 | |||
2937 | 19 | #ifndef MIR_EXAMPLE_TILING_WINDOW_MANAGER_H_ | ||
2938 | 20 | #define MIR_EXAMPLE_TILING_WINDOW_MANAGER_H_ | ||
2939 | 21 | |||
2940 | 22 | #include "server_example_basic_window_manager.h" | ||
2941 | 23 | |||
2942 | 24 | ///\example server_example_tiling_window_manager.h | ||
2943 | 25 | /// Demonstrate implementing a simple tiling algorithm | ||
2944 | 26 | |||
2945 | 27 | namespace mir | ||
2946 | 28 | { | ||
2947 | 29 | namespace examples | ||
2948 | 30 | { | ||
2949 | 31 | // simple tiling algorithm: | ||
2950 | 32 | // o Switch apps: tap or click on the corresponding tile | ||
2951 | 33 | // o Move window: Alt-leftmousebutton drag (three finger drag) | ||
2952 | 34 | // o Resize window: Alt-middle_button drag (two finger drag) | ||
2953 | 35 | // o Maximize/restore current window (to tile size): Alt-F11 | ||
2954 | 36 | // o Maximize/restore current window (to tile height): Shift-F11 | ||
2955 | 37 | // o Maximize/restore current window (to tile width): Ctrl-F11 | ||
2956 | 38 | // o client requests to maximize, vertically maximize & restore | ||
2957 | 39 | class TilingWindowManagerPolicy : public WindowManagementPolicy | ||
2958 | 40 | { | ||
2959 | 41 | public: | ||
2960 | 42 | explicit TilingWindowManagerPolicy(WindowManagerTools* const tools); | ||
2961 | 43 | |||
2962 | 44 | void click(geometry::Point cursor); | ||
2963 | 45 | |||
2964 | 46 | void handle_session_info_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays); | ||
2965 | 47 | |||
2966 | 48 | void handle_displays_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays); | ||
2967 | 49 | |||
2968 | 50 | void resize(geometry::Point cursor); | ||
2969 | 51 | |||
2970 | 52 | auto handle_place_new_surface( | ||
2971 | 53 | std::shared_ptr<scene::Session> const& session, | ||
2972 | 54 | scene::SurfaceCreationParameters const& request_parameters) | ||
2973 | 55 | -> scene::SurfaceCreationParameters; | ||
2974 | 56 | |||
2975 | 57 | void handle_new_surface(std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface); | ||
2976 | 58 | |||
2977 | 59 | void handle_modify_surface( | ||
2978 | 60 | std::shared_ptr<scene::Session> const& session, | ||
2979 | 61 | std::shared_ptr<scene::Surface> const& surface, | ||
2980 | 62 | shell::SurfaceSpecification const& modifications); | ||
2981 | 63 | |||
2982 | 64 | void handle_delete_surface(std::shared_ptr<scene::Session> const& session, std::weak_ptr<scene::Surface> const& surface); | ||
2983 | 65 | |||
2984 | 66 | int handle_set_state(std::shared_ptr<scene::Surface> const& surface, MirSurfaceState value); | ||
2985 | 67 | |||
2986 | 68 | void drag(geometry::Point cursor); | ||
2987 | 69 | |||
2988 | 70 | bool handle_keyboard_event(MirKeyboardEvent const* event); | ||
2989 | 71 | |||
2990 | 72 | bool handle_touch_event(MirTouchEvent const* event); | ||
2991 | 73 | |||
2992 | 74 | bool handle_pointer_event(MirPointerEvent const* event); | ||
2993 | 75 | |||
2994 | 76 | void handle_raise_surface( | ||
2995 | 77 | std::shared_ptr<scene::Session> const& session, | ||
2996 | 78 | std::shared_ptr<scene::Surface> const& surface); | ||
2997 | 79 | |||
2998 | 80 | void generate_decorations_for( | ||
2999 | 81 | std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface, | ||
3000 | 82 | SurfaceInfoMap& surface_info, | ||
3001 | 83 | std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const&, scene::SurfaceCreationParameters const&)> const& build); | ||
3002 | 84 | |||
3003 | 85 | private: | ||
3004 | 86 | static const int modifier_mask = | ||
3005 | 87 | mir_input_event_modifier_alt | | ||
3006 | 88 | mir_input_event_modifier_shift | | ||
3007 | 89 | mir_input_event_modifier_sym | | ||
3008 | 90 | mir_input_event_modifier_ctrl | | ||
3009 | 91 | mir_input_event_modifier_meta; | ||
3010 | 92 | |||
3011 | 93 | void toggle(MirSurfaceState state); | ||
3012 | 94 | |||
3013 | 95 | std::shared_ptr<scene::Session> session_under(geometry::Point position); | ||
3014 | 96 | |||
3015 | 97 | void update_tiles( | ||
3016 | 98 | SessionInfoMap& session_info, | ||
3017 | 99 | geometry::Rectangles const& displays); | ||
3018 | 100 | |||
3019 | 101 | void update_surfaces(std::weak_ptr<scene::Session> const& session, geometry::Rectangle const& old_tile, geometry::Rectangle const& new_tile); | ||
3020 | 102 | |||
3021 | 103 | static void clip_to_tile(scene::SurfaceCreationParameters& parameters, geometry::Rectangle const& tile); | ||
3022 | 104 | |||
3023 | 105 | static void fit_to_new_tile(scene::Surface& surface, geometry::Rectangle const& old_tile, geometry::Rectangle const& new_tile); | ||
3024 | 106 | |||
3025 | 107 | void drag(std::shared_ptr<scene::Surface> surface, geometry::Point to, geometry::Point from, geometry::Rectangle bounds); | ||
3026 | 108 | |||
3027 | 109 | static void resize(std::shared_ptr<scene::Surface> surface, geometry::Point cursor, geometry::Point old_cursor, geometry::Rectangle bounds); | ||
3028 | 110 | |||
3029 | 111 | static void constrained_move(std::shared_ptr<scene::Surface> const& surface, geometry::Displacement& movement, geometry::Rectangle const& bounds); | ||
3030 | 112 | |||
3031 | 113 | std::shared_ptr<scene::Surface> select_active_surface(std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface); | ||
3032 | 114 | |||
3033 | 115 | WindowManagerTools* const tools; | ||
3034 | 116 | |||
3035 | 117 | geometry::Point old_cursor{}; | ||
3036 | 118 | }; | ||
3037 | 119 | |||
3038 | 120 | using TilingWindowManager = WindowManagerBuilder<TilingWindowManagerPolicy>; | ||
3039 | 121 | } | ||
3040 | 122 | } | ||
3041 | 123 | |||
3042 | 124 | #endif /* MIR_EXAMPLE_TILING_WINDOW_MANAGER_H_ */ | ||
3043 | 0 | 125 | ||
3044 | === added file 'src/platforms/mirserver/wm-wip/server_example_window_management.cpp' | |||
3045 | --- src/platforms/mirserver/wm-wip/server_example_window_management.cpp 1970-01-01 00:00:00 +0000 | |||
3046 | +++ src/platforms/mirserver/wm-wip/server_example_window_management.cpp 2016-03-11 11:36:44 +0000 | |||
3047 | @@ -0,0 +1,155 @@ | |||
3048 | 1 | /* | ||
3049 | 2 | * Copyright © 2014 Canonical Ltd. | ||
3050 | 3 | * | ||
3051 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
3052 | 5 | * under the terms of the GNU General Public License version 3, | ||
3053 | 6 | * as published by the Free Software Foundation. | ||
3054 | 7 | * | ||
3055 | 8 | * This program is distributed in the hope that it will be useful, | ||
3056 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
3057 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
3058 | 11 | * GNU General Public License for more details. | ||
3059 | 12 | * | ||
3060 | 13 | * You should have received a copy of the GNU General Public License | ||
3061 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3062 | 15 | * | ||
3063 | 16 | * Authored By: Alan Griffiths <alan@octopull.co.uk> | ||
3064 | 17 | */ | ||
3065 | 18 | |||
3066 | 19 | #include "server_example_window_management.h" | ||
3067 | 20 | |||
3068 | 21 | #include "server_example_tiling_window_manager.h" | ||
3069 | 22 | #include "server_example_canonical_window_manager.h" | ||
3070 | 23 | |||
3071 | 24 | #include "mir/abnormal_exit.h" | ||
3072 | 25 | #include "mir/server.h" | ||
3073 | 26 | #include "mir/input/composite_event_filter.h" | ||
3074 | 27 | #include "mir/options/option.h" | ||
3075 | 28 | #include "mir/scene/session.h" | ||
3076 | 29 | #include "mir/scene/surface_creation_parameters.h" | ||
3077 | 30 | #include "mir/shell/display_layout.h" | ||
3078 | 31 | #include "mir/shell/system_compositor_window_manager.h" | ||
3079 | 32 | |||
3080 | 33 | namespace me = mir::examples; | ||
3081 | 34 | namespace mf = mir::frontend; | ||
3082 | 35 | namespace mg = mir::graphics; | ||
3083 | 36 | namespace mi = mir::input; | ||
3084 | 37 | namespace ms = mir::scene; | ||
3085 | 38 | namespace msh = mir::shell; | ||
3086 | 39 | using namespace mir::geometry; | ||
3087 | 40 | |||
3088 | 41 | ///\example server_example_window_management.cpp | ||
3089 | 42 | /// Demonstrate introducing a window management strategy | ||
3090 | 43 | |||
3091 | 44 | namespace | ||
3092 | 45 | { | ||
3093 | 46 | char const* const wm_option = "window-manager"; | ||
3094 | 47 | char const* const wm_description = "window management strategy [{tiling|fullscreen|canonical|system-compositor}]"; | ||
3095 | 48 | |||
3096 | 49 | char const* const wm_tiling = "tiling"; | ||
3097 | 50 | char const* const wm_fullscreen = "fullscreen"; | ||
3098 | 51 | char const* const wm_canonical = "canonical"; | ||
3099 | 52 | char const* const wm_system_compositor = "system-compositor"; | ||
3100 | 53 | |||
3101 | 54 | // Very simple - make every surface fullscreen | ||
3102 | 55 | class FullscreenWindowManagerPolicy : public me::WindowManagementPolicy | ||
3103 | 56 | { | ||
3104 | 57 | public: | ||
3105 | 58 | FullscreenWindowManagerPolicy(me::WindowManagerTools* const /*tools*/, std::shared_ptr<msh::DisplayLayout> const& display_layout) : | ||
3106 | 59 | display_layout{display_layout} {} | ||
3107 | 60 | |||
3108 | 61 | void handle_session_info_updated(SessionInfoMap& /*session_info*/, Rectangles const& /*displays*/) {} | ||
3109 | 62 | |||
3110 | 63 | void handle_displays_updated(SessionInfoMap& /*session_info*/, Rectangles const& /*displays*/) {} | ||
3111 | 64 | |||
3112 | 65 | auto handle_place_new_surface( | ||
3113 | 66 | std::shared_ptr<ms::Session> const& /*session*/, | ||
3114 | 67 | ms::SurfaceCreationParameters const& request_parameters) | ||
3115 | 68 | -> ms::SurfaceCreationParameters | ||
3116 | 69 | { | ||
3117 | 70 | auto placed_parameters = request_parameters; | ||
3118 | 71 | |||
3119 | 72 | Rectangle rect{request_parameters.top_left, request_parameters.size}; | ||
3120 | 73 | display_layout->size_to_output(rect); | ||
3121 | 74 | placed_parameters.size = rect.size; | ||
3122 | 75 | |||
3123 | 76 | return placed_parameters; | ||
3124 | 77 | } | ||
3125 | 78 | void handle_modify_surface( | ||
3126 | 79 | std::shared_ptr<ms::Session> const& /*session*/, | ||
3127 | 80 | std::shared_ptr<ms::Surface> const& /*surface*/, | ||
3128 | 81 | msh::SurfaceSpecification const& /*modifications*/) | ||
3129 | 82 | { | ||
3130 | 83 | } | ||
3131 | 84 | |||
3132 | 85 | void handle_new_surface(std::shared_ptr<ms::Session> const& /*session*/, std::shared_ptr<ms::Surface> const& /*surface*/) | ||
3133 | 86 | { | ||
3134 | 87 | } | ||
3135 | 88 | |||
3136 | 89 | void handle_delete_surface(std::shared_ptr<ms::Session> const& session, std::weak_ptr<ms::Surface> const& surface) | ||
3137 | 90 | { session->destroy_surface(surface); } | ||
3138 | 91 | |||
3139 | 92 | int handle_set_state(std::shared_ptr<ms::Surface> const& /*surface*/, MirSurfaceState value) | ||
3140 | 93 | { return value; } | ||
3141 | 94 | |||
3142 | 95 | bool handle_keyboard_event(MirKeyboardEvent const* /*event*/) { return false; } | ||
3143 | 96 | |||
3144 | 97 | bool handle_touch_event(MirTouchEvent const* /*event*/) { return false; } | ||
3145 | 98 | |||
3146 | 99 | bool handle_pointer_event(MirPointerEvent const* /*event*/) { return false; } | ||
3147 | 100 | |||
3148 | 101 | void handle_raise_surface( | ||
3149 | 102 | std::shared_ptr<ms::Session> const& /*session*/, | ||
3150 | 103 | std::shared_ptr<ms::Surface> const& /*surface*/) | ||
3151 | 104 | { | ||
3152 | 105 | } | ||
3153 | 106 | |||
3154 | 107 | void generate_decorations_for( | ||
3155 | 108 | std::shared_ptr<ms::Session> const&, | ||
3156 | 109 | std::shared_ptr<ms::Surface> const&, | ||
3157 | 110 | SurfaceInfoMap&, | ||
3158 | 111 | std::function<mf::SurfaceId(std::shared_ptr<ms::Session> const&, ms::SurfaceCreationParameters const&)> const&) | ||
3159 | 112 | { | ||
3160 | 113 | } | ||
3161 | 114 | private: | ||
3162 | 115 | std::shared_ptr<msh::DisplayLayout> const display_layout; | ||
3163 | 116 | }; | ||
3164 | 117 | |||
3165 | 118 | } | ||
3166 | 119 | |||
3167 | 120 | using FullscreenWindowManager = me::WindowManagerBuilder<FullscreenWindowManagerPolicy>; | ||
3168 | 121 | using CanonicalWindowManager = me::WindowManagerBuilder<me::CanonicalWindowManagerPolicyCopy>; | ||
3169 | 122 | |||
3170 | 123 | void me::add_window_manager_option_to(Server& server) | ||
3171 | 124 | { | ||
3172 | 125 | server.add_configuration_option(wm_option, wm_description, wm_canonical); | ||
3173 | 126 | |||
3174 | 127 | server.override_the_window_manager_builder([&server](msh::FocusController* focus_controller) | ||
3175 | 128 | -> std::shared_ptr<msh::WindowManager> | ||
3176 | 129 | { | ||
3177 | 130 | auto const options = server.get_options(); | ||
3178 | 131 | auto const selection = options->get<std::string>(wm_option); | ||
3179 | 132 | |||
3180 | 133 | if (selection == wm_tiling) | ||
3181 | 134 | { | ||
3182 | 135 | return std::make_shared<TilingWindowManager>(focus_controller); | ||
3183 | 136 | } | ||
3184 | 137 | else if (selection == wm_fullscreen) | ||
3185 | 138 | { | ||
3186 | 139 | return std::make_shared<FullscreenWindowManager>(focus_controller, server.the_shell_display_layout()); | ||
3187 | 140 | } | ||
3188 | 141 | else if (selection == wm_canonical) | ||
3189 | 142 | { | ||
3190 | 143 | return std::make_shared<CanonicalWindowManager>(focus_controller, server.the_shell_display_layout()); | ||
3191 | 144 | } | ||
3192 | 145 | else if (selection == wm_system_compositor) | ||
3193 | 146 | { | ||
3194 | 147 | return std::make_shared<msh::SystemCompositorWindowManager>( | ||
3195 | 148 | focus_controller, | ||
3196 | 149 | server.the_shell_display_layout(), | ||
3197 | 150 | server.the_session_coordinator()); | ||
3198 | 151 | } | ||
3199 | 152 | |||
3200 | 153 | throw mir::AbnormalExit("Unknown window manager: " + selection); | ||
3201 | 154 | }); | ||
3202 | 155 | } | ||
3203 | 0 | 156 | ||
3204 | === added file 'src/platforms/mirserver/wm-wip/server_example_window_management.h' | |||
3205 | --- src/platforms/mirserver/wm-wip/server_example_window_management.h 1970-01-01 00:00:00 +0000 | |||
3206 | +++ src/platforms/mirserver/wm-wip/server_example_window_management.h 2016-03-11 11:36:44 +0000 | |||
3207 | @@ -0,0 +1,33 @@ | |||
3208 | 1 | /* | ||
3209 | 2 | * Copyright © 2014 Canonical Ltd. | ||
3210 | 3 | * | ||
3211 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
3212 | 5 | * under the terms of the GNU General Public License version 3, | ||
3213 | 6 | * as published by the Free Software Foundation. | ||
3214 | 7 | * | ||
3215 | 8 | * This program is distributed in the hope that it will be useful, | ||
3216 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
3217 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
3218 | 11 | * GNU General Public License for more details. | ||
3219 | 12 | * | ||
3220 | 13 | * You should have received a copy of the GNU General Public License | ||
3221 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3222 | 15 | * | ||
3223 | 16 | * Authored By: Alan Griffiths <alan@octopull.co.uk> | ||
3224 | 17 | */ | ||
3225 | 18 | |||
3226 | 19 | #ifndef MIR_EXAMPLES_WINDOW_MANAGEMENT_H_ | ||
3227 | 20 | #define MIR_EXAMPLES_WINDOW_MANAGEMENT_H_ | ||
3228 | 21 | |||
3229 | 22 | namespace mir | ||
3230 | 23 | { | ||
3231 | 24 | class Server; | ||
3232 | 25 | |||
3233 | 26 | namespace examples | ||
3234 | 27 | { | ||
3235 | 28 | void add_window_manager_option_to(Server& server); | ||
3236 | 29 | } | ||
3237 | 30 | } // namespace mir | ||
3238 | 31 | |||
3239 | 32 | |||
3240 | 33 | #endif // MIR_EXAMPLES_WINDOW_MANAGEMENT_H_ | ||
3241 | 0 | 34 | ||
3242 | === added file 'src/platforms/mirserver/wm-wip/server_example_window_management_info.cpp' | |||
3243 | --- src/platforms/mirserver/wm-wip/server_example_window_management_info.cpp 1970-01-01 00:00:00 +0000 | |||
3244 | +++ src/platforms/mirserver/wm-wip/server_example_window_management_info.cpp 2016-03-11 11:36:44 +0000 | |||
3245 | @@ -0,0 +1,406 @@ | |||
3246 | 1 | /* | ||
3247 | 2 | * Copyright © 2015 Canonical Ltd. | ||
3248 | 3 | * | ||
3249 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
3250 | 5 | * under the terms of the GNU General Public License version 3, | ||
3251 | 6 | * as published by the Free Software Foundation. | ||
3252 | 7 | * | ||
3253 | 8 | * This program is distributed in the hope that it will be useful, | ||
3254 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
3255 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
3256 | 11 | * GNU General Public License for more details. | ||
3257 | 12 | * | ||
3258 | 13 | * You should have received a copy of the GNU General Public License | ||
3259 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3260 | 15 | * | ||
3261 | 16 | * Authored by: Alan Griffiths <alan@octopull.co.uk> | ||
3262 | 17 | */ | ||
3263 | 18 | |||
3264 | 19 | #include "server_example_window_management_info.h" | ||
3265 | 20 | |||
3266 | 21 | #include "mir/scene/surface.h" | ||
3267 | 22 | #include "mir/scene/surface_creation_parameters.h" | ||
3268 | 23 | |||
3269 | 24 | #include "mir/graphics/buffer.h" | ||
3270 | 25 | |||
3271 | 26 | #include <atomic> | ||
3272 | 27 | |||
3273 | 28 | namespace me = mir::examples; | ||
3274 | 29 | namespace ms = mir::scene; | ||
3275 | 30 | namespace mg = mir::graphics; | ||
3276 | 31 | using namespace mir::geometry; | ||
3277 | 32 | |||
3278 | 33 | me::SurfaceInfo::SurfaceInfo( | ||
3279 | 34 | std::shared_ptr<scene::Session> const& session, | ||
3280 | 35 | std::shared_ptr<scene::Surface> const& surface, | ||
3281 | 36 | scene::SurfaceCreationParameters const& params) : | ||
3282 | 37 | type{surface->type()}, | ||
3283 | 38 | state{surface->state()}, | ||
3284 | 39 | restore_rect{surface->top_left(), surface->size()}, | ||
3285 | 40 | session{session}, | ||
3286 | 41 | parent{params.parent}, | ||
3287 | 42 | min_width{params.min_width.is_set() ? params.min_width.value() : Width{}}, | ||
3288 | 43 | min_height{params.min_height.is_set() ? params.min_height.value() : Height{}}, | ||
3289 | 44 | max_width{params.max_width.is_set() ? params.max_width.value() : Width{std::numeric_limits<int>::max()}}, | ||
3290 | 45 | max_height{params.max_height.is_set() ? params.max_height.value() : Height{std::numeric_limits<int>::max()}}, | ||
3291 | 46 | width_inc{params.width_inc}, | ||
3292 | 47 | height_inc{params.height_inc}, | ||
3293 | 48 | min_aspect{params.min_aspect}, | ||
3294 | 49 | max_aspect{params.max_aspect} | ||
3295 | 50 | { | ||
3296 | 51 | if (params.output_id != mir::graphics::DisplayConfigurationOutputId{0}) | ||
3297 | 52 | output_id = params.output_id; | ||
3298 | 53 | } | ||
3299 | 54 | |||
3300 | 55 | bool me::SurfaceInfo::can_be_active() const | ||
3301 | 56 | { | ||
3302 | 57 | switch (type) | ||
3303 | 58 | { | ||
3304 | 59 | case mir_surface_type_normal: /**< AKA "regular" */ | ||
3305 | 60 | case mir_surface_type_utility: /**< AKA "floating" */ | ||
3306 | 61 | case mir_surface_type_dialog: | ||
3307 | 62 | case mir_surface_type_satellite: /**< AKA "toolbox"/"toolbar" */ | ||
3308 | 63 | case mir_surface_type_freestyle: | ||
3309 | 64 | case mir_surface_type_menu: | ||
3310 | 65 | case mir_surface_type_inputmethod: /**< AKA "OSK" or handwriting etc. */ | ||
3311 | 66 | return true; | ||
3312 | 67 | |||
3313 | 68 | case mir_surface_type_gloss: | ||
3314 | 69 | case mir_surface_type_tip: /**< AKA "tooltip" */ | ||
3315 | 70 | default: | ||
3316 | 71 | // Cannot have input focus | ||
3317 | 72 | return false; | ||
3318 | 73 | } | ||
3319 | 74 | } | ||
3320 | 75 | |||
3321 | 76 | bool me::SurfaceInfo::must_have_parent() const | ||
3322 | 77 | { | ||
3323 | 78 | switch (type) | ||
3324 | 79 | { | ||
3325 | 80 | case mir_surface_type_overlay:; | ||
3326 | 81 | case mir_surface_type_inputmethod: | ||
3327 | 82 | case mir_surface_type_satellite: | ||
3328 | 83 | case mir_surface_type_tip: | ||
3329 | 84 | return true; | ||
3330 | 85 | |||
3331 | 86 | default: | ||
3332 | 87 | return false; | ||
3333 | 88 | } | ||
3334 | 89 | } | ||
3335 | 90 | |||
3336 | 91 | bool me::SurfaceInfo::can_morph_to(MirSurfaceType new_type) const | ||
3337 | 92 | { | ||
3338 | 93 | switch (new_type) | ||
3339 | 94 | { | ||
3340 | 95 | case mir_surface_type_normal: | ||
3341 | 96 | case mir_surface_type_utility: | ||
3342 | 97 | case mir_surface_type_satellite: | ||
3343 | 98 | switch (type) | ||
3344 | 99 | { | ||
3345 | 100 | case mir_surface_type_normal: | ||
3346 | 101 | case mir_surface_type_utility: | ||
3347 | 102 | case mir_surface_type_dialog: | ||
3348 | 103 | case mir_surface_type_satellite: | ||
3349 | 104 | return true; | ||
3350 | 105 | |||
3351 | 106 | default: | ||
3352 | 107 | break; | ||
3353 | 108 | } | ||
3354 | 109 | break; | ||
3355 | 110 | |||
3356 | 111 | case mir_surface_type_dialog: | ||
3357 | 112 | switch (type) | ||
3358 | 113 | { | ||
3359 | 114 | case mir_surface_type_normal: | ||
3360 | 115 | case mir_surface_type_utility: | ||
3361 | 116 | case mir_surface_type_dialog: | ||
3362 | 117 | case mir_surface_type_popover: | ||
3363 | 118 | case mir_surface_type_satellite: | ||
3364 | 119 | return true; | ||
3365 | 120 | |||
3366 | 121 | default: | ||
3367 | 122 | break; | ||
3368 | 123 | } | ||
3369 | 124 | break; | ||
3370 | 125 | |||
3371 | 126 | default: | ||
3372 | 127 | break; | ||
3373 | 128 | } | ||
3374 | 129 | |||
3375 | 130 | return false; | ||
3376 | 131 | } | ||
3377 | 132 | |||
3378 | 133 | bool me::SurfaceInfo::must_not_have_parent() const | ||
3379 | 134 | { | ||
3380 | 135 | switch (type) | ||
3381 | 136 | { | ||
3382 | 137 | case mir_surface_type_normal: | ||
3383 | 138 | case mir_surface_type_utility: | ||
3384 | 139 | return true; | ||
3385 | 140 | |||
3386 | 141 | default: | ||
3387 | 142 | return false; | ||
3388 | 143 | } | ||
3389 | 144 | } | ||
3390 | 145 | |||
3391 | 146 | bool me::SurfaceInfo::is_visible() const | ||
3392 | 147 | { | ||
3393 | 148 | switch (state) | ||
3394 | 149 | { | ||
3395 | 150 | case mir_surface_state_hidden: | ||
3396 | 151 | case mir_surface_state_minimized: | ||
3397 | 152 | return false; | ||
3398 | 153 | default: | ||
3399 | 154 | break; | ||
3400 | 155 | } | ||
3401 | 156 | return true; | ||
3402 | 157 | } | ||
3403 | 158 | |||
3404 | 159 | struct mir::examples::SurfaceInfo::StreamPainter | ||
3405 | 160 | { | ||
3406 | 161 | virtual void paint(int) = 0; | ||
3407 | 162 | virtual ~StreamPainter() = default; | ||
3408 | 163 | StreamPainter() = default; | ||
3409 | 164 | StreamPainter(StreamPainter const&) = delete; | ||
3410 | 165 | StreamPainter& operator=(StreamPainter const&) = delete; | ||
3411 | 166 | }; | ||
3412 | 167 | |||
3413 | 168 | struct mir::examples::SurfaceInfo::SwappingPainter | ||
3414 | 169 | : mir::examples::SurfaceInfo::StreamPainter | ||
3415 | 170 | { | ||
3416 | 171 | SwappingPainter(std::shared_ptr<frontend::BufferStream> const& buffer_stream) : | ||
3417 | 172 | buffer_stream{buffer_stream}, buffer{nullptr} | ||
3418 | 173 | { | ||
3419 | 174 | swap_buffers(); | ||
3420 | 175 | } | ||
3421 | 176 | |||
3422 | 177 | void swap_buffers() | ||
3423 | 178 | { | ||
3424 | 179 | auto const callback = [this](mir::graphics::Buffer* new_buffer) | ||
3425 | 180 | { | ||
3426 | 181 | buffer.store(new_buffer); | ||
3427 | 182 | }; | ||
3428 | 183 | |||
3429 | 184 | buffer_stream->swap_buffers(buffer, callback); | ||
3430 | 185 | } | ||
3431 | 186 | |||
3432 | 187 | void paint(int intensity) override | ||
3433 | 188 | { | ||
3434 | 189 | if (auto const buf = buffer.load()) | ||
3435 | 190 | { | ||
3436 | 191 | auto const format = buffer_stream->pixel_format(); | ||
3437 | 192 | auto const sz = buf->size().height.as_int() * | ||
3438 | 193 | buf->size().width.as_int() * MIR_BYTES_PER_PIXEL(format); | ||
3439 | 194 | std::vector<unsigned char> pixels(sz, intensity); | ||
3440 | 195 | buf->write(pixels.data(), sz); | ||
3441 | 196 | swap_buffers(); | ||
3442 | 197 | } | ||
3443 | 198 | } | ||
3444 | 199 | |||
3445 | 200 | std::shared_ptr<frontend::BufferStream> const buffer_stream; | ||
3446 | 201 | std::atomic<graphics::Buffer*> buffer; | ||
3447 | 202 | }; | ||
3448 | 203 | |||
3449 | 204 | struct mir::examples::SurfaceInfo::AllocatingPainter | ||
3450 | 205 | : mir::examples::SurfaceInfo::StreamPainter | ||
3451 | 206 | { | ||
3452 | 207 | AllocatingPainter(std::shared_ptr<frontend::BufferStream> const& buffer_stream, Size size) : | ||
3453 | 208 | buffer_stream(buffer_stream), | ||
3454 | 209 | properties({ | ||
3455 | 210 | size, | ||
3456 | 211 | buffer_stream->pixel_format(), | ||
3457 | 212 | mg::BufferUsage::software | ||
3458 | 213 | }), | ||
3459 | 214 | front_buffer(buffer_stream->allocate_buffer(properties)), | ||
3460 | 215 | back_buffer(buffer_stream->allocate_buffer(properties)) | ||
3461 | 216 | { | ||
3462 | 217 | } | ||
3463 | 218 | |||
3464 | 219 | void paint(int intensity) override | ||
3465 | 220 | { | ||
3466 | 221 | buffer_stream->with_buffer(back_buffer, | ||
3467 | 222 | [this, intensity](graphics::Buffer& buffer) | ||
3468 | 223 | { | ||
3469 | 224 | auto const format = buffer.pixel_format(); | ||
3470 | 225 | auto const sz = buffer.size().height.as_int() * | ||
3471 | 226 | buffer.size().width.as_int() * MIR_BYTES_PER_PIXEL(format); | ||
3472 | 227 | std::vector<unsigned char> pixels(sz, intensity); | ||
3473 | 228 | buffer.write(pixels.data(), sz); | ||
3474 | 229 | buffer_stream->swap_buffers(&buffer, [](mg::Buffer*){}); | ||
3475 | 230 | }); | ||
3476 | 231 | std::swap(front_buffer, back_buffer); | ||
3477 | 232 | } | ||
3478 | 233 | |||
3479 | 234 | ~AllocatingPainter() | ||
3480 | 235 | { | ||
3481 | 236 | buffer_stream->remove_buffer(front_buffer); | ||
3482 | 237 | buffer_stream->remove_buffer(back_buffer); | ||
3483 | 238 | } | ||
3484 | 239 | |||
3485 | 240 | std::shared_ptr<frontend::BufferStream> const buffer_stream; | ||
3486 | 241 | mg::BufferProperties properties; | ||
3487 | 242 | mg::BufferID front_buffer; | ||
3488 | 243 | mg::BufferID back_buffer; | ||
3489 | 244 | }; | ||
3490 | 245 | |||
3491 | 246 | void mir::examples::SurfaceInfo::init_titlebar(std::shared_ptr<scene::Surface> const& surface) | ||
3492 | 247 | { | ||
3493 | 248 | auto stream = surface->primary_buffer_stream(); | ||
3494 | 249 | try | ||
3495 | 250 | { | ||
3496 | 251 | stream_painter = std::make_shared<AllocatingPainter>(stream, surface->size()); | ||
3497 | 252 | } | ||
3498 | 253 | catch (...) | ||
3499 | 254 | { | ||
3500 | 255 | stream_painter = std::make_shared<SwappingPainter>(stream); | ||
3501 | 256 | } | ||
3502 | 257 | } | ||
3503 | 258 | |||
3504 | 259 | void mir::examples::SurfaceInfo::paint_titlebar(int intensity) | ||
3505 | 260 | { | ||
3506 | 261 | stream_painter->paint(intensity); | ||
3507 | 262 | } | ||
3508 | 263 | |||
3509 | 264 | void me::SurfaceInfo::constrain_resize( | ||
3510 | 265 | std::shared_ptr<ms::Surface> const& surface, | ||
3511 | 266 | Point& requested_pos, | ||
3512 | 267 | Size& requested_size, | ||
3513 | 268 | bool const left_resize, | ||
3514 | 269 | bool const top_resize, | ||
3515 | 270 | Rectangle const& /*bounds*/) const | ||
3516 | 271 | { | ||
3517 | 272 | Point new_pos = requested_pos; | ||
3518 | 273 | Size new_size = requested_size; | ||
3519 | 274 | |||
3520 | 275 | if (min_aspect.is_set()) | ||
3521 | 276 | { | ||
3522 | 277 | auto const ar = min_aspect.value(); | ||
3523 | 278 | |||
3524 | 279 | auto const error = new_size.height.as_int()*long(ar.width) - new_size.width.as_int()*long(ar.height); | ||
3525 | 280 | |||
3526 | 281 | if (error > 0) | ||
3527 | 282 | { | ||
3528 | 283 | // Add (denominator-1) to numerator to ensure rounding up | ||
3529 | 284 | auto const width_correction = (error+(ar.height-1))/ar.height; | ||
3530 | 285 | auto const height_correction = (error+(ar.width-1))/ar.width; | ||
3531 | 286 | |||
3532 | 287 | if (width_correction < height_correction) | ||
3533 | 288 | { | ||
3534 | 289 | new_size.width = new_size.width + DeltaX(width_correction); | ||
3535 | 290 | } | ||
3536 | 291 | else | ||
3537 | 292 | { | ||
3538 | 293 | new_size.height = new_size.height - DeltaY(height_correction); | ||
3539 | 294 | } | ||
3540 | 295 | } | ||
3541 | 296 | } | ||
3542 | 297 | |||
3543 | 298 | if (max_aspect.is_set()) | ||
3544 | 299 | { | ||
3545 | 300 | auto const ar = max_aspect.value(); | ||
3546 | 301 | |||
3547 | 302 | auto const error = new_size.width.as_int()*long(ar.height) - new_size.height.as_int()*long(ar.width); | ||
3548 | 303 | |||
3549 | 304 | if (error > 0) | ||
3550 | 305 | { | ||
3551 | 306 | // Add (denominator-1) to numerator to ensure rounding up | ||
3552 | 307 | auto const height_correction = (error+(ar.width-1))/ar.width; | ||
3553 | 308 | auto const width_correction = (error+(ar.height-1))/ar.height; | ||
3554 | 309 | |||
3555 | 310 | if (width_correction < height_correction) | ||
3556 | 311 | { | ||
3557 | 312 | new_size.width = new_size.width - DeltaX(width_correction); | ||
3558 | 313 | } | ||
3559 | 314 | else | ||
3560 | 315 | { | ||
3561 | 316 | new_size.height = new_size.height + DeltaY(height_correction); | ||
3562 | 317 | } | ||
3563 | 318 | } | ||
3564 | 319 | } | ||
3565 | 320 | |||
3566 | 321 | if (min_width > new_size.width) | ||
3567 | 322 | new_size.width = min_width; | ||
3568 | 323 | |||
3569 | 324 | if (min_height > new_size.height) | ||
3570 | 325 | new_size.height = min_height; | ||
3571 | 326 | |||
3572 | 327 | if (max_width < new_size.width) | ||
3573 | 328 | new_size.width = max_width; | ||
3574 | 329 | |||
3575 | 330 | if (max_height < new_size.height) | ||
3576 | 331 | new_size.height = max_height; | ||
3577 | 332 | |||
3578 | 333 | if (width_inc.is_set()) | ||
3579 | 334 | { | ||
3580 | 335 | auto const width = new_size.width.as_int() - min_width.as_int(); | ||
3581 | 336 | auto inc = width_inc.value().as_int(); | ||
3582 | 337 | if (width % inc) | ||
3583 | 338 | new_size.width = min_width + DeltaX{inc*(((2L*width + inc)/2)/inc)}; | ||
3584 | 339 | } | ||
3585 | 340 | |||
3586 | 341 | if (height_inc.is_set()) | ||
3587 | 342 | { | ||
3588 | 343 | auto const height = new_size.height.as_int() - min_height.as_int(); | ||
3589 | 344 | auto inc = height_inc.value().as_int(); | ||
3590 | 345 | if (height % inc) | ||
3591 | 346 | new_size.height = min_height + DeltaY{inc*(((2L*height + inc)/2)/inc)}; | ||
3592 | 347 | } | ||
3593 | 348 | |||
3594 | 349 | if (left_resize) | ||
3595 | 350 | new_pos.x += new_size.width - requested_size.width; | ||
3596 | 351 | |||
3597 | 352 | if (top_resize) | ||
3598 | 353 | new_pos.y += new_size.height - requested_size.height; | ||
3599 | 354 | |||
3600 | 355 | // placeholder - constrain onscreen | ||
3601 | 356 | |||
3602 | 357 | switch (state) | ||
3603 | 358 | { | ||
3604 | 359 | case mir_surface_state_restored: | ||
3605 | 360 | break; | ||
3606 | 361 | |||
3607 | 362 | // "A vertically maximised surface is anchored to the top and bottom of | ||
3608 | 363 | // the available workspace and can have any width." | ||
3609 | 364 | case mir_surface_state_vertmaximized: | ||
3610 | 365 | new_pos.y = surface->top_left().y; | ||
3611 | 366 | new_size.height = surface->size().height; | ||
3612 | 367 | break; | ||
3613 | 368 | |||
3614 | 369 | // "A horizontally maximised surface is anchored to the left and right of | ||
3615 | 370 | // the available workspace and can have any height" | ||
3616 | 371 | case mir_surface_state_horizmaximized: | ||
3617 | 372 | new_pos.x = surface->top_left().x; | ||
3618 | 373 | new_size.width = surface->size().width; | ||
3619 | 374 | break; | ||
3620 | 375 | |||
3621 | 376 | // "A maximised surface is anchored to the top, bottom, left and right of the | ||
3622 | 377 | // available workspace. For example, if the launcher is always-visible then | ||
3623 | 378 | // the left-edge of the surface is anchored to the right-edge of the launcher." | ||
3624 | 379 | case mir_surface_state_maximized: | ||
3625 | 380 | default: | ||
3626 | 381 | new_pos.x = surface->top_left().x; | ||
3627 | 382 | new_pos.y = surface->top_left().y; | ||
3628 | 383 | new_size.width = surface->size().width; | ||
3629 | 384 | new_size.height = surface->size().height; | ||
3630 | 385 | break; | ||
3631 | 386 | } | ||
3632 | 387 | |||
3633 | 388 | requested_pos = new_pos; | ||
3634 | 389 | requested_size = new_size; | ||
3635 | 390 | } | ||
3636 | 391 | |||
3637 | 392 | bool me::SurfaceInfo::needs_titlebar(MirSurfaceType type) | ||
3638 | 393 | { | ||
3639 | 394 | switch (type) | ||
3640 | 395 | { | ||
3641 | 396 | case mir_surface_type_freestyle: | ||
3642 | 397 | case mir_surface_type_menu: | ||
3643 | 398 | case mir_surface_type_inputmethod: | ||
3644 | 399 | case mir_surface_type_gloss: | ||
3645 | 400 | case mir_surface_type_tip: | ||
3646 | 401 | // No decorations for these surface types | ||
3647 | 402 | return false; | ||
3648 | 403 | default: | ||
3649 | 404 | return true; | ||
3650 | 405 | } | ||
3651 | 406 | } | ||
3652 | 0 | 407 | ||
3653 | === added file 'src/platforms/mirserver/wm-wip/server_example_window_management_info.h' | |||
3654 | --- src/platforms/mirserver/wm-wip/server_example_window_management_info.h 1970-01-01 00:00:00 +0000 | |||
3655 | +++ src/platforms/mirserver/wm-wip/server_example_window_management_info.h 2016-03-11 11:36:44 +0000 | |||
3656 | @@ -0,0 +1,103 @@ | |||
3657 | 1 | /* | ||
3658 | 2 | * Copyright © 2015 Canonical Ltd. | ||
3659 | 3 | * | ||
3660 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
3661 | 5 | * under the terms of the GNU General Public License version 3, | ||
3662 | 6 | * as published by the Free Software Foundation. | ||
3663 | 7 | * | ||
3664 | 8 | * This program is distributed in the hope that it will be useful, | ||
3665 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
3666 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
3667 | 11 | * GNU General Public License for more details. | ||
3668 | 12 | * | ||
3669 | 13 | * You should have received a copy of the GNU General Public License | ||
3670 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3671 | 15 | * | ||
3672 | 16 | * Authored by: Alan Griffiths <alan@octopull.co.uk> | ||
3673 | 17 | */ | ||
3674 | 18 | |||
3675 | 19 | #ifndef MIR_SERVER_EXAMPLE_WINDOW_MANAGEMENT_INFO_H | ||
3676 | 20 | #define MIR_SERVER_EXAMPLE_WINDOW_MANAGEMENT_INFO_H | ||
3677 | 21 | |||
3678 | 22 | #include "mir/geometry/rectangles.h" | ||
3679 | 23 | #include "mir/optional_value.h" | ||
3680 | 24 | #include "mir/shell/surface_specification.h" | ||
3681 | 25 | |||
3682 | 26 | #include <vector> | ||
3683 | 27 | |||
3684 | 28 | namespace mir | ||
3685 | 29 | { | ||
3686 | 30 | namespace scene { class Session; class Surface; class SurfaceCreationParameters; } | ||
3687 | 31 | namespace examples | ||
3688 | 32 | { | ||
3689 | 33 | struct SurfaceInfo | ||
3690 | 34 | { | ||
3691 | 35 | SurfaceInfo( | ||
3692 | 36 | std::shared_ptr <scene::Session> const& session, | ||
3693 | 37 | std::shared_ptr <scene::Surface> const& surface, | ||
3694 | 38 | scene::SurfaceCreationParameters const& params); | ||
3695 | 39 | |||
3696 | 40 | bool can_be_active() const; | ||
3697 | 41 | |||
3698 | 42 | bool can_morph_to(MirSurfaceType new_type) const; | ||
3699 | 43 | |||
3700 | 44 | bool must_have_parent() const; | ||
3701 | 45 | |||
3702 | 46 | bool must_not_have_parent() const; | ||
3703 | 47 | |||
3704 | 48 | bool is_visible() const; | ||
3705 | 49 | |||
3706 | 50 | static bool needs_titlebar(MirSurfaceType type); | ||
3707 | 51 | |||
3708 | 52 | void constrain_resize( | ||
3709 | 53 | std::shared_ptr <scene::Surface> const& surface, | ||
3710 | 54 | geometry::Point& requested_pos, | ||
3711 | 55 | geometry::Size& requested_size, | ||
3712 | 56 | const bool left_resize, | ||
3713 | 57 | const bool top_resize, | ||
3714 | 58 | geometry::Rectangle const& bounds) const; | ||
3715 | 59 | |||
3716 | 60 | MirSurfaceType type; | ||
3717 | 61 | MirSurfaceState state; | ||
3718 | 62 | geometry::Rectangle restore_rect; | ||
3719 | 63 | std::weak_ptr <scene::Session> session; | ||
3720 | 64 | std::weak_ptr <scene::Surface> parent; | ||
3721 | 65 | std::vector <std::weak_ptr<scene::Surface>> children; | ||
3722 | 66 | std::shared_ptr <scene::Surface> titlebar; | ||
3723 | 67 | frontend::SurfaceId titlebar_id; | ||
3724 | 68 | bool is_titlebar = false; | ||
3725 | 69 | geometry::Width min_width; | ||
3726 | 70 | geometry::Height min_height; | ||
3727 | 71 | geometry::Width max_width; | ||
3728 | 72 | geometry::Height max_height; | ||
3729 | 73 | mir::optional_value<geometry::DeltaX> width_inc; | ||
3730 | 74 | mir::optional_value<geometry::DeltaY> height_inc; | ||
3731 | 75 | mir::optional_value<shell::SurfaceAspectRatio> min_aspect; | ||
3732 | 76 | mir::optional_value<shell::SurfaceAspectRatio> max_aspect; | ||
3733 | 77 | mir::optional_value<graphics::DisplayConfigurationOutputId> output_id; | ||
3734 | 78 | |||
3735 | 79 | void init_titlebar(std::shared_ptr <scene::Surface> const& surface); | ||
3736 | 80 | |||
3737 | 81 | void paint_titlebar(int intensity); | ||
3738 | 82 | |||
3739 | 83 | private: | ||
3740 | 84 | |||
3741 | 85 | struct StreamPainter; | ||
3742 | 86 | struct AllocatingPainter; | ||
3743 | 87 | struct SwappingPainter; | ||
3744 | 88 | |||
3745 | 89 | std::shared_ptr <StreamPainter> stream_painter; | ||
3746 | 90 | }; | ||
3747 | 91 | |||
3748 | 92 | struct SessionInfo | ||
3749 | 93 | { | ||
3750 | 94 | std::vector<std::weak_ptr<scene::Surface>> surfaces; | ||
3751 | 95 | |||
3752 | 96 | // This is only used by the TilingWindowManagerPolicy, | ||
3753 | 97 | // perhaps we need a more extensible mechanism. (std::experimental::any?) | ||
3754 | 98 | geometry::Rectangle tile; | ||
3755 | 99 | }; | ||
3756 | 100 | } | ||
3757 | 101 | } | ||
3758 | 102 | |||
3759 | 103 | #endif //MIR_SERVER_EXAMPLE_WINDOW_MANAGEMENT_INFO_H | ||
3760 | 0 | 104 | ||
3761 | === modified file 'tests/framework/mock_proc_info.cpp' | |||
3762 | --- tests/framework/mock_proc_info.cpp 2015-11-20 16:47:09 +0000 | |||
3763 | +++ tests/framework/mock_proc_info.cpp 2016-03-11 11:36:44 +0000 | |||
3764 | @@ -21,6 +21,8 @@ | |||
3765 | 21 | 21 | ||
3766 | 22 | MockProcInfo::MockProcInfo() | 22 | MockProcInfo::MockProcInfo() |
3767 | 23 | { | 23 | { |
3768 | 24 | using namespace ::testing; | ||
3769 | 25 | ON_CALL(*this, command_line(_)).WillByDefault(Return(QByteArray())); | ||
3770 | 24 | } | 26 | } |
3771 | 25 | 27 | ||
3772 | 26 | MockProcInfo::~MockProcInfo() | 28 | MockProcInfo::~MockProcInfo() |
3773 | 27 | 29 | ||
3774 | === modified file 'tests/framework/mock_session.cpp' | |||
3775 | --- tests/framework/mock_session.cpp 2015-10-19 10:45:42 +0000 | |||
3776 | +++ tests/framework/mock_session.cpp 2016-03-11 11:36:44 +0000 | |||
3777 | @@ -23,6 +23,7 @@ | |||
3778 | 23 | : SessionInterface(0) | 23 | : SessionInterface(0) |
3779 | 24 | { | 24 | { |
3780 | 25 | m_state = Starting; | 25 | m_state = Starting; |
3781 | 26 | ON_CALL(*this, name()).WillByDefault(::testing::Return(QString())); | ||
3782 | 26 | ON_CALL(*this, suspend()).WillByDefault(::testing::Invoke(this, &MockSession::doSuspend)); | 27 | ON_CALL(*this, suspend()).WillByDefault(::testing::Invoke(this, &MockSession::doSuspend)); |
3783 | 27 | ON_CALL(*this, resume()).WillByDefault(::testing::Invoke(this, &MockSession::doResume)); | 28 | ON_CALL(*this, resume()).WillByDefault(::testing::Invoke(this, &MockSession::doResume)); |
3784 | 28 | ON_CALL(*this, stop()).WillByDefault(::testing::Invoke(this, &MockSession::doStop)); | 29 | ON_CALL(*this, stop()).WillByDefault(::testing::Invoke(this, &MockSession::doStop)); |
3785 | 29 | 30 | ||
3786 | === modified file 'tests/framework/mock_task_controller.cpp' | |||
3787 | --- tests/framework/mock_task_controller.cpp 2016-02-11 11:52:06 +0000 | |||
3788 | +++ tests/framework/mock_task_controller.cpp 2016-03-11 11:36:44 +0000 | |||
3789 | @@ -68,11 +68,11 @@ | |||
3790 | 68 | 68 | ||
3791 | 69 | bool MockTaskController::doAppIdHasProcessId(const QString &appId, pid_t pid) | 69 | bool MockTaskController::doAppIdHasProcessId(const QString &appId, pid_t pid) |
3792 | 70 | { | 70 | { |
3796 | 71 | auto it = children.find(appId); | 71 | auto primaryPid = primaryPidForAppId(appId); |
3797 | 72 | if (it == children.end()) | 72 | if (primaryPid == -1) |
3798 | 73 | return -1; | 73 | return false; |
3799 | 74 | 74 | ||
3801 | 75 | return it->pid() == pid; | 75 | return primaryPid == pid; |
3802 | 76 | } | 76 | } |
3803 | 77 | 77 | ||
3804 | 78 | 78 | ||
3805 | 79 | 79 | ||
3806 | === modified file 'tests/framework/qtmir_test.cpp' | |||
3807 | --- tests/framework/qtmir_test.cpp 2016-02-11 11:52:06 +0000 | |||
3808 | +++ tests/framework/qtmir_test.cpp 2016-03-11 11:36:44 +0000 | |||
3809 | @@ -99,13 +99,13 @@ | |||
3810 | 99 | }; | 99 | }; |
3811 | 100 | 100 | ||
3812 | 101 | 101 | ||
3814 | 102 | namespace { char const* argv[] = { nullptr }; } | 102 | namespace { int argc = 0; char* argv[] = { nullptr }; } |
3815 | 103 | 103 | ||
3816 | 104 | class FakeMirServer: private TestMirServerInit, public MirServer | 104 | class FakeMirServer: private TestMirServerInit, public MirServer |
3817 | 105 | { | 105 | { |
3818 | 106 | public: | 106 | public: |
3819 | 107 | FakeMirServer(std::shared_ptr<StubPromptSessionManager> const& promptSessionManager) | 107 | FakeMirServer(std::shared_ptr<StubPromptSessionManager> const& promptSessionManager) |
3821 | 108 | : TestMirServerInit(promptSessionManager), MirServer(0, argv, QSharedPointer<ScreenController>()) | 108 | : TestMirServerInit(promptSessionManager), MirServer(argc, argv, QSharedPointer<ScreenController>()) |
3822 | 109 | { | 109 | { |
3823 | 110 | } | 110 | } |
3824 | 111 | 111 | ||
3825 | 112 | 112 | ||
3826 | === added directory 'tests/mirserver/ArgvHelper' | |||
3827 | === added file 'tests/mirserver/ArgvHelper/CMakeLists.txt' | |||
3828 | --- tests/mirserver/ArgvHelper/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
3829 | +++ tests/mirserver/ArgvHelper/CMakeLists.txt 2016-03-11 11:36:44 +0000 | |||
3830 | @@ -0,0 +1,18 @@ | |||
3831 | 1 | set( | ||
3832 | 2 | ARGVHELPER_TEST_SOURCES | ||
3833 | 3 | argvHelper_test.cpp | ||
3834 | 4 | ) | ||
3835 | 5 | |||
3836 | 6 | add_executable(ArgvHelperTest ${ARGVHELPER_TEST_SOURCES}) | ||
3837 | 7 | |||
3838 | 8 | include_directories( | ||
3839 | 9 | ${CMAKE_SOURCE_DIR}/src/platforms/mirserver | ||
3840 | 10 | ) | ||
3841 | 11 | |||
3842 | 12 | target_link_libraries( | ||
3843 | 13 | ArgvHelperTest | ||
3844 | 14 | |||
3845 | 15 | ${GTEST_BOTH_LIBRARIES} | ||
3846 | 16 | ) | ||
3847 | 17 | |||
3848 | 18 | add_test(ArgvHelper, ArgvHelperTest) | ||
3849 | 0 | 19 | ||
3850 | === added file 'tests/mirserver/ArgvHelper/argvHelper_test.cpp' | |||
3851 | --- tests/mirserver/ArgvHelper/argvHelper_test.cpp 1970-01-01 00:00:00 +0000 | |||
3852 | +++ tests/mirserver/ArgvHelper/argvHelper_test.cpp 2016-03-11 11:36:44 +0000 | |||
3853 | @@ -0,0 +1,72 @@ | |||
3854 | 1 | /* | ||
3855 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
3856 | 3 | * | ||
3857 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
3858 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
3859 | 6 | * the Free Software Foundation. | ||
3860 | 7 | * | ||
3861 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
3862 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
3863 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
3864 | 11 | * Lesser General Public License for more details. | ||
3865 | 12 | * | ||
3866 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
3867 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3868 | 15 | */ | ||
3869 | 16 | |||
3870 | 17 | #include <gtest/gtest.h> | ||
3871 | 18 | |||
3872 | 19 | #include <argvHelper.h> | ||
3873 | 20 | |||
3874 | 21 | using namespace qtmir; | ||
3875 | 22 | |||
3876 | 23 | TEST(ArgvHelperTest, StripsCorrectly) | ||
3877 | 24 | { | ||
3878 | 25 | int argc = 5; | ||
3879 | 26 | const char *argv[6] = { "/usr/bin/unity8", "-fullscreen", "--debug", | ||
3880 | 27 | "--platform-input-lib=/path/to/lib.so", "-testability", nullptr }; | ||
3881 | 28 | |||
3882 | 29 | const int filteredArgc = 2; | ||
3883 | 30 | const char *filteredArgv[3] = { "-fullscreen", "-testability", nullptr }; | ||
3884 | 31 | |||
3885 | 32 | editArgvToMatch(argc, const_cast<char**>(argv), filteredArgc, filteredArgv); | ||
3886 | 33 | |||
3887 | 34 | EXPECT_EQ(argc, 3); | ||
3888 | 35 | EXPECT_EQ(argv[0], "/usr/bin/unity8"); | ||
3889 | 36 | EXPECT_EQ(argv[1], "-fullscreen"); | ||
3890 | 37 | EXPECT_EQ(argv[2], "-testability"); | ||
3891 | 38 | EXPECT_EQ(argv[3], nullptr); | ||
3892 | 39 | } | ||
3893 | 40 | |||
3894 | 41 | TEST(ArgvHelperTest, NothingToStrip) | ||
3895 | 42 | { | ||
3896 | 43 | int argc = 4; | ||
3897 | 44 | const char *argv[5] = { "/usr/bin/unity8", "-fullscreen", "--multisample", "-testability", nullptr }; | ||
3898 | 45 | |||
3899 | 46 | const int filteredArgc = 3; | ||
3900 | 47 | const char *filteredArgv[4] = { "-fullscreen", "-testability", "--multisample", nullptr }; | ||
3901 | 48 | |||
3902 | 49 | editArgvToMatch(argc, const_cast<char**>(argv), filteredArgc, filteredArgv); | ||
3903 | 50 | |||
3904 | 51 | EXPECT_EQ(argc, 4); | ||
3905 | 52 | EXPECT_EQ(argv[0], "/usr/bin/unity8"); | ||
3906 | 53 | EXPECT_EQ(argv[1], "-fullscreen"); | ||
3907 | 54 | EXPECT_EQ(argv[2], "-testability"); | ||
3908 | 55 | EXPECT_EQ(argv[3], "--multisample"); | ||
3909 | 56 | EXPECT_EQ(argv[4], nullptr); | ||
3910 | 57 | } | ||
3911 | 58 | |||
3912 | 59 | TEST(ArgvHelperTest, NothingToDo) | ||
3913 | 60 | { | ||
3914 | 61 | int argc = 1; | ||
3915 | 62 | const char *argv[2] = { "/usr/bin/unity8", nullptr }; | ||
3916 | 63 | |||
3917 | 64 | const int filteredArgc = 0; | ||
3918 | 65 | const char *filteredArgv[1] = { nullptr }; | ||
3919 | 66 | |||
3920 | 67 | editArgvToMatch(argc, const_cast<char**>(argv), filteredArgc, filteredArgv); | ||
3921 | 68 | |||
3922 | 69 | EXPECT_EQ(argc, 1); | ||
3923 | 70 | EXPECT_EQ(argv[0], "/usr/bin/unity8"); | ||
3924 | 71 | EXPECT_EQ(argv[1], nullptr); | ||
3925 | 72 | } | ||
3926 | 0 | 73 | ||
3927 | === modified file 'tests/mirserver/CMakeLists.txt' | |||
3928 | --- tests/mirserver/CMakeLists.txt 2015-10-27 10:17:45 +0000 | |||
3929 | +++ tests/mirserver/CMakeLists.txt 2016-03-11 11:36:44 +0000 | |||
3930 | @@ -1,3 +1,4 @@ | |||
3931 | 1 | add_subdirectory(ArgvHelper) | ||
3932 | 1 | add_subdirectory(QtEventFeeder) | 2 | add_subdirectory(QtEventFeeder) |
3933 | 2 | add_subdirectory(Clipboard) | 3 | add_subdirectory(Clipboard) |
3934 | 3 | add_subdirectory(Screen) | 4 | add_subdirectory(Screen) |
3935 | 4 | 5 | ||
3936 | === modified file 'tests/mirserver/Screen/screen_test.cpp' | |||
3937 | --- tests/mirserver/Screen/screen_test.cpp 2015-10-14 22:59:04 +0000 | |||
3938 | +++ tests/mirserver/Screen/screen_test.cpp 2016-03-11 11:36:44 +0000 | |||
3939 | @@ -42,9 +42,23 @@ | |||
3940 | 42 | Screen::skipDBusRegistration = true; | 42 | Screen::skipDBusRegistration = true; |
3941 | 43 | } | 43 | } |
3942 | 44 | 44 | ||
3946 | 45 | TEST_F(ScreenTest, OrientationSensor) | 45 | TEST_F(ScreenTest, OrientationSensorForExternalDisplay) |
3947 | 46 | { | 46 | { |
3948 | 47 | Screen *screen = new Screen(fakeOutput1); | 47 | Screen *screen = new Screen(fakeOutput1); // is external display (dvi) |
3949 | 48 | |||
3950 | 49 | // Default state should be disabled | ||
3951 | 50 | ASSERT_FALSE(screen->orientationSensorEnabled()); | ||
3952 | 51 | |||
3953 | 52 | screen->onDisplayPowerStateChanged(0,0); | ||
3954 | 53 | ASSERT_FALSE(screen->orientationSensorEnabled()); | ||
3955 | 54 | |||
3956 | 55 | screen->onDisplayPowerStateChanged(1,0); | ||
3957 | 56 | ASSERT_FALSE(screen->orientationSensorEnabled()); | ||
3958 | 57 | } | ||
3959 | 58 | |||
3960 | 59 | TEST_F(ScreenTest, OrientationSensorForInternalDisplay) | ||
3961 | 60 | { | ||
3962 | 61 | Screen *screen = new Screen(fakeOutput2); // is internal display | ||
3963 | 48 | 62 | ||
3964 | 49 | // Default state should be active | 63 | // Default state should be active |
3965 | 50 | ASSERT_TRUE(screen->orientationSensorEnabled()); | 64 | ASSERT_TRUE(screen->orientationSensorEnabled()); |
3966 | 51 | 65 | ||
3967 | === modified file 'tests/modules/ApplicationManager/application_manager_test.cpp' | |||
3968 | --- tests/modules/ApplicationManager/application_manager_test.cpp 2016-02-12 00:07:09 +0000 | |||
3969 | +++ tests/modules/ApplicationManager/application_manager_test.cpp 2016-03-11 11:36:44 +0000 | |||
3970 | @@ -71,6 +71,13 @@ | |||
3971 | 71 | ASSERT_EQ(Application::InternalState::Suspended, application->internalState()); | 71 | ASSERT_EQ(Application::InternalState::Suspended, application->internalState()); |
3972 | 72 | } | 72 | } |
3973 | 73 | 73 | ||
3974 | 74 | static inline qtmir::DesktopFileReader* createMockDesktopFileReader(const QString &appId, const QFileInfo &fi) { | ||
3975 | 75 | using namespace ::testing; | ||
3976 | 76 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, fi); | ||
3977 | 77 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | ||
3978 | 78 | return mockDesktopFileReader; | ||
3979 | 79 | } | ||
3980 | 80 | |||
3981 | 74 | protected: | 81 | protected: |
3982 | 75 | virtual void SetUp() override { | 82 | virtual void SetUp() override { |
3983 | 76 | if (m_tempDir.isValid()) qputenv("XDG_CACHE_HOME", m_tempDir.path().toUtf8()); | 83 | if (m_tempDir.isValid()) qputenv("XDG_CACHE_HOME", m_tempDir.path().toUtf8()); |
3984 | @@ -751,11 +758,7 @@ | |||
3985 | 751 | const QString appId("testAppId"); | 758 | const QString appId("testAppId"); |
3986 | 752 | 759 | ||
3987 | 753 | // Set up Mocks & signal watcher | 760 | // Set up Mocks & signal watcher |
3993 | 754 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 761 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
3989 | 755 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | ||
3990 | 756 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
3991 | 757 | |||
3992 | 758 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
3994 | 759 | 762 | ||
3995 | 760 | EXPECT_CALL(*taskController, start(appId, _)) | 763 | EXPECT_CALL(*taskController, start(appId, _)) |
3996 | 761 | .Times(1) | 764 | .Times(1) |
3997 | @@ -789,11 +792,8 @@ | |||
3998 | 789 | const pid_t procId = 5551; | 792 | const pid_t procId = 5551; |
3999 | 790 | 793 | ||
4000 | 791 | // Set up Mocks & signal watcher | 794 | // Set up Mocks & signal watcher |
4006 | 792 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 795 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4007 | 793 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 796 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4003 | 794 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4004 | 795 | |||
4005 | 796 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4008 | 797 | 797 | ||
4009 | 798 | EXPECT_CALL(*taskController, start(appId, _)) | 798 | EXPECT_CALL(*taskController, start(appId, _)) |
4010 | 799 | .Times(1) | 799 | .Times(1) |
4011 | @@ -833,11 +833,8 @@ | |||
4012 | 833 | const pid_t procId = 5551; | 833 | const pid_t procId = 5551; |
4013 | 834 | 834 | ||
4014 | 835 | // Set up Mocks & signal watcher | 835 | // Set up Mocks & signal watcher |
4020 | 836 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 836 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4021 | 837 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 837 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4017 | 838 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4018 | 839 | |||
4019 | 840 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4022 | 841 | 838 | ||
4023 | 842 | EXPECT_CALL(*taskController, start(appId, _)) | 839 | EXPECT_CALL(*taskController, start(appId, _)) |
4024 | 843 | .Times(1) | 840 | .Times(1) |
4025 | @@ -869,16 +866,11 @@ | |||
4026 | 869 | { | 866 | { |
4027 | 870 | using namespace ::testing; | 867 | using namespace ::testing; |
4028 | 871 | const QString appId("testAppId"); | 868 | const QString appId("testAppId"); |
4029 | 872 | const QString desktopFilePath("testAppId.desktop"); | ||
4030 | 873 | const pid_t procId = 5551; | 869 | const pid_t procId = 5551; |
4031 | 874 | 870 | ||
4032 | 875 | // Set up Mocks & signal watcher | 871 | // Set up Mocks & signal watcher |
4039 | 876 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 872 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4040 | 877 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 873 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4035 | 878 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4036 | 879 | ON_CALL(*mockDesktopFileReader, file()).WillByDefault(Return(desktopFilePath)); | ||
4037 | 880 | |||
4038 | 881 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4041 | 882 | 874 | ||
4042 | 883 | EXPECT_CALL(*taskController, start(appId, _)) | 875 | EXPECT_CALL(*taskController, start(appId, _)) |
4043 | 884 | .Times(1) | 876 | .Times(1) |
4044 | @@ -917,11 +909,8 @@ | |||
4045 | 917 | const pid_t procId = 5551; | 909 | const pid_t procId = 5551; |
4046 | 918 | 910 | ||
4047 | 919 | // Set up Mocks & signal watcher | 911 | // Set up Mocks & signal watcher |
4053 | 920 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 912 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4054 | 921 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 913 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4050 | 922 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4051 | 923 | |||
4052 | 924 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4055 | 925 | 914 | ||
4056 | 926 | EXPECT_CALL(*taskController, start(appId, _)) | 915 | EXPECT_CALL(*taskController, start(appId, _)) |
4057 | 927 | .Times(1) | 916 | .Times(1) |
4058 | @@ -960,11 +949,8 @@ | |||
4059 | 960 | const pid_t procId = 5551; | 949 | const pid_t procId = 5551; |
4060 | 961 | 950 | ||
4061 | 962 | // Set up Mocks & signal watcher | 951 | // Set up Mocks & signal watcher |
4067 | 963 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 952 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4068 | 964 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 953 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4064 | 965 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4065 | 966 | |||
4066 | 967 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4069 | 968 | 954 | ||
4070 | 969 | EXPECT_CALL(*taskController, start(appId, _)) | 955 | EXPECT_CALL(*taskController, start(appId, _)) |
4071 | 970 | .Times(1) | 956 | .Times(1) |
4072 | @@ -1006,11 +992,8 @@ | |||
4073 | 1006 | const pid_t procId = 5551; | 992 | const pid_t procId = 5551; |
4074 | 1007 | 993 | ||
4075 | 1008 | // Set up Mocks & signal watcher | 994 | // Set up Mocks & signal watcher |
4081 | 1009 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 995 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4082 | 1010 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 996 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4078 | 1011 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4079 | 1012 | |||
4080 | 1013 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4083 | 1014 | 997 | ||
4084 | 1015 | EXPECT_CALL(*taskController, start(appId, _)) | 998 | EXPECT_CALL(*taskController, start(appId, _)) |
4085 | 1016 | .Times(1) | 999 | .Times(1) |
4086 | @@ -1051,11 +1034,8 @@ | |||
4087 | 1051 | const pid_t procId = 5551; | 1034 | const pid_t procId = 5551; |
4088 | 1052 | 1035 | ||
4089 | 1053 | // Set up Mocks & signal watcher | 1036 | // Set up Mocks & signal watcher |
4095 | 1054 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1037 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4096 | 1055 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 1038 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4092 | 1056 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4093 | 1057 | |||
4094 | 1058 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4097 | 1059 | 1039 | ||
4098 | 1060 | EXPECT_CALL(*taskController, start(appId, _)) | 1040 | EXPECT_CALL(*taskController, start(appId, _)) |
4099 | 1061 | .Times(1) | 1041 | .Times(1) |
4100 | @@ -1102,11 +1082,8 @@ | |||
4101 | 1102 | const pid_t procId = 5551; | 1082 | const pid_t procId = 5551; |
4102 | 1103 | 1083 | ||
4103 | 1104 | // Set up Mocks & signal watcher | 1084 | // Set up Mocks & signal watcher |
4109 | 1105 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1085 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4110 | 1106 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 1086 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4106 | 1107 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4107 | 1108 | |||
4108 | 1109 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4111 | 1110 | 1087 | ||
4112 | 1111 | EXPECT_CALL(*taskController, start(appId, _)) | 1088 | EXPECT_CALL(*taskController, start(appId, _)) |
4113 | 1112 | .Times(1) | 1089 | .Times(1) |
4114 | @@ -1160,11 +1137,8 @@ | |||
4115 | 1160 | const pid_t procId = 5551; | 1137 | const pid_t procId = 5551; |
4116 | 1161 | 1138 | ||
4117 | 1162 | // Set up Mocks & signal watcher | 1139 | // Set up Mocks & signal watcher |
4123 | 1163 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1140 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4124 | 1164 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 1141 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4120 | 1165 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4121 | 1166 | |||
4122 | 1167 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4125 | 1168 | 1142 | ||
4126 | 1169 | EXPECT_CALL(*taskController, start(appId, _)) | 1143 | EXPECT_CALL(*taskController, start(appId, _)) |
4127 | 1170 | .Times(1) | 1144 | .Times(1) |
4128 | @@ -1213,11 +1187,8 @@ | |||
4129 | 1213 | const pid_t procId = 5551; | 1187 | const pid_t procId = 5551; |
4130 | 1214 | 1188 | ||
4131 | 1215 | // Set up Mocks & signal watcher | 1189 | // Set up Mocks & signal watcher |
4137 | 1216 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1190 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4138 | 1217 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 1191 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4134 | 1218 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4135 | 1219 | |||
4136 | 1220 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4139 | 1221 | 1192 | ||
4140 | 1222 | EXPECT_CALL(*taskController, start(appId, _)) | 1193 | EXPECT_CALL(*taskController, start(appId, _)) |
4141 | 1223 | .Times(1) | 1194 | .Times(1) |
4142 | @@ -1252,11 +1223,8 @@ | |||
4143 | 1252 | const pid_t procId = 5551; | 1223 | const pid_t procId = 5551; |
4144 | 1253 | 1224 | ||
4145 | 1254 | // Set up Mocks & signal watcher | 1225 | // Set up Mocks & signal watcher |
4151 | 1255 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1226 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4152 | 1256 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 1227 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4148 | 1257 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4149 | 1258 | |||
4150 | 1259 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4153 | 1260 | 1228 | ||
4154 | 1261 | EXPECT_CALL(*taskController, start(appId, _)) | 1229 | EXPECT_CALL(*taskController, start(appId, _)) |
4155 | 1262 | .Times(1) | 1230 | .Times(1) |
4156 | @@ -1348,11 +1316,8 @@ | |||
4157 | 1348 | const pid_t procId = 5551; | 1316 | const pid_t procId = 5551; |
4158 | 1349 | 1317 | ||
4159 | 1350 | // Set up Mocks & signal watcher | 1318 | // Set up Mocks & signal watcher |
4165 | 1351 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1319 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4166 | 1352 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 1320 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4162 | 1353 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4163 | 1354 | |||
4164 | 1355 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4167 | 1356 | 1321 | ||
4168 | 1357 | EXPECT_CALL(*taskController, start(appId, _)) | 1322 | EXPECT_CALL(*taskController, start(appId, _)) |
4169 | 1358 | .Times(1) | 1323 | .Times(1) |
4170 | @@ -1407,12 +1372,8 @@ | |||
4171 | 1407 | const pid_t procId = 5551; | 1372 | const pid_t procId = 5551; |
4172 | 1408 | 1373 | ||
4173 | 1409 | // Set up Mocks & signal watcher | 1374 | // Set up Mocks & signal watcher |
4180 | 1410 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1375 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4181 | 1411 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 1376 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4176 | 1412 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4177 | 1413 | ON_CALL(*mockDesktopFileReader, file()).WillByDefault(Return(appId + ".desktop")); | ||
4178 | 1414 | |||
4179 | 1415 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4182 | 1416 | 1377 | ||
4183 | 1417 | EXPECT_CALL(*taskController, start(appId, _)) | 1378 | EXPECT_CALL(*taskController, start(appId, _)) |
4184 | 1418 | .Times(1) | 1379 | .Times(1) |
4185 | @@ -1465,11 +1426,7 @@ | |||
4186 | 1465 | ON_CALL(*taskController,appIdHasProcessId(_, procId2)).WillByDefault(Return(false)); | 1426 | ON_CALL(*taskController,appIdHasProcessId(_, procId2)).WillByDefault(Return(false)); |
4187 | 1466 | 1427 | ||
4188 | 1467 | // Set up Mocks & signal watcher | 1428 | // Set up Mocks & signal watcher |
4194 | 1468 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1429 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4190 | 1469 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | ||
4191 | 1470 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4192 | 1471 | |||
4193 | 1472 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4195 | 1473 | 1430 | ||
4196 | 1474 | EXPECT_CALL(*taskController, start(appId, _)) | 1431 | EXPECT_CALL(*taskController, start(appId, _)) |
4197 | 1475 | .Times(1) | 1432 | .Times(1) |
4198 | @@ -1525,11 +1482,7 @@ | |||
4199 | 1525 | ON_CALL(*taskController,appIdHasProcessId(_, procId2)).WillByDefault(Return(false)); | 1482 | ON_CALL(*taskController,appIdHasProcessId(_, procId2)).WillByDefault(Return(false)); |
4200 | 1526 | 1483 | ||
4201 | 1527 | // Set up Mocks & signal watcher | 1484 | // Set up Mocks & signal watcher |
4207 | 1528 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1485 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4203 | 1529 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | ||
4204 | 1530 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4205 | 1531 | |||
4206 | 1532 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4208 | 1533 | 1486 | ||
4209 | 1534 | EXPECT_CALL(*taskController, start(appId, _)) | 1487 | EXPECT_CALL(*taskController, start(appId, _)) |
4210 | 1535 | .Times(1) | 1488 | .Times(1) |
4211 | @@ -1583,11 +1536,8 @@ | |||
4212 | 1583 | const pid_t procId = 5551; | 1536 | const pid_t procId = 5551; |
4213 | 1584 | 1537 | ||
4214 | 1585 | // Set up Mocks & signal watcher | 1538 | // Set up Mocks & signal watcher |
4220 | 1586 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1539 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4221 | 1587 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 1540 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4217 | 1588 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4218 | 1589 | |||
4219 | 1590 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4222 | 1591 | 1541 | ||
4223 | 1592 | EXPECT_CALL(*taskController, start(appId, _)) | 1542 | EXPECT_CALL(*taskController, start(appId, _)) |
4224 | 1593 | .Times(1) | 1543 | .Times(1) |
4225 | @@ -1629,19 +1579,14 @@ | |||
4226 | 1629 | { | 1579 | { |
4227 | 1630 | using namespace testing; | 1580 | using namespace testing; |
4228 | 1631 | const QString appId("webapp"); | 1581 | const QString appId("webapp"); |
4229 | 1632 | const QString desktopFilePath("webapp.desktop"); | ||
4230 | 1633 | const pid_t procId = 5551; | 1582 | const pid_t procId = 5551; |
4231 | 1634 | 1583 | ||
4232 | 1635 | std::mutex mutex; | 1584 | std::mutex mutex; |
4233 | 1636 | std::condition_variable cv; | 1585 | std::condition_variable cv; |
4234 | 1637 | bool done = false; | 1586 | bool done = false; |
4235 | 1638 | 1587 | ||
4242 | 1639 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1588 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4243 | 1640 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 1589 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4238 | 1641 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4239 | 1642 | ON_CALL(*mockDesktopFileReader, file()).WillByDefault(Return(desktopFilePath)); | ||
4240 | 1643 | |||
4241 | 1644 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4244 | 1645 | 1590 | ||
4245 | 1646 | EXPECT_CALL(*taskController, start(appId, _)) | 1591 | EXPECT_CALL(*taskController, start(appId, _)) |
4246 | 1647 | .Times(1) | 1592 | .Times(1) |
4247 | @@ -1753,11 +1698,8 @@ | |||
4248 | 1753 | const quint64 procId = 12345; | 1698 | const quint64 procId = 12345; |
4249 | 1754 | 1699 | ||
4250 | 1755 | // Set up Mocks & signal watcher | 1700 | // Set up Mocks & signal watcher |
4256 | 1756 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1701 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4257 | 1757 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 1702 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4253 | 1758 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4254 | 1759 | |||
4255 | 1760 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4258 | 1761 | 1703 | ||
4259 | 1762 | EXPECT_CALL(*taskController, start(appId, _)) | 1704 | EXPECT_CALL(*taskController, start(appId, _)) |
4260 | 1763 | .Times(1) | 1705 | .Times(1) |
4261 | @@ -1821,11 +1763,8 @@ | |||
4262 | 1821 | const quint64 procId = 12345; | 1763 | const quint64 procId = 12345; |
4263 | 1822 | 1764 | ||
4264 | 1823 | // Set up Mocks & signal watcher | 1765 | // Set up Mocks & signal watcher |
4270 | 1824 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1766 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4271 | 1825 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 1767 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4267 | 1826 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4268 | 1827 | |||
4269 | 1828 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4272 | 1829 | 1768 | ||
4273 | 1830 | EXPECT_CALL(*taskController, start(appId, _)) | 1769 | EXPECT_CALL(*taskController, start(appId, _)) |
4274 | 1831 | .Times(1) | 1770 | .Times(1) |
4275 | @@ -1863,12 +1802,8 @@ | |||
4276 | 1863 | const pid_t procId = 5551; | 1802 | const pid_t procId = 5551; |
4277 | 1864 | 1803 | ||
4278 | 1865 | // Set up Mocks & signal watcher | 1804 | // Set up Mocks & signal watcher |
4285 | 1866 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1805 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4286 | 1867 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 1806 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4281 | 1868 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4282 | 1869 | ON_CALL(*mockDesktopFileReader, file()).WillByDefault(Return(appId + ".desktop")); | ||
4283 | 1870 | |||
4284 | 1871 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4287 | 1872 | 1807 | ||
4288 | 1873 | EXPECT_CALL(*taskController, start(appId, _)) | 1808 | EXPECT_CALL(*taskController, start(appId, _)) |
4289 | 1874 | .Times(1) | 1809 | .Times(1) |
4290 | @@ -1908,11 +1843,8 @@ | |||
4291 | 1908 | const pid_t procId = 5551; | 1843 | const pid_t procId = 5551; |
4292 | 1909 | 1844 | ||
4293 | 1910 | // Set up Mocks & signal watcher | 1845 | // Set up Mocks & signal watcher |
4299 | 1911 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1846 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4300 | 1912 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 1847 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4296 | 1913 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4297 | 1914 | |||
4298 | 1915 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4301 | 1916 | 1848 | ||
4302 | 1917 | EXPECT_CALL(*taskController, start(appId, _)) | 1849 | EXPECT_CALL(*taskController, start(appId, _)) |
4303 | 1918 | .Times(1) | 1850 | .Times(1) |
4304 | @@ -1957,11 +1889,8 @@ | |||
4305 | 1957 | const pid_t procId = 5551; | 1889 | const pid_t procId = 5551; |
4306 | 1958 | 1890 | ||
4307 | 1959 | // Set up Mocks & signal watcher | 1891 | // Set up Mocks & signal watcher |
4313 | 1960 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1892 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4314 | 1961 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 1893 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4310 | 1962 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4311 | 1963 | |||
4312 | 1964 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4315 | 1965 | 1894 | ||
4316 | 1966 | EXPECT_CALL(*taskController, start(appId, _)) | 1895 | EXPECT_CALL(*taskController, start(appId, _)) |
4317 | 1967 | .Times(1) | 1896 | .Times(1) |
4318 | @@ -2032,12 +1961,8 @@ | |||
4319 | 2032 | const QString appId("testAppId"); | 1961 | const QString appId("testAppId"); |
4320 | 2033 | quint64 procId = 5551; | 1962 | quint64 procId = 5551; |
4321 | 2034 | 1963 | ||
4328 | 2035 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 1964 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4329 | 2036 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 1965 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4324 | 2037 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4325 | 2038 | ON_CALL(*mockDesktopFileReader, file()).WillByDefault(Return(appId + ".desktop")); | ||
4326 | 2039 | |||
4327 | 2040 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4330 | 2041 | 1966 | ||
4331 | 2042 | EXPECT_CALL(*taskController, start(appId, _)) | 1967 | EXPECT_CALL(*taskController, start(appId, _)) |
4332 | 2043 | .Times(1) | 1968 | .Times(1) |
4333 | @@ -2085,10 +2010,8 @@ | |||
4334 | 2085 | const QString appId("testAppId"); | 2010 | const QString appId("testAppId"); |
4335 | 2086 | quint64 procId = 5551; | 2011 | quint64 procId = 5551; |
4336 | 2087 | 2012 | ||
4341 | 2088 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)) | 2013 | ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId)); |
4342 | 2089 | .WillByDefault(Invoke( | 2014 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader)); |
4339 | 2090 | [](const QString &appId, const QFileInfo&) { return new FakeDesktopFileReader(appId); } | ||
4340 | 2091 | )); | ||
4343 | 2092 | 2015 | ||
4344 | 2093 | EXPECT_CALL(*taskController, start(appId, _)) | 2016 | EXPECT_CALL(*taskController, start(appId, _)) |
4345 | 2094 | .Times(1) | 2017 | .Times(1) |