Merge lp:~alan-griffiths/mir/msh_SystemCompositorWindowManager into lp:mir
- msh_SystemCompositorWindowManager
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Alan Griffiths |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2666 |
Proposed branch: | lp:~alan-griffiths/mir/msh_SystemCompositorWindowManager |
Merge into: | lp:mir |
Diff against target: |
628 lines (+522/-2) 7 files modified
examples/server_example_window_management.cpp (+10/-1) include/server/mir/shell/system_compositor_window_manager.h (+99/-0) src/server/shell/CMakeLists.txt (+1/-0) src/server/shell/system_compositor_window_manager.cpp (+151/-0) src/server/symbols.map (+55/-1) tests/acceptance-tests/CMakeLists.txt (+1/-0) tests/acceptance-tests/test_system_compositor_window_manager.cpp (+205/-0) |
To merge this branch: | bzr merge lp:~alan-griffiths/mir/msh_SystemCompositorWindowManager |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Alexandros Frantzis (community) | Approve | ||
Review via email: mp+261751@code.launchpad.net |
Commit message
shell, examples: add a basic SystemComposito
Description of the change
shell, examples: add a basic SystemComposito
Ensures we have explicit support for the system-compositor use case. The following mir_demo_server config now offers a minimal "system compositor":
$ cat ~/.config/
file=
arw-file=
vt=1
display-
window-
SystemComposito
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2661
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:2662
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alexandros Frantzis (afrantzis) wrote : | # |
Looks good.
I was a bit torn when I started reviewing this (not sure if it's worth the trouble and extra coupling), but I think this may be useful for simple products based on Mir. I still don't think it's worth doing this if it's just to simplify USC.
95 + /// Called the first time each surface owned by the session posts its first buffer
We have always assumed one surface per system-compositor client, so it's not clear what's the correct behavior if such a client creates and posts to multiple surfaces. I guess the proposed approach of always focusing the "default" surface is OK for now, but perhaps in the future on_session_ready method should be extended to also provide the surface that became ready.
Alan Griffiths (alan-griffiths) wrote : | # |
> We have always assumed one surface per system-compositor client, so it's not
> clear what's the correct behavior if such a client creates and posts to
> multiple surfaces. I guess the proposed approach of always focusing the
> "default" surface is OK for now, but perhaps in the future on_session_ready
> method should be extended to also provide the surface that became ready.
What we actually have (c.f. the nested code and spinner) is one surface for each output for each system-compositor client.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:2665
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'examples/server_example_window_management.cpp' |
2 | --- examples/server_example_window_management.cpp 2015-05-19 21:34:34 +0000 |
3 | +++ examples/server_example_window_management.cpp 2015-06-16 08:37:48 +0000 |
4 | @@ -27,6 +27,7 @@ |
5 | #include "mir/input/composite_event_filter.h" |
6 | #include "mir/options/option.h" |
7 | #include "mir/shell/display_layout.h" |
8 | +#include "mir/shell/system_compositor_window_manager.h" |
9 | |
10 | namespace me = mir::examples; |
11 | namespace mf = mir::frontend; |
12 | @@ -42,11 +43,12 @@ |
13 | namespace |
14 | { |
15 | char const* const wm_option = "window-manager"; |
16 | -char const* const wm_description = "window management strategy [{tiling|fullscreen|canonical}]"; |
17 | +char const* const wm_description = "window management strategy [{tiling|fullscreen|canonical|system-compositor}]"; |
18 | |
19 | char const* const wm_tiling = "tiling"; |
20 | char const* const wm_fullscreen = "fullscreen"; |
21 | char const* const wm_canonical = "canonical"; |
22 | +char const* const wm_system_compositor = "system-compositor"; |
23 | |
24 | struct NullSessionInfo |
25 | { |
26 | @@ -149,6 +151,13 @@ |
27 | { |
28 | return std::make_shared<CanonicalWindowManager>(focus_controller, server.the_shell_display_layout()); |
29 | } |
30 | + else if (selection == wm_system_compositor) |
31 | + { |
32 | + return std::make_shared<msh::SystemCompositorWindowManager>( |
33 | + focus_controller, |
34 | + server.the_shell_display_layout(), |
35 | + server.the_session_coordinator()); |
36 | + } |
37 | |
38 | throw mir::AbnormalExit("Unknown window manager: " + selection); |
39 | }); |
40 | |
41 | === added file 'include/server/mir/shell/system_compositor_window_manager.h' |
42 | --- include/server/mir/shell/system_compositor_window_manager.h 1970-01-01 00:00:00 +0000 |
43 | +++ include/server/mir/shell/system_compositor_window_manager.h 2015-06-16 08:37:48 +0000 |
44 | @@ -0,0 +1,99 @@ |
45 | +/* |
46 | + * Copyright © 2015 Canonical Ltd. |
47 | + * |
48 | + * This program is free software: you can redistribute it and/or modify it |
49 | + * under the terms of the GNU General Public License version 3, |
50 | + * as published by the Free Software Foundation. |
51 | + * |
52 | + * This program is distributed in the hope that it will be useful, |
53 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
54 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
55 | + * GNU General Public License for more details. |
56 | + * |
57 | + * You should have received a copy of the GNU General Public License |
58 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
59 | + * |
60 | + * Authored By: Alan Griffiths <alan@octopull.co.uk> |
61 | + */ |
62 | + |
63 | +#ifndef MIR_SHELL_SYSTEM_COMPOSITOR_WINDOW_MANAGER_H_ |
64 | +#define MIR_SHELL_SYSTEM_COMPOSITOR_WINDOW_MANAGER_H_ |
65 | + |
66 | +#include "mir/shell/window_manager.h" |
67 | + |
68 | +namespace mir |
69 | +{ |
70 | +namespace scene { class PlacementStrategy; class SessionCoordinator; } |
71 | +namespace shell |
72 | +{ |
73 | +class FocusController; |
74 | +class DisplayLayout; |
75 | + |
76 | +/** Minimal window management for system compositing. |
77 | + */ |
78 | +class SystemCompositorWindowManager : public WindowManager |
79 | +{ |
80 | +public: |
81 | + SystemCompositorWindowManager( |
82 | + FocusController* focus_controller, |
83 | + std::shared_ptr<shell::DisplayLayout> const& display_layout, |
84 | + std::shared_ptr<scene::SessionCoordinator> const& session_coordinator); |
85 | + |
86 | +/** @name Customization points |
87 | + * These are the likely events that a system compositor will care about |
88 | + * @{ */ |
89 | + /// Called when a session first connects (before any surfaces are ready) |
90 | + virtual void on_session_added(std::shared_ptr<scene::Session> const& session) const; |
91 | + |
92 | + /// Called when a session disconnects |
93 | + virtual void on_session_removed(std::shared_ptr<scene::Session> const& session) const; |
94 | + |
95 | + /// Called the first time each surface owned by the session posts its first buffer |
96 | + virtual void on_session_ready(std::shared_ptr<scene::Session> const& session) const; |
97 | +/** @} */ |
98 | + |
99 | +protected: |
100 | + FocusController* const focus_controller; |
101 | + std::shared_ptr<DisplayLayout> const display_layout; |
102 | + std::shared_ptr<scene::SessionCoordinator> const session_coordinator; |
103 | + |
104 | +private: |
105 | + void add_session(std::shared_ptr<scene::Session> const& session) override; |
106 | + |
107 | + void remove_session(std::shared_ptr<scene::Session> const& session) override; |
108 | + |
109 | + frontend::SurfaceId add_surface( |
110 | + std::shared_ptr<scene::Session> const& session, |
111 | + scene::SurfaceCreationParameters const& params, |
112 | + std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build) override; |
113 | + |
114 | + void modify_surface( |
115 | + std::shared_ptr<scene::Session> const& session, |
116 | + std::shared_ptr<scene::Surface> const& surface, |
117 | + SurfaceSpecification const& modifications) override; |
118 | + |
119 | + void remove_surface( |
120 | + std::shared_ptr<scene::Session> const& session, |
121 | + std::weak_ptr<scene::Surface> const& surface) override; |
122 | + |
123 | + void add_display(geometry::Rectangle const& area) override; |
124 | + |
125 | + void remove_display(geometry::Rectangle const& area) override; |
126 | + |
127 | + bool handle_keyboard_event(MirKeyboardEvent const* event) override; |
128 | + |
129 | + bool handle_touch_event(MirTouchEvent const* event) override; |
130 | + |
131 | + bool handle_pointer_event(MirPointerEvent const* event) override; |
132 | + |
133 | + int set_surface_attribute( |
134 | + std::shared_ptr<scene::Session> const& session, |
135 | + std::shared_ptr<scene::Surface> const& surface, |
136 | + MirSurfaceAttrib attrib, |
137 | + int value) override; |
138 | +}; |
139 | +} |
140 | +} |
141 | + |
142 | + |
143 | +#endif /* MIR_SHELL_SYSTEM_COMPOSITOR_WINDOW_MANAGER_H_ */ |
144 | |
145 | === modified file 'src/server/shell/CMakeLists.txt' |
146 | --- src/server/shell/CMakeLists.txt 2015-05-28 07:48:04 +0000 |
147 | +++ src/server/shell/CMakeLists.txt 2015-06-16 08:37:48 +0000 |
148 | @@ -10,6 +10,7 @@ |
149 | default_window_manager.cpp |
150 | shell_wrapper.cpp |
151 | surface_ready_observer.cpp |
152 | + system_compositor_window_manager.cpp |
153 | default_persistent_surface_store.cpp |
154 | persistent_surface_store.cpp |
155 | ) |
156 | |
157 | === added file 'src/server/shell/system_compositor_window_manager.cpp' |
158 | --- src/server/shell/system_compositor_window_manager.cpp 1970-01-01 00:00:00 +0000 |
159 | +++ src/server/shell/system_compositor_window_manager.cpp 2015-06-16 08:37:48 +0000 |
160 | @@ -0,0 +1,151 @@ |
161 | +/* |
162 | + * Copyright © 2015 Canonical Ltd. |
163 | + * |
164 | + * This program is free software: you can redistribute it and/or modify it |
165 | + * under the terms of the GNU General Public License version 3, |
166 | + * as published by the Free Software Foundation. |
167 | + * |
168 | + * This program is distributed in the hope that it will be useful, |
169 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
170 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
171 | + * GNU General Public License for more details. |
172 | + * |
173 | + * You should have received a copy of the GNU General Public License |
174 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
175 | + * |
176 | + * Authored By: Alan Griffiths <alan@octopull.co.uk> |
177 | + */ |
178 | + |
179 | +#include "mir/shell/system_compositor_window_manager.h" |
180 | + |
181 | +#include "mir/shell/display_layout.h" |
182 | +#include "mir/shell/focus_controller.h" |
183 | +#include "mir/shell/surface_ready_observer.h" |
184 | +#include "mir/shell/surface_specification.h" |
185 | + |
186 | +#include "mir/scene/session.h" |
187 | +#include "mir/scene/session_coordinator.h" |
188 | +#include "mir/scene/surface.h" |
189 | +#include "mir/scene/surface_creation_parameters.h" |
190 | + |
191 | +namespace mf = mir::frontend; |
192 | +namespace ms = mir::scene; |
193 | +namespace msh = mir::shell; |
194 | + |
195 | +msh::SystemCompositorWindowManager::SystemCompositorWindowManager( |
196 | + FocusController* focus_controller, |
197 | + std::shared_ptr<DisplayLayout> const& display_layout, |
198 | + std::shared_ptr<ms::SessionCoordinator> const& session_coordinator) : |
199 | + focus_controller{focus_controller}, |
200 | + display_layout{display_layout}, |
201 | + session_coordinator{session_coordinator} |
202 | +{ |
203 | +} |
204 | + |
205 | +void msh::SystemCompositorWindowManager::add_session(std::shared_ptr<ms::Session> const& session) |
206 | +{ |
207 | + on_session_added(session); |
208 | +} |
209 | + |
210 | +void msh::SystemCompositorWindowManager::remove_session(std::shared_ptr<ms::Session> const& session) |
211 | +{ |
212 | + on_session_removed(session); |
213 | +} |
214 | + |
215 | +auto msh::SystemCompositorWindowManager::add_surface( |
216 | + std::shared_ptr<ms::Session> const& session, |
217 | + ms::SurfaceCreationParameters const& params, |
218 | + std::function<mf::SurfaceId(std::shared_ptr<ms::Session> const& session, ms::SurfaceCreationParameters const& params)> const& build) |
219 | +-> mf::SurfaceId |
220 | +{ |
221 | + mir::geometry::Rectangle rect{params.top_left, params.size}; |
222 | + |
223 | + display_layout->place_in_output(params.output_id, rect); |
224 | + |
225 | + auto placed_parameters = params; |
226 | + placed_parameters.top_left = rect.top_left; |
227 | + placed_parameters.size = rect.size; |
228 | + |
229 | + auto const result = build(session, placed_parameters); |
230 | + auto const surface = session->surface(result); |
231 | + |
232 | + auto const session_ready_observer = std::make_shared<SurfaceReadyObserver>( |
233 | + [this](std::shared_ptr<ms::Session> const& session, std::shared_ptr<ms::Surface> const& /*surface*/) |
234 | + { |
235 | + on_session_ready(session); |
236 | + }, |
237 | + session, |
238 | + surface); |
239 | + |
240 | + surface->add_observer(session_ready_observer); |
241 | + |
242 | + return result; |
243 | +} |
244 | + |
245 | +void msh::SystemCompositorWindowManager::modify_surface( |
246 | + std::shared_ptr<ms::Session> const& /*session*/, |
247 | + std::shared_ptr<ms::Surface> const& surface, |
248 | + SurfaceSpecification const& modifications) |
249 | +{ |
250 | + if (modifications.name.is_set()) |
251 | + surface->rename(modifications.name.value()); |
252 | +} |
253 | + |
254 | +void msh::SystemCompositorWindowManager::remove_surface( |
255 | + std::shared_ptr<ms::Session> const& /*session*/, |
256 | + std::weak_ptr<ms::Surface> const& /*surface*/) |
257 | +{ |
258 | +} |
259 | + |
260 | +void msh::SystemCompositorWindowManager::add_display(mir::geometry::Rectangle const& /*area*/) |
261 | +{ |
262 | +} |
263 | + |
264 | +void msh::SystemCompositorWindowManager::remove_display(mir::geometry::Rectangle const& /*area*/) |
265 | +{ |
266 | +} |
267 | + |
268 | +bool msh::SystemCompositorWindowManager::handle_keyboard_event(MirKeyboardEvent const* /*event*/) |
269 | +{ |
270 | + return false; |
271 | +} |
272 | + |
273 | +bool msh::SystemCompositorWindowManager::handle_touch_event(MirTouchEvent const* /*event*/) |
274 | +{ |
275 | + return false; |
276 | +} |
277 | + |
278 | +bool msh::SystemCompositorWindowManager::handle_pointer_event(MirPointerEvent const* /*event*/) |
279 | +{ |
280 | + return false; |
281 | +} |
282 | + |
283 | +int msh::SystemCompositorWindowManager::set_surface_attribute( |
284 | + std::shared_ptr<ms::Session> const& /*session*/, |
285 | + std::shared_ptr<ms::Surface> const& surface, |
286 | + MirSurfaceAttrib attrib, |
287 | + int value) |
288 | +{ |
289 | + return surface->configure(attrib, value); |
290 | +} |
291 | + |
292 | +void msh::SystemCompositorWindowManager::on_session_added(std::shared_ptr<mir::scene::Session> const& /*session*/) const |
293 | +{ |
294 | +} |
295 | + |
296 | +void msh::SystemCompositorWindowManager::on_session_removed(std::shared_ptr<mir::scene::Session> const& session) const |
297 | +{ |
298 | + if (focus_controller->focused_session() == session) |
299 | + { |
300 | + auto const next_session = session_coordinator->successor_of({}); |
301 | + if (next_session) |
302 | + focus_controller->set_focus_to(next_session, next_session->default_surface()); |
303 | + else |
304 | + focus_controller->set_focus_to(next_session, {}); |
305 | + } |
306 | +} |
307 | + |
308 | +void msh::SystemCompositorWindowManager::on_session_ready(std::shared_ptr<mir::scene::Session> const& session) const |
309 | +{ |
310 | + focus_controller->set_focus_to(session, session->default_surface()); |
311 | +} |
312 | |
313 | === modified file 'src/server/symbols.map' |
314 | --- src/server/symbols.map 2015-06-10 23:37:28 +0000 |
315 | +++ src/server/symbols.map 2015-06-16 08:37:48 +0000 |
316 | @@ -5,7 +5,8 @@ |
317 | vtable?for?mir::input::NullInputDispatcher; |
318 | VTT?for?mir::DefaultServerConfiguration; |
319 | VTT?for?mir::shell::ShellWrapper; |
320 | - |
321 | + VTT?for?mir::shell::SystemCompositorWindowManager; |
322 | + |
323 | # The following symbols come from running a script over the generated docs. Vis: |
324 | # ../tools/process_doxygen_xml.py doc/xml/*.xml | grep "^mirserver public" | sed "s/mirserver public: / /" | sort |
325 | mir::compositor::Compositor::Compositor*; |
326 | @@ -252,6 +253,34 @@ |
327 | mir::shell::ShellWrapper::surface_at*; |
328 | mir::shell::SurfaceReadyObserver::SurfaceReadyObserver*; |
329 | mir::shell::SurfaceReadyObserver::?SurfaceReadyObserver*; |
330 | + mir::shell::SystemCompositorWindowManager::SystemCompositorWindowManager*; |
331 | + mir::shell::SystemCompositorWindowManager::add_display*; |
332 | + mir::shell::SystemCompositorWindowManager::add_prompt_provider_for*; |
333 | + mir::shell::SystemCompositorWindowManager::add_session*; |
334 | + mir::shell::SystemCompositorWindowManager::add_surface*; |
335 | + mir::shell::SystemCompositorWindowManager::close_session*; |
336 | + mir::shell::SystemCompositorWindowManager::create_surface*; |
337 | + mir::shell::SystemCompositorWindowManager::destroy_surface*; |
338 | + mir::shell::SystemCompositorWindowManager::focused_session*; |
339 | + mir::shell::SystemCompositorWindowManager::focused_surface*; |
340 | + mir::shell::SystemCompositorWindowManager::focus_next_session*; |
341 | + mir::shell::SystemCompositorWindowManager::get_surface_attribute*; |
342 | + mir::shell::SystemCompositorWindowManager::handle*; |
343 | + mir::shell::SystemCompositorWindowManager::modify_surface*; |
344 | + mir::shell::SystemCompositorWindowManager::on_session_added*; |
345 | + mir::shell::SystemCompositorWindowManager::on_session_removed*; |
346 | + mir::shell::SystemCompositorWindowManager::on_session_ready*; |
347 | + mir::shell::SystemCompositorWindowManager::open_session*; |
348 | + mir::shell::SystemCompositorWindowManager::raise*; |
349 | + mir::shell::SystemCompositorWindowManager::remove_display*; |
350 | + mir::shell::SystemCompositorWindowManager::remove_session*; |
351 | + mir::shell::SystemCompositorWindowManager::remove_surface*; |
352 | + mir::shell::SystemCompositorWindowManager::set_focus_to*; |
353 | + mir::shell::SystemCompositorWindowManager::set_surface_attribute*; |
354 | + mir::shell::SystemCompositorWindowManager::ShellWrapper*; |
355 | + mir::shell::SystemCompositorWindowManager::start_prompt_session_for*; |
356 | + mir::shell::SystemCompositorWindowManager::stop_prompt_session*; |
357 | + mir::shell::SystemCompositorWindowManager::surface_at*; |
358 | mir::shell::WindowManager::operator*; |
359 | mir::shell::WindowManager::?WindowManager*; |
360 | mir::shell::WindowManager::WindowManager*; |
361 | @@ -345,6 +374,29 @@ |
362 | non-virtual?thunk?to?mir::shell::ShellWrapper::stop_prompt_session*; |
363 | non-virtual?thunk?to?mir::shell::ShellWrapper::surface_at*; |
364 | non-virtual?thunk?to?mir::shell::SurfaceReadyObserver::?SurfaceReadyObserver*; |
365 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::add_display*; |
366 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::add_prompt_provider_for*; |
367 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::close_session*; |
368 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::create_surface*; |
369 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::destroy_surface*; |
370 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::focused_session*; |
371 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::focused_surface*; |
372 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::focus_next_session*; |
373 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::get_surface_attribute*; |
374 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::handle*; |
375 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::modify_surface*; |
376 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::on_session_added*; |
377 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::on_session_removed*; |
378 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::on_session_ready*; |
379 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::open_session*; |
380 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::raise*; |
381 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::remove_display*; |
382 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::set_focus_to*; |
383 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::set_surface_attribute*; |
384 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::ShellWrapper*; |
385 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::start_prompt_session_for*; |
386 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::stop_prompt_session*; |
387 | + non-virtual?thunk?to?mir::shell::SystemCompositorWindowManager::surface_at*; |
388 | non-virtual?thunk?to?mir::shell::WindowManager::?WindowManager*; |
389 | non-virtual?thunk?to?mir::time::Alarm::?Alarm*; |
390 | non-virtual?thunk?to?mir::time::AlarmFactory::?AlarmFactory*; |
391 | @@ -402,6 +454,7 @@ |
392 | typeinfo?for?mir::shell::Shell; |
393 | typeinfo?for?mir::shell::ShellWrapper; |
394 | typeinfo?for?mir::shell::SurfaceReadyObserver; |
395 | + typeinfo?for?mir::shell::SystemCompositorWindowManager; |
396 | typeinfo?for?mir::shell::WindowManager; |
397 | typeinfo?for?mir::time::Alarm; |
398 | typeinfo?for?mir::time::AlarmFactory; |
399 | @@ -459,6 +512,7 @@ |
400 | vtable?for?mir::shell::Shell; |
401 | vtable?for?mir::shell::ShellWrapper; |
402 | vtable?for?mir::shell::SurfaceReadyObserver; |
403 | + vtable?for?mir::shell::SystemCompositorWindowManager; |
404 | vtable?for?mir::shell::WindowManager; |
405 | vtable?for?mir::time::Alarm; |
406 | vtable?for?mir::time::AlarmFactory; |
407 | |
408 | === modified file 'tests/acceptance-tests/CMakeLists.txt' |
409 | --- tests/acceptance-tests/CMakeLists.txt 2015-06-11 09:41:30 +0000 |
410 | +++ tests/acceptance-tests/CMakeLists.txt 2015-06-16 08:37:48 +0000 |
411 | @@ -45,6 +45,7 @@ |
412 | test_surface_modifications.cpp |
413 | test_surface_placement.cpp |
414 | test_surface_morphing.cpp |
415 | + test_system_compositor_window_manager.cpp |
416 | test_session_mediator_report.cpp |
417 | ) |
418 | |
419 | |
420 | === added file 'tests/acceptance-tests/test_system_compositor_window_manager.cpp' |
421 | --- tests/acceptance-tests/test_system_compositor_window_manager.cpp 1970-01-01 00:00:00 +0000 |
422 | +++ tests/acceptance-tests/test_system_compositor_window_manager.cpp 2015-06-16 08:37:48 +0000 |
423 | @@ -0,0 +1,205 @@ |
424 | +/* |
425 | + * Copyright © 2015 Canonical Ltd. |
426 | + * |
427 | + * This program is free software: you can redistribute it and/or modify it |
428 | + * under the terms of the GNU General Public License version 3, |
429 | + * as published by the Free Software Foundation. |
430 | + * |
431 | + * This program is distributed in the hope that it will be useful, |
432 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
433 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
434 | + * GNU General Public License for more details. |
435 | + * |
436 | + * You should have received a copy of the GNU General Public License |
437 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
438 | + * |
439 | + * Authored by: Alan Griffiths <alan@octopull.co.uk> |
440 | + */ |
441 | + |
442 | +#include "mir/shell/system_compositor_window_manager.h" |
443 | +#include "mir_toolkit/mir_client_library.h" |
444 | + |
445 | +#include "mir/geometry/rectangle.h" |
446 | +#include "mir_test_framework/headless_test.h" |
447 | +#include "mir_test/signal.h" |
448 | + |
449 | +#include "gmock/gmock.h" |
450 | + |
451 | +namespace msh = mir::shell; |
452 | +namespace mt = mir::test; |
453 | +namespace mtf = mir_test_framework; |
454 | + |
455 | +using namespace testing; |
456 | +using namespace std::chrono_literals; |
457 | + |
458 | +namespace |
459 | +{ |
460 | +class SurfaceHandle |
461 | +{ |
462 | +public: |
463 | + explicit SurfaceHandle(MirSurface* surface) : surface{surface} {} |
464 | + ~SurfaceHandle() { if (surface) mir_surface_release_sync(surface); } |
465 | + |
466 | + operator MirSurface*() const { return surface; } |
467 | + |
468 | + void post_buffer() |
469 | + { |
470 | + mir_buffer_stream_swap_buffers_sync(mir_surface_get_buffer_stream(surface)); |
471 | + } |
472 | + |
473 | + SurfaceHandle(SurfaceHandle const&& that) : surface{that.surface} { surface = nullptr; } |
474 | +private: |
475 | + SurfaceHandle(SurfaceHandle const&) = delete; |
476 | + MirSurface* surface; |
477 | +}; |
478 | + |
479 | +struct MockClient |
480 | +{ |
481 | + explicit MockClient(char const* connect_string) : |
482 | + connection{mir_connect_sync(connect_string, __PRETTY_FUNCTION__)} |
483 | + { |
484 | + } |
485 | + |
486 | + MockClient(MockClient&& source) : |
487 | + connection{nullptr} |
488 | + { |
489 | + std::swap(connection, source.connection); |
490 | + } |
491 | + |
492 | + auto create_surface(int output_id) -> SurfaceHandle |
493 | + { |
494 | + auto const spec = mir_connection_create_spec_for_normal_surface( |
495 | + connection, 800, 600, mir_pixel_format_bgr_888); |
496 | + |
497 | + mir_surface_spec_set_fullscreen_on_output(spec, output_id); |
498 | + auto const surface = mir_surface_create_sync(spec); |
499 | + mir_surface_spec_release(spec); |
500 | + |
501 | + mir_surface_set_event_handler(surface, on_surface_event, this); |
502 | + |
503 | + return SurfaceHandle{surface}; |
504 | + }; |
505 | + |
506 | + void disconnect() |
507 | + { |
508 | + if (connection) |
509 | + mir_connection_release(connection); |
510 | + |
511 | + connection = nullptr; |
512 | + } |
513 | + |
514 | + ~MockClient() noexcept |
515 | + { |
516 | + disconnect(); |
517 | + } |
518 | + |
519 | + MOCK_METHOD2(surface_event, void(MirSurface* surface, const MirEvent* event)); |
520 | + |
521 | +private: |
522 | + MirConnection* connection{nullptr}; |
523 | + |
524 | + static void on_surface_event(MirSurface* surface, const MirEvent* event, void* client_ptr) |
525 | + { |
526 | + static_cast<MockClient*>(client_ptr)->surface_event(surface, event); |
527 | + } |
528 | +}; |
529 | + |
530 | +struct SystemCompositorWindowManager : mtf::HeadlessTest |
531 | +{ |
532 | + void SetUp() override |
533 | + { |
534 | + add_to_environment("MIR_SERVER_NO_FILE", ""); |
535 | + |
536 | + initial_display_layout({{{0, 0}, { 640, 480}}, {{480, 0}, {1920, 1080}}}); |
537 | + |
538 | + server.override_the_window_manager_builder( |
539 | + [this](msh::FocusController* focus_controller) |
540 | + { |
541 | + return std::make_shared<msh::SystemCompositorWindowManager>( |
542 | + focus_controller, |
543 | + server.the_shell_display_layout(), |
544 | + server.the_session_coordinator()); |
545 | + }); |
546 | + |
547 | + start_server(); |
548 | + } |
549 | + |
550 | + void TearDown() override |
551 | + { |
552 | + stop_server(); |
553 | + } |
554 | + |
555 | + MockClient connect_client() |
556 | + { |
557 | + return MockClient(new_connection().c_str()); |
558 | + } |
559 | +}; |
560 | + |
561 | +MATCHER_P(MirFocusEvent, expected, "") |
562 | +{ |
563 | + if (mir_event_get_type(arg) != mir_event_type_surface) |
564 | + return false; |
565 | + |
566 | + auto surface_event = mir_event_get_surface_event(arg); |
567 | + auto attrib = mir_surface_event_get_attribute(surface_event); |
568 | + auto value = mir_surface_event_get_attribute_value(surface_event); |
569 | + |
570 | + return (attrib == mir_surface_attrib_focus) |
571 | + && (value == expected); |
572 | +} |
573 | +} |
574 | + |
575 | +TEST_F(SystemCompositorWindowManager, when_output_is_valid_surfaces_creation_succeeds) |
576 | +{ |
577 | + auto client = connect_client(); |
578 | + |
579 | + auto surface1 = client.create_surface(1); |
580 | + auto surface2 = client.create_surface(2); |
581 | + |
582 | + EXPECT_TRUE(mir_surface_is_valid(surface1)); |
583 | + EXPECT_TRUE(mir_surface_is_valid(surface2)); |
584 | +} |
585 | + |
586 | +TEST_F(SystemCompositorWindowManager, when_output_ID_not_specified_surfaces_creation_fails) |
587 | +{ |
588 | + auto client = connect_client(); |
589 | + |
590 | + auto surface = client.create_surface(0); |
591 | + |
592 | + EXPECT_FALSE(mir_surface_is_valid(surface)); |
593 | + EXPECT_THAT(mir_surface_get_error_message(surface), HasSubstr("Failed to place surface")); |
594 | +} |
595 | + |
596 | +TEST_F(SystemCompositorWindowManager, if_a_surface_posts_client_gets_focus) |
597 | +{ |
598 | + auto client = connect_client(); |
599 | + |
600 | + // Throw away all uninteresting surface events |
601 | + EXPECT_CALL(client, surface_event(_, Not(MirFocusEvent(mir_surface_focused)))).Times(AnyNumber()); |
602 | + |
603 | + auto surface = client.create_surface(1); |
604 | + |
605 | + mt::Signal signal; |
606 | + |
607 | + EXPECT_CALL(client, surface_event(_, MirFocusEvent(mir_surface_focused))).Times(1) |
608 | + .WillOnce(InvokeWithoutArgs([&] { signal.raise(); })); |
609 | + |
610 | + surface.post_buffer(); |
611 | + |
612 | + signal.wait_for(1s); |
613 | +} |
614 | + |
615 | +TEST_F(SystemCompositorWindowManager, if_no_surface_posts_client_never_gets_focus) |
616 | +{ |
617 | + auto client = connect_client(); |
618 | + auto surface = client.create_surface(1); |
619 | + |
620 | + mt::Signal signal; |
621 | + |
622 | + ON_CALL(client, surface_event(_, MirFocusEvent(mir_surface_focused))) |
623 | + .WillByDefault(InvokeWithoutArgs([&] { signal.raise(); })); |
624 | + |
625 | + EXPECT_CALL(client, surface_event(_, MirFocusEvent(mir_surface_focused))).Times(0); |
626 | + |
627 | + signal.wait_for(100ms); |
628 | +} |
PASSED: Continuous integration, rev:2660 jenkins. qa.ubuntu. com/job/ mir-ci/ 4082/ jenkins. qa.ubuntu. com/job/ mir-android- vivid-i386- build/2822 jenkins. qa.ubuntu. com/job/ mir-clang- wily-amd64- build/335 jenkins. qa.ubuntu. com/job/ mir-mediumtests -vivid- touch/2770 jenkins. qa.ubuntu. com/job/ mir-wily- amd64-ci/ 238 jenkins. qa.ubuntu. com/job/ mir-wily- amd64-ci/ 238/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-mediumtests -builder- vivid-armhf/ 2770 jenkins. qa.ubuntu. com/job/ mir-mediumtests -builder- vivid-armhf/ 2770/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-mediumtests -runner- mako/5605 s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 21147
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/mir- ci/4082/ rebuild
http://