Mir

Merge lp:~alan-griffiths/mir/MVC-introduce-default-controller-object into lp:mir

Proposed by Alan Griffiths on 2015-01-19
Status: Merged
Approved by: Alexandros Frantzis on 2015-01-22
Approved revision: 2240
Merged at revision: 2250
Proposed branch: lp:~alan-griffiths/mir/MVC-introduce-default-controller-object
Merge into: lp:mir
Prerequisite: lp:~alan-griffiths/mir/MVC-cleanup-of-frontend
Diff against target: 1401 lines (+542/-338)
19 files modified
include/server/mir/scene/session_coordinator.h (+40/-4)
include/server/mir/shell/session_coordinator_wrapper.h (+13/-29)
server-ABI-sha1sums (+2/-2)
src/include/server/mir/default_server_configuration.h (+5/-0)
src/server/scene/default_configuration.cpp (+0/-13)
src/server/scene/session_manager.cpp (+22/-120)
src/server/scene/session_manager.h (+11/-40)
src/server/shell/CMakeLists.txt (+1/-0)
src/server/shell/default_configuration.cpp (+25/-1)
src/server/shell/default_shell.cpp (+178/-0)
src/server/shell/default_shell.h (+94/-0)
src/server/shell/session_coordinator_wrapper.cpp (+13/-45)
src/server/symbols.map (+2/-0)
tests/acceptance-tests/server_configuration_wrapping.cpp (+3/-3)
tests/acceptance-tests/test_client_focus_notification.cpp (+1/-0)
tests/acceptance-tests/test_prompt_session_client_api.cpp (+1/-1)
tests/integration-tests/CMakeLists.txt (+1/-1)
tests/integration-tests/test_default_shell.cpp (+27/-30)
tests/unit-tests/scene/test_session_manager.cpp (+103/-49)
To merge this branch: bzr merge lp:~alan-griffiths/mir/MVC-introduce-default-controller-object
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve on 2015-01-22
Robert Carr (community) Approve on 2015-01-21
Alexandros Frantzis (community) Approve on 2015-01-21
Daniel van Vugt Needs Information on 2015-01-21
Alberto Aguirre 2015-01-19 Approve on 2015-01-20
Review via email: mp+246924@code.launchpad.net

Commit Message

shell, scene: introduce a "Controller" into shell and shift window management logic there from scene

Description of the Change

shell, scene: introduce a "Controller" into shell and shift window management logic there from scene

I hope thins to start simplifying after this - my next target is the removal of FocusSetter/DefaultFocusMechanism and their integration into DefaultShell.

This doesn't make the "DefaultShell" controller customizable - that, and other cleanup is for a future MP

To post a comment you must log in.
Alan Griffiths (alan-griffiths) wrote :

mako-08 AWOL again - retriggering

Alberto Aguirre (albaguirre) wrote :

OK.

review: Approve
Daniel van Vugt (vanvugt) wrote :

That's a bit disappointing. It's this ugliness by previous branch was designed to avoid:
  13 + auto const surface = std::dynamic_pointer_cast<ms::Surface>(session->get_surface(surface_id));
And yet we've landed it already.

On a different note; are there plans to move Shell out of frontend? Why is it there?

review: Needs Information
Alan Griffiths (alan-griffiths) wrote :

> That's a bit disappointing. It's this ugliness by previous branch was designed
> to avoid:
> 13 + auto const surface =
> std::dynamic_pointer_cast<ms::Surface>(session->get_surface(surface_id));
> And yet we've landed it already.

Agreed, the ugliness hasn't been addressed (yet). But the point of this MP is to separate the window management logic from the model code. I'm trying to keep other (needed) refactoring out of the MP until the consolidation of "controller" functionality is in place.

> On a different note; are there plans to move Shell out of frontend? Why is it
> there?

I'm sure you've asked this question before. The answer is still the same:

No, the frontend::Shell interface defines the needs of frontend and hence belongs there.

Alan Griffiths (alan-griffiths) wrote :

>
W: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/vivid/universe/i18n/Translation-en Hash Sum mismatch

unrelated CI error

2240. By Alan Griffiths on 2015-01-21

merge lp:mir

Alexandros Frantzis (afrantzis) wrote :

Looks good as an intermediate step.

review: Approve
Alan Griffiths (alan-griffiths) wrote :

> Building remotely on cloud-worker-11 in workspace /var/lib/jenkins/slaves/cloud-worker-11/workspace/mir-android-vivid-i386-build
...
> [ 51%] Building CXX object tests/acceptance-tests/throwback/CMakeFiles/acceptance-test-throwback.dir/test_custom_input_dispatcher.cpp.o
> Build timed out (after 120 minutes). Marking the build as failed.
> Build was aborted

cloud-worker-11 timing out again

Retriggering

Robert Carr (robertcarr) wrote :

+1

review: Approve
Alberto Aguirre (albaguirre) wrote :

"FATAL: Unable to delete script file /tmp/hudson3556432461291323175.sh
hudson.util.IOException2: remote file operation failed: /tmp/hudson3556432461291323175.sh at hudson.remoting.Channel@4e966112:cloud-worker-11"

Re-triggering

Daniel van Vugt (vanvugt) wrote :

> No, the frontend::Shell interface defines the needs of frontend and hence
> belongs there.

I don't think that's a good answer. A "shell" is something that will be implemented by other people. And those other people should not know or care what the internal term "frontend" means to the Mir source code.

Alan Griffiths (alan-griffiths) wrote :

>
Building remotely on cloud-worker-11 in workspace /var/lib/jenkins/slaves/cloud-worker-11/workspace/mir-android-vivid-i386-build
...

> [ 51%] Building CXX object tests/mir_test_doubles/CMakeFiles/mir-test-doubles.dir/test_protobuf_client.cpp.o
> FATAL: Unable to delete script file /tmp/hudson6153692886848568188.sh
> hudson.util.IOException2: remote file operation failed: /tmp/hudson6153692886848568188.sh at hudson.remoting.Channel@5ba6b35d:cloud-worker-11

Our old friend cloud-worker-11 :(

Alan Griffiths (alan-griffiths) wrote :

> > No, the frontend::Shell interface defines the needs of frontend and hence
> > belongs there.
>
> I don't think that's a good answer. A "shell" is something that will be
> implemented by other people. And those other people should not know or care
> what the internal term "frontend" means to the Mir source code.

1. I don't see how any of this tired discussion is relevant to landing this MP
2. Putting the interface with the code that uses it is policy (although not followed very strictly - but we are fixing that)
3. frontend::Shell is not a definition of "something that will be implemented by other people" it is a definition of what that would need to do to support frontend.
4. "something that will be implemented by other people" will have to support other components too - e.g. to handle changes to outputs it needs to support graphics::DisplayConfigurationPolicy

There is nothing that prevents us having:

shell::Shell : public graphics::DisplayConfigurationPolicy, public frontend::Shell, ...

Alexandros Frantzis (afrantzis) wrote :

All parts of the request for information have been either addressed adequately (we agree that std::dynamic_cast<> is not ideal and will be fixed in a future MP), or are tangential to this MP (frontend::Shell discussion) and therefore not blockers anyway, so I am going to top approve.

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/server/mir/scene/session_coordinator.h'
2--- include/server/mir/scene/session_coordinator.h 2015-01-14 06:39:13 +0000
3+++ include/server/mir/scene/session_coordinator.h 2015-01-21 10:18:06 +0000
4@@ -19,17 +19,53 @@
5 #ifndef MIR_SCENE_SESSION_COORDINATOR_H_
6 #define MIR_SCENE_SESSION_COORDINATOR_H_
7
8-
9-#include "mir/frontend/shell.h"
10-#include "mir/shell/focus_controller.h"
11+#include "mir/frontend/surface_id.h"
12+
13+#include "mir_toolkit/common.h"
14+
15+#include <memory>
16
17 namespace mir
18 {
19+namespace frontend
20+{
21+class EventSink;
22+}
23+
24 namespace scene
25 {
26+class PromptSession;
27+class PromptSessionCreationParameters;
28+class Session;
29+class Surface;
30+class SurfaceCreationParameters;
31
32-class SessionCoordinator : public frontend::Shell, public shell::FocusController
33+class SessionCoordinator
34 {
35+public:
36+ virtual void set_focus_to(std::shared_ptr<Session> const& focus) = 0;
37+ virtual void unset_focus() = 0;
38+
39+ virtual std::shared_ptr<Session> open_session(
40+ pid_t client_pid,
41+ std::string const& name,
42+ std::shared_ptr<frontend::EventSink> const& sink) = 0;
43+
44+ virtual void close_session(std::shared_ptr<Session> const& session) = 0;
45+
46+ virtual std::shared_ptr<Session> successor_of(std::shared_ptr<Session> const&) const = 0;
47+
48+ virtual std::shared_ptr<PromptSession> start_prompt_session_for(std::shared_ptr<Session> const& session,
49+ PromptSessionCreationParameters const& params) = 0;
50+ virtual void add_prompt_provider_for(std::shared_ptr<PromptSession> const& prompt_session,
51+ std::shared_ptr<Session> const& session) = 0;
52+ virtual void stop_prompt_session(std::shared_ptr<PromptSession> const& prompt_session) = 0;
53+
54+protected:
55+ SessionCoordinator() = default;
56+ virtual ~SessionCoordinator() = default;
57+ SessionCoordinator(SessionCoordinator const&) = delete;
58+ SessionCoordinator& operator=(SessionCoordinator const&) = delete;
59 };
60
61 }
62
63=== modified file 'include/server/mir/shell/session_coordinator_wrapper.h'
64--- include/server/mir/shell/session_coordinator_wrapper.h 2015-01-19 11:36:40 +0000
65+++ include/server/mir/shell/session_coordinator_wrapper.h 2015-01-21 10:18:06 +0000
66@@ -31,43 +31,27 @@
67 public:
68 SessionCoordinatorWrapper(std::shared_ptr<scene::SessionCoordinator> const& wrapped);
69
70- virtual std::shared_ptr<frontend::Session> open_session(
71+ virtual std::shared_ptr<scene::Session> open_session(
72 pid_t client_pid,
73 std::string const& name,
74 std::shared_ptr<frontend::EventSink> const& sink) override;
75
76- virtual void close_session(std::shared_ptr<frontend::Session> const& session) override;
77-
78- void focus_next() override;
79- std::weak_ptr<scene::Session> focussed_application() const override;
80+ virtual void close_session(std::shared_ptr<scene::Session> const& session) override;
81+
82+ std::shared_ptr<scene::Session> successor_of(std::shared_ptr<scene::Session> const&) const override;
83+
84 void set_focus_to(std::shared_ptr<scene::Session> const& focus) override;
85-
86- void handle_surface_created(std::shared_ptr<frontend::Session> const& session) override;
87-
88- std::shared_ptr<frontend::PromptSession> start_prompt_session_for(
89- std::shared_ptr<frontend::Session> const& session,
90+ void unset_focus() override;
91+
92+ std::shared_ptr<scene::PromptSession> start_prompt_session_for(
93+ std::shared_ptr<scene::Session> const& session,
94 scene::PromptSessionCreationParameters const& params) override;
95
96 void add_prompt_provider_for(
97- std::shared_ptr<frontend::PromptSession> const& prompt_session,
98- std::shared_ptr<frontend::Session> const& session) override;
99-
100- void stop_prompt_session(std::shared_ptr<frontend::PromptSession> const& prompt_session) override;
101-
102- frontend::SurfaceId create_surface(std::shared_ptr<frontend::Session> const& session, scene::SurfaceCreationParameters const& params) override;
103-
104- void destroy_surface(std::shared_ptr<frontend::Session> const& session, frontend::SurfaceId surface) override;
105-
106- int set_surface_attribute(
107- std::shared_ptr<frontend::Session> const& session,
108- frontend::SurfaceId surface_id,
109- MirSurfaceAttrib attrib,
110- int value) override;
111-
112- int get_surface_attribute(
113- std::shared_ptr<frontend::Session> const& session,
114- frontend::SurfaceId surface_id,
115- MirSurfaceAttrib attrib) override;
116+ std::shared_ptr<scene::PromptSession> const& prompt_session,
117+ std::shared_ptr<scene::Session> const& session) override;
118+
119+ void stop_prompt_session(std::shared_ptr<scene::PromptSession> const& prompt_session) override;
120
121 protected:
122 std::shared_ptr<scene::SessionCoordinator> const wrapped;
123
124=== modified file 'server-ABI-sha1sums'
125--- server-ABI-sha1sums 2015-01-21 08:38:18 +0000
126+++ server-ABI-sha1sums 2015-01-21 10:18:06 +0000
127@@ -90,7 +90,7 @@
128 b657cfb8fb31140b83b78fc19135dd0165ede67b include/server/mir/scene/prompt_session.h
129 a745a63d413ced63b82350b8c253b65dffd5bf44 include/server/mir/scene/prompt_session_listener.h
130 a09a3f18ecea53dc45386c1e2baf545c4177c047 include/server/mir/scene/prompt_session_manager.h
131-5edf446380070f567500069e422d293e88468ee5 include/server/mir/scene/session_coordinator.h
132+d812335ef394d076952db04d1560f1f4a3159510 include/server/mir/scene/session_coordinator.h
133 8cb940e808eca7db115239a25167955d34acafc4 include/server/mir/scene/session.h
134 ee94083f10f890e24c0e0bbdb94842e2dd788deb include/server/mir/scene/session_listener.h
135 7f5f26000fd2312373817d05c488a6a950a47c82 include/server/mir/scene/snapshot.h
136@@ -107,7 +107,7 @@
137 6a2107b01feae13060d5c305804906e53c52e0be include/server/mir/shell/focus_controller.h
138 f8d415af54b4a477338fb9dbe20db01aa4544029 include/server/mir/shell/host_lifecycle_event_listener.h
139 4f50c37bb8e36a1aa4918af6aa01b0f032ed0984 include/server/mir/shell/input_targeter.h
140-a46723e246b4cb6619cf8abbedb02c3391f563c9 include/server/mir/shell/session_coordinator_wrapper.h
141+abb366424a9e09a75e5e68c67095f0b9bbe8eb54 include/server/mir/shell/session_coordinator_wrapper.h
142 18e869c5b87ab8be4bc185d2cd55a93d699cde72 include/server/mir/shell/surface_coordinator_wrapper.h
143 114cc8c0b12ee4fd78d86c8f3309546e4dc68c9f include/server/mir/terminate_with_current_exception.h
144 1b8c2a763c8f5f00b737c3a187db2304676f8076 include/server/mir/time/alarm.h
145
146=== modified file 'src/include/server/mir/default_server_configuration.h'
147--- src/include/server/mir/default_server_configuration.h 2015-01-14 06:39:13 +0000
148+++ src/include/server/mir/default_server_configuration.h 2015-01-21 10:18:06 +0000
149@@ -75,6 +75,7 @@
150 class FocusController;
151 class DisplayLayout;
152 class HostLifecycleEventListener;
153+class DefaultShell;
154 }
155 namespace time
156 {
157@@ -438,6 +439,10 @@
158 std::shared_ptr<scene::BroadcastingSessionEventSink> the_broadcasting_session_event_sink();
159
160 auto report_factory(char const* report_opt) -> std::unique_ptr<report::ReportFactory>;
161+
162+ // TODO properly expose a shell::Shell interface
163+ CachedPtr<shell::DefaultShell> default_shell;
164+ auto the_shell() -> std::shared_ptr<shell::DefaultShell>;
165 };
166 }
167
168
169=== modified file 'src/server/scene/default_configuration.cpp'
170--- src/server/scene/default_configuration.cpp 2015-01-14 06:39:13 +0000
171+++ src/server/scene/default_configuration.cpp 2015-01-21 10:18:06 +0000
172@@ -179,7 +179,6 @@
173 std::make_shared<ms::SessionManager>(
174 the_surface_coordinator(),
175 the_session_container(),
176- the_shell_focus_setter(),
177 the_snapshot_strategy(),
178 the_session_event_sink(),
179 the_session_listener(),
180@@ -194,18 +193,6 @@
181 return wrapped;
182 }
183
184-std::shared_ptr<mf::Shell>
185-mir::DefaultServerConfiguration::the_frontend_shell()
186-{
187- return the_session_coordinator();
188-}
189-
190-std::shared_ptr<msh::FocusController>
191-mir::DefaultServerConfiguration::the_focus_controller()
192-{
193- return the_session_coordinator();
194-}
195-
196 std::shared_ptr<ms::PixelBuffer>
197 mir::DefaultServerConfiguration::the_pixel_buffer()
198 {
199
200=== modified file 'src/server/scene/session_manager.cpp'
201--- src/server/scene/session_manager.cpp 2015-01-19 11:36:40 +0000
202+++ src/server/scene/session_manager.cpp 2015-01-21 10:18:06 +0000
203@@ -21,7 +21,6 @@
204 #include "session_container.h"
205 #include "mir/scene/surface.h"
206 #include "mir/scene/surface_coordinator.h"
207-#include "mir/shell/focus_setter.h"
208 #include "mir/scene/session.h"
209 #include "mir/scene/session_listener.h"
210 #include "mir/scene/prompt_session.h"
211@@ -41,14 +40,12 @@
212
213 ms::SessionManager::SessionManager(std::shared_ptr<SurfaceCoordinator> const& surface_factory,
214 std::shared_ptr<SessionContainer> const& container,
215- std::shared_ptr<msh::FocusSetter> const& focus_setter,
216 std::shared_ptr<SnapshotStrategy> const& snapshot_strategy,
217 std::shared_ptr<SessionEventSink> const& session_event_sink,
218 std::shared_ptr<SessionListener> const& session_listener,
219 std::shared_ptr<PromptSessionManager> const& prompt_session_manager) :
220 surface_coordinator(surface_factory),
221 app_container(container),
222- focus_setter(focus_setter),
223 snapshot_strategy(snapshot_strategy),
224 session_event_sink(session_event_sink),
225 session_listener(session_listener),
226@@ -56,7 +53,6 @@
227 {
228 assert(surface_factory);
229 assert(container);
230- assert(focus_setter);
231 assert(session_listener);
232 }
233
234@@ -80,7 +76,7 @@
235 close_session(session);
236 }
237
238-std::shared_ptr<mf::Session> ms::SessionManager::open_session(
239+std::shared_ptr<ms::Session> ms::SessionManager::open_session(
240 pid_t client_pid,
241 std::string const& name,
242 std::shared_ptr<mf::EventSink> const& sender)
243@@ -93,37 +89,22 @@
244
245 session_listener->starting(new_session);
246
247- set_focus_to(new_session);
248-
249 return new_session;
250 }
251
252-inline void ms::SessionManager::set_focus_to_locked(std::unique_lock<std::mutex> const&, std::shared_ptr<Session> const& session)
253-{
254- auto old_focus = focus_application.lock();
255-
256- focus_application = session;
257-
258- focus_setter->set_focus_to(session);
259- if (session)
260- {
261- session_event_sink->handle_focus_change(session);
262- session_listener->focused(session);
263- }
264- else
265- {
266- session_event_sink->handle_no_focus();
267- session_listener->unfocused();
268- }
269-}
270-
271 void ms::SessionManager::set_focus_to(std::shared_ptr<Session> const& session)
272 {
273- std::unique_lock<std::mutex> lg(mutex);
274- set_focus_to_locked(lg, session);
275-}
276-
277-void ms::SessionManager::close_session(std::shared_ptr<mf::Session> const& session)
278+ session_event_sink->handle_focus_change(session);
279+ session_listener->focused(session);
280+}
281+
282+void ms::SessionManager::unset_focus()
283+{
284+ session_event_sink->handle_no_focus();
285+ session_listener->unfocused();
286+}
287+
288+void ms::SessionManager::close_session(std::shared_ptr<Session> const& session)
289 {
290 auto scene_session = std::dynamic_pointer_cast<Session>(session);
291
292@@ -136,37 +117,9 @@
293 session_listener->stopping(scene_session);
294
295 app_container->remove_session(scene_session);
296-
297- std::unique_lock<std::mutex> lock(mutex);
298- set_focus_to_locked(lock, app_container->successor_of(std::shared_ptr<Session>()));
299-}
300-
301-void ms::SessionManager::focus_next()
302-{
303- std::unique_lock<std::mutex> lock(mutex);
304- auto focus = focus_application.lock();
305- if (!focus)
306- {
307- focus = app_container->successor_of(std::shared_ptr<Session>());
308- }
309- else
310- {
311- focus = app_container->successor_of(focus);
312- }
313- set_focus_to_locked(lock, focus);
314-}
315-
316-std::weak_ptr<ms::Session> ms::SessionManager::focussed_application() const
317-{
318- return focus_application;
319-}
320-
321-void ms::SessionManager::handle_surface_created(std::shared_ptr<mf::Session> const& session)
322-{
323- set_focus_to(std::dynamic_pointer_cast<Session>(session));
324-}
325-
326-std::shared_ptr<mf::PromptSession> ms::SessionManager::start_prompt_session_for(std::shared_ptr<mf::Session> const& session,
327+}
328+
329+std::shared_ptr<ms::PromptSession> ms::SessionManager::start_prompt_session_for(std::shared_ptr<Session> const& session,
330 PromptSessionCreationParameters const& params)
331 {
332 auto shell_session = std::dynamic_pointer_cast<Session>(session);
333@@ -177,8 +130,8 @@
334 }
335
336 void ms::SessionManager::add_prompt_provider_for(
337- std::shared_ptr<mf::PromptSession> const& prompt_session,
338- std::shared_ptr<frontend::Session> const& session)
339+ std::shared_ptr<PromptSession> const& prompt_session,
340+ std::shared_ptr<Session> const& session)
341 {
342 auto scene_prompt_session = std::dynamic_pointer_cast<PromptSession>(prompt_session);
343 auto scene_session = std::dynamic_pointer_cast<Session>(session);
344@@ -186,65 +139,14 @@
345 prompt_session_manager->add_prompt_provider(scene_prompt_session, scene_session);
346 }
347
348-void ms::SessionManager::stop_prompt_session(std::shared_ptr<mf::PromptSession> const& prompt_session)
349+void ms::SessionManager::stop_prompt_session(std::shared_ptr<PromptSession> const& prompt_session)
350 {
351 auto scene_prompt_session = std::dynamic_pointer_cast<PromptSession>(prompt_session);
352 prompt_session_manager->stop_prompt_session(scene_prompt_session);
353 }
354
355-mf::SurfaceId ms::SessionManager::create_surface(std::shared_ptr<mf::Session> const& session, scene::SurfaceCreationParameters const& params)
356-{
357- // TODO this downcasting is clunky, but is temporary wiring of the new interaction route to the old implementation
358- if (auto const sess = std::dynamic_pointer_cast<Session>(session))
359- {
360- return sess->create_surface(params);
361- }
362-
363- BOOST_THROW_EXCEPTION(std::logic_error("invalid session"));
364-}
365-
366-void ms::SessionManager::destroy_surface(std::shared_ptr<mf::Session> const& session, mf::SurfaceId surface)
367-{
368- // TODO this downcasting is clunky, but is temporary wiring of the new interaction route to the old implementation
369- if (auto const sess = std::dynamic_pointer_cast<Session>(session))
370- {
371- return sess->destroy_surface(surface);
372- }
373-
374- BOOST_THROW_EXCEPTION(std::logic_error("invalid session"));
375-}
376-
377-int ms::SessionManager::set_surface_attribute(
378- std::shared_ptr<mf::Session> const& session,
379- mf::SurfaceId surface_id,
380- MirSurfaceAttrib attrib,
381- int value)
382-{
383- // TODO this downcasting is clunky, but is temporary wiring of the new interaction route to the old implementation
384- if (!session)
385- BOOST_THROW_EXCEPTION(std::logic_error("invalid session"));
386-
387- auto const surface = std::dynamic_pointer_cast<Surface>(session->get_surface(surface_id));
388-
389- if (!surface)
390- BOOST_THROW_EXCEPTION(std::logic_error("invalid surface id"));
391-
392- return surface->configure(attrib, value);
393-}
394-
395-int ms::SessionManager::get_surface_attribute(
396- std::shared_ptr<mf::Session> const& session,
397- mf::SurfaceId surface_id,
398- MirSurfaceAttrib attrib)
399-{
400- // TODO this downcasting is clunky, but is temporary wiring of the new interaction route to the old implementation
401- if (!session)
402- BOOST_THROW_EXCEPTION(std::logic_error("invalid session"));
403-
404- auto const surface = std::dynamic_pointer_cast<Surface>(session->get_surface(surface_id));
405-
406- if (!surface)
407- BOOST_THROW_EXCEPTION(std::logic_error("invalid surface id"));
408-
409- return surface->query(attrib);
410+std::shared_ptr<ms::Session> ms::SessionManager::successor_of(
411+ std::shared_ptr<Session> const& session) const
412+{
413+ return app_container->successor_of(session);
414 }
415
416=== modified file 'src/server/scene/session_manager.h'
417--- src/server/scene/session_manager.h 2015-01-19 11:36:40 +0000
418+++ src/server/scene/session_manager.h 2015-01-21 10:18:06 +0000
419@@ -21,18 +21,11 @@
420
421 #include "mir/scene/session_coordinator.h"
422
423-#include <mutex>
424 #include <memory>
425 #include <vector>
426
427 namespace mir
428 {
429-
430-namespace shell
431-{
432-class FocusSetter;
433-}
434-
435 namespace scene
436 {
437 class SessionContainer;
438@@ -48,45 +41,29 @@
439 public:
440 explicit SessionManager(std::shared_ptr<SurfaceCoordinator> const& surface_coordinator,
441 std::shared_ptr<SessionContainer> const& app_container,
442- std::shared_ptr<shell::FocusSetter> const& focus_setter,
443 std::shared_ptr<SnapshotStrategy> const& snapshot_strategy,
444 std::shared_ptr<SessionEventSink> const& session_event_sink,
445 std::shared_ptr<SessionListener> const& session_listener,
446 std::shared_ptr<PromptSessionManager> const& prompt_session_manager);
447 virtual ~SessionManager() noexcept;
448
449- virtual std::shared_ptr<frontend::Session> open_session(
450+ std::shared_ptr<Session> open_session(
451 pid_t client_pid,
452 std::string const& name,
453 std::shared_ptr<frontend::EventSink> const& sink) override;
454
455- virtual void close_session(std::shared_ptr<frontend::Session> const& session) override;
456-
457- void focus_next() override;
458- std::weak_ptr<Session> focussed_application() const override;
459+ void close_session(std::shared_ptr<Session> const& session) override;
460+
461+ std::shared_ptr<Session> successor_of(std::shared_ptr<Session> const&) const override;
462+
463 void set_focus_to(std::shared_ptr<Session> const& focus) override;
464-
465- void handle_surface_created(std::shared_ptr<frontend::Session> const& session) override;
466-
467- std::shared_ptr<frontend::PromptSession> start_prompt_session_for(std::shared_ptr<frontend::Session> const& session,
468+ void unset_focus() override;
469+
470+ std::shared_ptr<PromptSession> start_prompt_session_for(std::shared_ptr<Session> const& session,
471 PromptSessionCreationParameters const& params) override;
472- void add_prompt_provider_for(std::shared_ptr<frontend::PromptSession> const& prompt_session,
473- std::shared_ptr<frontend::Session> const& session) override;
474- void stop_prompt_session(std::shared_ptr<frontend::PromptSession> const& prompt_session) override;
475-
476- int set_surface_attribute(
477- std::shared_ptr<frontend::Session> const& session,
478- frontend::SurfaceId surface_id,
479- MirSurfaceAttrib attrib,
480- int value) override;
481-
482- int get_surface_attribute(
483- std::shared_ptr<frontend::Session> const& session,
484- frontend::SurfaceId surface_id,
485- MirSurfaceAttrib attrib) override;
486-
487- frontend::SurfaceId create_surface(std::shared_ptr<frontend::Session> const& session, SurfaceCreationParameters const& params) override;
488- void destroy_surface(std::shared_ptr<frontend::Session> const& session, frontend::SurfaceId surface) override;
489+ void add_prompt_provider_for(std::shared_ptr<PromptSession> const& prompt_session,
490+ std::shared_ptr<Session> const& session) override;
491+ void stop_prompt_session(std::shared_ptr<PromptSession> const& prompt_session) override;
492
493 protected:
494 SessionManager(const SessionManager&) = delete;
495@@ -95,16 +72,10 @@
496 private:
497 std::shared_ptr<SurfaceCoordinator> const surface_coordinator;
498 std::shared_ptr<SessionContainer> const app_container;
499- std::shared_ptr<shell::FocusSetter> const focus_setter;
500 std::shared_ptr<SnapshotStrategy> const snapshot_strategy;
501 std::shared_ptr<SessionEventSink> const session_event_sink;
502 std::shared_ptr<SessionListener> const session_listener;
503 std::shared_ptr<PromptSessionManager> const prompt_session_manager;
504-
505- std::mutex mutex;
506- std::weak_ptr<Session> focus_application;
507-
508- void set_focus_to_locked(std::unique_lock<std::mutex> const& lock, std::shared_ptr<Session> const& next_focus);
509 };
510
511 }
512
513=== modified file 'src/server/shell/CMakeLists.txt'
514--- src/server/shell/CMakeLists.txt 2015-01-14 06:39:13 +0000
515+++ src/server/shell/CMakeLists.txt 2015-01-21 10:18:06 +0000
516@@ -5,6 +5,7 @@
517 default_placement_strategy.cpp
518 graphics_display_layout.cpp
519 default_configuration.cpp
520+ default_shell.cpp
521 session_coordinator_wrapper.cpp
522 surface_coordinator_wrapper.cpp
523 )
524
525=== modified file 'src/server/shell/default_configuration.cpp'
526--- src/server/shell/default_configuration.cpp 2015-01-14 06:39:13 +0000
527+++ src/server/shell/default_configuration.cpp 2015-01-21 10:18:06 +0000
528@@ -1,5 +1,5 @@
529 /*
530- * Copyright © 2013 Canonical Ltd.
531+ * Copyright © 2013-2015 Canonical Ltd.
532 *
533 * This program is free software: you can redistribute it and/or modify it
534 * under the terms of the GNU General Public License version 3,
535@@ -22,12 +22,36 @@
536
537 #include "default_placement_strategy.h"
538 #include "default_focus_mechanism.h"
539+#include "default_shell.h"
540 #include "graphics_display_layout.h"
541
542 namespace ms = mir::scene;
543 namespace msh = mir::shell;
544 namespace mf = mir::frontend;
545
546+auto mir::DefaultServerConfiguration::the_shell() -> std::shared_ptr<msh::DefaultShell>
547+{
548+ return default_shell([this]
549+ {
550+ return std::make_shared<msh::DefaultShell>(
551+ the_shell_focus_setter(),
552+ the_session_coordinator());
553+ });
554+}
555+
556+std::shared_ptr<mf::Shell>
557+mir::DefaultServerConfiguration::the_frontend_shell()
558+{
559+ return the_shell();
560+}
561+
562+
563+std::shared_ptr<msh::FocusController>
564+mir::DefaultServerConfiguration::the_focus_controller()
565+{
566+ return the_shell();
567+}
568+
569 std::shared_ptr<ms::PlacementStrategy>
570 mir::DefaultServerConfiguration::the_placement_strategy()
571 {
572
573=== added file 'src/server/shell/default_shell.cpp'
574--- src/server/shell/default_shell.cpp 1970-01-01 00:00:00 +0000
575+++ src/server/shell/default_shell.cpp 2015-01-21 10:18:06 +0000
576@@ -0,0 +1,178 @@
577+/*
578+ * Copyright © 2015 Canonical Ltd.
579+ *
580+ * This program is free software: you can redistribute it and/or modify it
581+ * under the terms of the GNU General Public License version 3,
582+ * as published by the Free Software Foundation.
583+ *
584+ * This program is distributed in the hope that it will be useful,
585+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
586+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
587+ * GNU General Public License for more details.
588+ *
589+ * You should have received a copy of the GNU General Public License
590+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
591+ *
592+ * Authored By: Alan Griffiths <alan@octopull.co.uk>
593+ */
594+
595+#include "default_shell.h"
596+#include "mir/shell/focus_setter.h"
597+#include "mir/scene/prompt_session.h"
598+#include "mir/scene/session_coordinator.h"
599+#include "mir/scene/session.h"
600+#include "mir/scene/surface.h"
601+
602+#include <boost/throw_exception.hpp>
603+
604+#include <stdexcept>
605+
606+namespace mf = mir::frontend;
607+namespace ms = mir::scene;
608+namespace msh = mir::shell;
609+
610+msh::DefaultShell::DefaultShell(
611+ std::shared_ptr<FocusSetter> const& focus_setter,
612+ std::shared_ptr<scene::SessionCoordinator> const& session_coordinator) :
613+ focus_setter(focus_setter),
614+ session_coordinator(session_coordinator)
615+{
616+}
617+
618+std::shared_ptr<mf::Session> msh::DefaultShell::open_session(
619+ pid_t client_pid,
620+ std::string const& name,
621+ std::shared_ptr<mf::EventSink> const& sink)
622+{
623+ auto const new_session = session_coordinator->open_session(client_pid, name, sink);
624+ set_focus_to(new_session);
625+ return new_session;
626+}
627+
628+void msh::DefaultShell::close_session(
629+ std::shared_ptr<mf::Session> const& session)
630+{
631+ session_coordinator->close_session(std::dynamic_pointer_cast<ms::Session>(session));
632+
633+ std::unique_lock<std::mutex> lock(mutex);
634+ set_focus_to_locked(lock, session_coordinator->successor_of(std::shared_ptr<ms::Session>()));
635+}
636+
637+void msh::DefaultShell::focus_next()
638+{
639+ std::unique_lock<std::mutex> lock(mutex);
640+ auto focus = focus_application.lock();
641+
642+ focus = session_coordinator->successor_of(focus);
643+
644+ set_focus_to_locked(lock, focus);
645+}
646+
647+std::weak_ptr<ms::Session> msh::DefaultShell::focussed_application() const
648+{
649+ return focus_application;
650+}
651+
652+void msh::DefaultShell::set_focus_to(
653+ std::shared_ptr<scene::Session> const& focus)
654+{
655+ std::unique_lock<std::mutex> lg(mutex);
656+ set_focus_to_locked(lg, focus);
657+}
658+
659+void msh::DefaultShell::handle_surface_created(
660+ std::shared_ptr<mf::Session> const& session)
661+{
662+ auto const focus = std::dynamic_pointer_cast<ms::Session>(session);
663+ set_focus_to(focus);
664+}
665+
666+std::shared_ptr<mf::PromptSession> msh::DefaultShell::start_prompt_session_for(
667+ std::shared_ptr<mf::Session> const& session,
668+ scene::PromptSessionCreationParameters const& params)
669+{
670+ auto const scene_session = std::dynamic_pointer_cast<ms::Session>(session);
671+
672+ return session_coordinator->start_prompt_session_for(scene_session, params);
673+}
674+
675+void msh::DefaultShell::add_prompt_provider_for(
676+ std::shared_ptr<mf::PromptSession> const& prompt_session,
677+ std::shared_ptr<mf::Session> const& session)
678+{
679+ auto const scene_prompt_session = std::dynamic_pointer_cast<ms::PromptSession>(prompt_session);
680+ auto const scene_session = std::dynamic_pointer_cast<ms::Session>(session);
681+ session_coordinator->add_prompt_provider_for(scene_prompt_session, scene_session);
682+}
683+
684+void msh::DefaultShell::stop_prompt_session(std::shared_ptr<mf::PromptSession> const& prompt_session)
685+{
686+ auto const scene_prompt_session = std::dynamic_pointer_cast<ms::PromptSession>(prompt_session);
687+ session_coordinator->stop_prompt_session(scene_prompt_session);
688+}
689+
690+mf::SurfaceId msh::DefaultShell::create_surface(std::shared_ptr<mf::Session> const& session, ms::SurfaceCreationParameters const& params)
691+{
692+ auto const scene_session = std::dynamic_pointer_cast<ms::Session>(session);
693+ auto const result = scene_session->create_surface(params);
694+ return result;
695+}
696+
697+void msh::DefaultShell::destroy_surface(std::shared_ptr<mf::Session> const& session, mf::SurfaceId surface)
698+{
699+ auto const scene_session = std::dynamic_pointer_cast<ms::Session>(session);
700+ scene_session->destroy_surface(surface);
701+}
702+
703+int msh::DefaultShell::set_surface_attribute(
704+ std::shared_ptr<mf::Session> const& session,
705+ mf::SurfaceId surface_id,
706+ MirSurfaceAttrib attrib,
707+ int value)
708+{
709+ // TODO this downcasting is clunky, but is temporary wiring of the new interaction route to the old implementation
710+ if (!session)
711+ BOOST_THROW_EXCEPTION(std::logic_error("invalid session"));
712+
713+ auto const surface = std::dynamic_pointer_cast<ms::Surface>(session->get_surface(surface_id));
714+
715+ if (!surface)
716+ BOOST_THROW_EXCEPTION(std::logic_error("invalid surface id"));
717+
718+ return surface->configure(attrib, value);
719+}
720+
721+int msh::DefaultShell::get_surface_attribute(
722+ std::shared_ptr<mf::Session> const& session,
723+ mf::SurfaceId surface_id,
724+ MirSurfaceAttrib attrib)
725+{
726+ // TODO this downcasting is clunky, but is temporary wiring of the new interaction route to the old implementation
727+ if (!session)
728+ BOOST_THROW_EXCEPTION(std::logic_error("invalid session"));
729+
730+ auto const surface = std::dynamic_pointer_cast<ms::Surface>(session->get_surface(surface_id));
731+
732+ if (!surface)
733+ BOOST_THROW_EXCEPTION(std::logic_error("invalid surface id"));
734+
735+ return surface->query(attrib);
736+}
737+
738+
739+inline void msh::DefaultShell::set_focus_to_locked(std::unique_lock<std::mutex> const&, std::shared_ptr<ms::Session> const& session)
740+{
741+ auto old_focus = focus_application.lock();
742+
743+ focus_setter->set_focus_to(session);
744+ focus_application = session;
745+
746+ if (session)
747+ {
748+ session_coordinator->set_focus_to(session);
749+ }
750+ else
751+ {
752+ session_coordinator->unset_focus();
753+ }
754+}
755
756=== added file 'src/server/shell/default_shell.h'
757--- src/server/shell/default_shell.h 1970-01-01 00:00:00 +0000
758+++ src/server/shell/default_shell.h 2015-01-21 10:18:06 +0000
759@@ -0,0 +1,94 @@
760+/*
761+ * Copyright © 2015 Canonical Ltd.
762+ *
763+ * This program is free software: you can redistribute it and/or modify it
764+ * under the terms of the GNU General Public License version 3,
765+ * as published by the Free Software Foundation.
766+ *
767+ * This program is distributed in the hope that it will be useful,
768+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
769+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
770+ * GNU General Public License for more details.
771+ *
772+ * You should have received a copy of the GNU General Public License
773+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
774+ *
775+ * Authored By: Alan Griffiths <alan@octopull.co.uk>
776+ */
777+
778+#ifndef MIR_SHELL_DEFAULT_SHELL_H_
779+#define MIR_SHELL_DEFAULT_SHELL_H_
780+
781+#include "mir/frontend/shell.h"
782+#include "mir/shell/focus_controller.h"
783+
784+#include <mutex>
785+
786+namespace mir
787+{
788+namespace scene { class SessionCoordinator; }
789+
790+namespace shell
791+{
792+class FocusSetter;
793+
794+class DefaultShell : public frontend::Shell, public FocusController
795+{
796+public:
797+ DefaultShell(
798+ std::shared_ptr<FocusSetter> const& focus_setter,
799+ std::shared_ptr<scene::SessionCoordinator> const& session_coordinator);
800+
801+ void focus_next() override;
802+
803+ std::weak_ptr<scene::Session> focussed_application() const override;
804+
805+ void set_focus_to(std::shared_ptr<scene::Session> const& focus) override;
806+
807+ virtual std::shared_ptr<frontend::Session> open_session(
808+ pid_t client_pid,
809+ std::string const& name,
810+ std::shared_ptr<frontend::EventSink> const& sink) override;
811+
812+ virtual void close_session(std::shared_ptr<frontend::Session> const& session) override;
813+
814+ void handle_surface_created(std::shared_ptr<frontend::Session> const& session) override;
815+
816+ std::shared_ptr<frontend::PromptSession> start_prompt_session_for(
817+ std::shared_ptr<frontend::Session> const& session,
818+ scene::PromptSessionCreationParameters const& params) override;
819+
820+ void add_prompt_provider_for(
821+ std::shared_ptr<frontend::PromptSession> const& prompt_session,
822+ std::shared_ptr<frontend::Session> const& session) override;
823+
824+ void stop_prompt_session(std::shared_ptr<frontend::PromptSession> const& prompt_session) override;
825+
826+ frontend::SurfaceId create_surface(std::shared_ptr<frontend::Session> const& session, scene::SurfaceCreationParameters const& params) override;
827+
828+ void destroy_surface(std::shared_ptr<frontend::Session> const& session, frontend::SurfaceId surface) override;
829+
830+ int set_surface_attribute(
831+ std::shared_ptr<frontend::Session> const& session,
832+ frontend::SurfaceId surface_id,
833+ MirSurfaceAttrib attrib,
834+ int value) override;
835+
836+ int get_surface_attribute(
837+ std::shared_ptr<frontend::Session> const& session,
838+ frontend::SurfaceId surface_id,
839+ MirSurfaceAttrib attrib) override;
840+
841+private:
842+ std::shared_ptr<FocusSetter> const focus_setter;
843+ std::shared_ptr<scene::SessionCoordinator> const session_coordinator;
844+
845+ std::mutex mutex;
846+ std::weak_ptr<scene::Session> focus_application;
847+
848+ void set_focus_to_locked(std::unique_lock<std::mutex> const& lock, std::shared_ptr<scene::Session> const& next_focus);
849+};
850+}
851+}
852+
853+#endif /* MIR_SHELL_DEFAULT_SHELL_H_ */
854
855=== modified file 'src/server/shell/session_coordinator_wrapper.cpp'
856--- src/server/shell/session_coordinator_wrapper.cpp 2015-01-19 11:36:40 +0000
857+++ src/server/shell/session_coordinator_wrapper.cpp 2015-01-21 10:18:06 +0000
858@@ -29,7 +29,7 @@
859 }
860
861
862-std::shared_ptr<mf::Session> msh::SessionCoordinatorWrapper::open_session(
863+std::shared_ptr<ms::Session> msh::SessionCoordinatorWrapper::open_session(
864 pid_t client_pid,
865 std::string const& name,
866 std::shared_ptr<mf::EventSink> const& sink)
867@@ -38,19 +38,15 @@
868 }
869
870 void msh::SessionCoordinatorWrapper::close_session(
871- std::shared_ptr<mf::Session> const& session)
872+ std::shared_ptr<ms::Session> const& session)
873 {
874 wrapped->close_session(session);
875 }
876
877-void msh::SessionCoordinatorWrapper::focus_next()
878-{
879- wrapped->focus_next();
880-}
881-
882-std::weak_ptr<ms::Session> msh::SessionCoordinatorWrapper::focussed_application() const
883-{
884- return wrapped->focussed_application();
885+std::shared_ptr<ms::Session> msh::SessionCoordinatorWrapper::successor_of(
886+ std::shared_ptr<ms::Session> const& session) const
887+{
888+ return wrapped->successor_of(session);
889 }
890
891 void msh::SessionCoordinatorWrapper::set_focus_to(
892@@ -59,54 +55,26 @@
893 wrapped->set_focus_to(focus);
894 }
895
896-void msh::SessionCoordinatorWrapper::handle_surface_created(
897- std::shared_ptr<mf::Session> const& session)
898+void msh::SessionCoordinatorWrapper::unset_focus()
899 {
900- wrapped->handle_surface_created(session);
901+ wrapped->unset_focus();
902 }
903
904-std::shared_ptr<mf::PromptSession> msh::SessionCoordinatorWrapper::start_prompt_session_for(
905- std::shared_ptr<mf::Session> const& session,
906+std::shared_ptr<ms::PromptSession> msh::SessionCoordinatorWrapper::start_prompt_session_for(
907+ std::shared_ptr<ms::Session> const& session,
908 scene::PromptSessionCreationParameters const& params)
909 {
910 return wrapped->start_prompt_session_for(session, params);
911 }
912
913 void msh::SessionCoordinatorWrapper::add_prompt_provider_for(
914- std::shared_ptr<mf::PromptSession> const& prompt_session,
915- std::shared_ptr<mf::Session> const& session)
916+ std::shared_ptr<ms::PromptSession> const& prompt_session,
917+ std::shared_ptr<ms::Session> const& session)
918 {
919 wrapped->add_prompt_provider_for(prompt_session, session);
920 }
921
922-void msh::SessionCoordinatorWrapper::stop_prompt_session(std::shared_ptr<mf::PromptSession> const& prompt_session)
923+void msh::SessionCoordinatorWrapper::stop_prompt_session(std::shared_ptr<ms::PromptSession> const& prompt_session)
924 {
925 wrapped->stop_prompt_session(prompt_session);
926 }
927-
928-mf::SurfaceId msh::SessionCoordinatorWrapper::create_surface(std::shared_ptr<mf::Session> const& session, ms::SurfaceCreationParameters const& params)
929-{
930- return wrapped->create_surface(session, params);
931-}
932-
933-void msh::SessionCoordinatorWrapper::destroy_surface(std::shared_ptr<mf::Session> const& session, mf::SurfaceId surface)
934-{
935- wrapped->destroy_surface(session, surface);
936-}
937-
938-int msh::SessionCoordinatorWrapper::set_surface_attribute(
939- std::shared_ptr<mf::Session> const& session,
940- mf::SurfaceId surface_id,
941- MirSurfaceAttrib attrib,
942- int value)
943-{
944- return wrapped->set_surface_attribute(session, surface_id, attrib, value);
945-}
946-
947-int msh::SessionCoordinatorWrapper::get_surface_attribute(
948- std::shared_ptr<mf::Session> const& session,
949- mf::SurfaceId surface_id,
950- MirSurfaceAttrib attrib)
951-{
952- return wrapped->get_surface_attribute(session, surface_id, attrib);
953-}
954
955=== modified file 'src/server/symbols.map'
956--- src/server/symbols.map 2015-01-21 08:38:18 +0000
957+++ src/server/symbols.map 2015-01-21 10:18:06 +0000
958@@ -500,6 +500,8 @@
959 mir::shell::SessionCoordinatorWrapper::set_surface_attribute*;
960 mir::shell::SessionCoordinatorWrapper::start_prompt_session_for*;
961 mir::shell::SessionCoordinatorWrapper::stop_prompt_session*;
962+ mir::shell::SessionCoordinatorWrapper::successor_of*;
963+ mir::shell::SessionCoordinatorWrapper::unset_focus*;
964 mir::shell::SurfaceCoordinatorWrapper::add_surface*;
965 mir::shell::SurfaceCoordinatorWrapper::raise*;
966 mir::shell::SurfaceCoordinatorWrapper::remove_surface*;
967
968=== modified file 'tests/acceptance-tests/server_configuration_wrapping.cpp'
969--- tests/acceptance-tests/server_configuration_wrapping.cpp 2014-11-06 03:56:24 +0000
970+++ tests/acceptance-tests/server_configuration_wrapping.cpp 2015-01-21 10:18:06 +0000
971@@ -41,7 +41,7 @@
972 {
973 using msh::SessionCoordinatorWrapper::SessionCoordinatorWrapper;
974
975- MOCK_METHOD0(focus_next, void());
976+ MOCK_METHOD0(unset_focus, void());
977 };
978
979 struct ServerConfigurationWrapping : mir_test_framework::HeadlessTest
980@@ -102,8 +102,8 @@
981 {
982 auto const my_session_coordinator = std::dynamic_pointer_cast<MySessionCoordinator>(session_coordinator);
983
984- EXPECT_CALL(*my_session_coordinator, focus_next()).Times(1);
985- session_coordinator->focus_next();
986+ EXPECT_CALL(*my_session_coordinator, unset_focus()).Times(1);
987+ session_coordinator->unset_focus();
988 }
989
990 TEST_F(ServerConfigurationWrapping, returns_same_session_coordinator_from_cache)
991
992=== modified file 'tests/acceptance-tests/test_client_focus_notification.cpp'
993--- tests/acceptance-tests/test_client_focus_notification.cpp 2015-01-14 06:39:13 +0000
994+++ tests/acceptance-tests/test_client_focus_notification.cpp 2015-01-21 10:18:06 +0000
995@@ -97,6 +97,7 @@
996 {
997 run_in_client([&]
998 {
999+ InSequence s;
1000 EXPECT_CALL(observer, see(Pointee(mt::SurfaceEvent(mir_surface_attrib_focus, mir_surface_focused)))).Times(1)
1001 .WillOnce(mt::WakeUp(&all_events_received));
1002 // We may not see mir_surface_unfocused before connection closes
1003
1004=== modified file 'tests/acceptance-tests/test_prompt_session_client_api.cpp'
1005--- tests/acceptance-tests/test_prompt_session_client_api.cpp 2015-01-14 06:39:13 +0000
1006+++ tests/acceptance-tests/test_prompt_session_client_api.cpp 2015-01-21 10:18:06 +0000
1007@@ -78,7 +78,7 @@
1008 pid_t client_pid,
1009 std::string const& name,
1010 std::shared_ptr<mf::EventSink> const& sink)
1011- -> std::shared_ptr<mf::Session> override
1012+ -> std::shared_ptr<ms::Session> override
1013 {
1014 auto const override_pid = (next != pids.end()) ? *next++ : client_pid;
1015
1016
1017=== modified file 'tests/integration-tests/CMakeLists.txt'
1018--- tests/integration-tests/CMakeLists.txt 2015-01-14 06:39:13 +0000
1019+++ tests/integration-tests/CMakeLists.txt 2015-01-21 10:18:06 +0000
1020@@ -34,7 +34,7 @@
1021 test_swapinterval.cpp
1022 test_server_client_types.cpp
1023 test_server_shutdown.cpp
1024- test_session_manager.cpp
1025+ test_default_shell.cpp
1026 test_session.cpp
1027 session_management.cpp
1028 surface_composition.cpp
1029
1030=== renamed file 'tests/integration-tests/test_session_manager.cpp' => 'tests/integration-tests/test_default_shell.cpp'
1031--- tests/integration-tests/test_session_manager.cpp 2015-01-14 06:39:13 +0000
1032+++ tests/integration-tests/test_default_shell.cpp 2015-01-21 10:18:06 +0000
1033@@ -1,5 +1,5 @@
1034 /*
1035- * Copyright © 2012 Canonical Ltd.
1036+ * Copyright © 2012-2015 Canonical Ltd.
1037 *
1038 * This program is free software: you can redistribute it and/or modify
1039 * it under the terms of the GNU General Public License version 3 as
1040@@ -16,6 +16,7 @@
1041 * Authored by: Thomas Voss <thomas.voss@canonical.com>
1042 */
1043
1044+#include "src/server/shell/default_shell.h"
1045 #include "src/server/scene/session_manager.h"
1046 #include "mir/scene/session.h"
1047 #include "mir/shell/focus_setter.h"
1048@@ -47,40 +48,36 @@
1049 namespace
1050 {
1051
1052-struct TestSessionManagerAndFocusSelectionStrategy : public testing::Test
1053+struct TestDefaultShellAndFocusSelectionStrategy : public testing::Test
1054 {
1055- TestSessionManagerAndFocusSelectionStrategy()
1056- : session_manager(
1057- mt::fake_shared(surface_coordinator),
1058- mt::fake_shared(container),
1059- mt::fake_shared(focus_setter),
1060- std::make_shared<mtd::NullSnapshotStrategy>(),
1061- std::make_shared<mtd::NullSessionEventSink>(),
1062- mt::fake_shared(session_listener),
1063- std::make_shared<mtd::NullPromptSessionManager>())
1064- {
1065-
1066- }
1067-
1068 mtd::MockSurfaceCoordinator surface_coordinator; // TODO this isn't used as a mock
1069 ms::DefaultSessionContainer container;
1070 mtd::MockFocusSetter focus_setter;
1071 std::shared_ptr<mf::Session> new_session;
1072 ms::NullSessionListener session_listener;
1073- ms::SessionManager session_manager;
1074+ ms::SessionManager session_manager
1075+ {
1076+ mt::fake_shared(surface_coordinator),
1077+ mt::fake_shared(container),
1078+ std::make_shared<mtd::NullSnapshotStrategy>(),
1079+ std::make_shared<mtd::NullSessionEventSink>(),
1080+ mt::fake_shared(session_listener),
1081+ std::make_shared<mtd::NullPromptSessionManager>()
1082+ };
1083+
1084+ msh::DefaultShell shell{mt::fake_shared(focus_setter), mt::fake_shared(session_manager)};
1085 };
1086-
1087 }
1088
1089-TEST_F(TestSessionManagerAndFocusSelectionStrategy, cycle_focus)
1090+TEST_F(TestDefaultShellAndFocusSelectionStrategy, cycle_focus)
1091 {
1092 using namespace ::testing;
1093
1094 EXPECT_CALL(focus_setter, set_focus_to(_)).Times(3);
1095
1096- auto session1 = session_manager.open_session(__LINE__, "Visual Basic Studio", std::make_shared<mtd::NullEventSink>());
1097- auto session2 = session_manager.open_session(__LINE__, "Microsoft Access", std::make_shared<mtd::NullEventSink>());
1098- auto session3 = session_manager.open_session(__LINE__, "WordPerfect", std::make_shared<mtd::NullEventSink>());
1099+ auto session1 = shell.open_session(__LINE__, "Visual Basic Studio", std::make_shared<mtd::NullEventSink>());
1100+ auto session2 = shell.open_session(__LINE__, "Microsoft Access", std::make_shared<mtd::NullEventSink>());
1101+ auto session3 = shell.open_session(__LINE__, "WordPerfect", std::make_shared<mtd::NullEventSink>());
1102
1103 Mock::VerifyAndClearExpectations(&focus_setter);
1104
1105@@ -91,9 +88,9 @@
1106 EXPECT_CALL(focus_setter, set_focus_to(Eq(session3))).Times(1);
1107 }
1108
1109- session_manager.focus_next();
1110- session_manager.focus_next();
1111- session_manager.focus_next();
1112+ shell.focus_next();
1113+ shell.focus_next();
1114+ shell.focus_next();
1115
1116 Mock::VerifyAndClearExpectations(&focus_setter);
1117
1118@@ -101,15 +98,15 @@
1119 EXPECT_CALL(focus_setter, set_focus_to(_)).Times(AtLeast(0));
1120 }
1121
1122-TEST_F(TestSessionManagerAndFocusSelectionStrategy, closing_applications_transfers_focus)
1123+TEST_F(TestDefaultShellAndFocusSelectionStrategy, closing_applications_transfers_focus)
1124 {
1125 using namespace ::testing;
1126
1127 EXPECT_CALL(focus_setter, set_focus_to(_)).Times(3);
1128
1129- auto session1 = session_manager.open_session(__LINE__, "Visual Basic Studio", std::make_shared<mtd::NullEventSink>());
1130- auto session2 = session_manager.open_session(__LINE__, "Microsoft Access", std::make_shared<mtd::NullEventSink>());
1131- auto session3 = session_manager.open_session(__LINE__, "WordPerfect", std::make_shared<mtd::NullEventSink>());
1132+ auto session1 = shell.open_session(__LINE__, "Visual Basic Studio", std::make_shared<mtd::NullEventSink>());
1133+ auto session2 = shell.open_session(__LINE__, "Microsoft Access", std::make_shared<mtd::NullEventSink>());
1134+ auto session3 = shell.open_session(__LINE__, "WordPerfect", std::make_shared<mtd::NullEventSink>());
1135
1136 Mock::VerifyAndClearExpectations(&focus_setter);
1137
1138@@ -119,8 +116,8 @@
1139 EXPECT_CALL(focus_setter, set_focus_to(Eq(session1))).Times(1);
1140 }
1141
1142- session_manager.close_session(session3);
1143- session_manager.close_session(session2);
1144+ shell.close_session(session3);
1145+ shell.close_session(session2);
1146
1147 Mock::VerifyAndClearExpectations(&focus_setter);
1148
1149
1150=== modified file 'tests/unit-tests/scene/test_session_manager.cpp'
1151--- tests/unit-tests/scene/test_session_manager.cpp 2015-01-19 11:36:40 +0000
1152+++ tests/unit-tests/scene/test_session_manager.cpp 2015-01-21 10:18:06 +0000
1153@@ -1,5 +1,5 @@
1154 /*
1155- * Copyright © 2012-2014 Canonical Ltd.
1156+ * Copyright © 2012-2015 Canonical Ltd.
1157 *
1158 * This program is free software: you can redistribute it and/or modify
1159 * it under the terms of the GNU General Public License version 3 as
1160@@ -33,7 +33,6 @@
1161 #include "mir_test/fake_shared.h"
1162 #include "mir_test_doubles/mock_buffer_stream.h"
1163 #include "mir_test_doubles/mock_surface_coordinator.h"
1164-#include "mir_test_doubles/mock_focus_setter.h"
1165 #include "mir_test_doubles/mock_session_listener.h"
1166 #include "mir_test_doubles/stub_buffer_stream.h"
1167 #include "mir_test_doubles/null_snapshot_strategy.h"
1168@@ -81,7 +80,6 @@
1169 SessionManagerSetup()
1170 : session_manager(mt::fake_shared(surface_coordinator),
1171 mt::fake_shared(container),
1172- mt::fake_shared(focus_setter),
1173 std::make_shared<mtd::NullSnapshotStrategy>(),
1174 std::make_shared<mtd::NullSessionEventSink>(),
1175 mt::fake_shared(session_listener),
1176@@ -104,7 +102,6 @@
1177 mir::report::null_scene_report());
1178 mtd::MockSurfaceCoordinator surface_coordinator;
1179 testing::NiceMock<MockSessionContainer> container; // Inelegant but some tests need a stub
1180- testing::NiceMock<mtd::MockFocusSetter> focus_setter; // Inelegant but some tests need a stub
1181 ms::NullSessionListener session_listener;
1182
1183 ms::SessionManager session_manager;
1184@@ -118,8 +115,6 @@
1185
1186 EXPECT_CALL(container, insert_session(_)).Times(1);
1187 EXPECT_CALL(container, remove_session(_)).Times(1);
1188- EXPECT_CALL(focus_setter, set_focus_to(_));
1189- EXPECT_CALL(focus_setter, set_focus_to(std::shared_ptr<ms::Session>())).Times(1);
1190
1191 auto session = session_manager.open_session(__LINE__, "Visual Basic Studio", std::shared_ptr<mf::EventSink>());
1192 session_manager.close_session(session);
1193@@ -137,36 +132,19 @@
1194 EXPECT_CALL(container, insert_session(_)).Times(1);
1195 EXPECT_CALL(container, remove_session(_)).Times(1);
1196
1197- EXPECT_CALL(focus_setter, set_focus_to(_)).Times(1);
1198- EXPECT_CALL(focus_setter, set_focus_to(std::shared_ptr<ms::Session>())).Times(1);
1199-
1200 auto session = session_manager.open_session(__LINE__, "Visual Basic Studio", std::shared_ptr<mf::EventSink>());
1201- session_manager.create_surface(session, ms::a_surface().of_size(geom::Size{geom::Width{1024}, geom::Height{768}}));
1202+ session->create_surface(ms::a_surface().of_size(geom::Size{geom::Width{1024}, geom::Height{768}}));
1203
1204 session_manager.close_session(session);
1205 }
1206
1207-TEST_F(SessionManagerSetup, new_applications_receive_focus)
1208-{
1209- using namespace ::testing;
1210- std::shared_ptr<ms::Session> new_session;
1211-
1212- EXPECT_CALL(container, insert_session(_)).Times(1);
1213- EXPECT_CALL(focus_setter, set_focus_to(_)).WillOnce(SaveArg<0>(&new_session));
1214-
1215- auto session = session_manager.open_session(__LINE__, "Visual Basic Studio", std::shared_ptr<mf::EventSink>());
1216- EXPECT_EQ(session, new_session);
1217-}
1218-
1219 namespace
1220 {
1221-
1222 struct SessionManagerSessionListenerSetup : public testing::Test
1223 {
1224 SessionManagerSessionListenerSetup()
1225 : session_manager(mt::fake_shared(surface_coordinator),
1226 mt::fake_shared(container),
1227- mt::fake_shared(focus_setter),
1228 std::make_shared<mtd::NullSnapshotStrategy>(),
1229 std::make_shared<mtd::NullSessionEventSink>(),
1230 mt::fake_shared(session_listener),
1231@@ -178,21 +156,18 @@
1232
1233 mtd::MockSurfaceCoordinator surface_coordinator;
1234 testing::NiceMock<MockSessionContainer> container; // Inelegant but some tests need a stub
1235- testing::NiceMock<mtd::MockFocusSetter> focus_setter; // Inelegant but some tests need a stub
1236 testing::NiceMock<mtd::MockSessionListener> session_listener;
1237
1238 ms::SessionManager session_manager;
1239 };
1240 }
1241
1242-TEST_F(SessionManagerSessionListenerSetup, session_listener_is_notified_of_lifecycle_and_focus)
1243+TEST_F(SessionManagerSessionListenerSetup, session_listener_is_notified_of_lifecycle)
1244 {
1245 using namespace ::testing;
1246
1247 EXPECT_CALL(session_listener, starting(_)).Times(1);
1248- EXPECT_CALL(session_listener, focused(_)).Times(1);
1249 EXPECT_CALL(session_listener, stopping(_)).Times(1);
1250- EXPECT_CALL(session_listener, unfocused()).Times(1);
1251
1252 auto session = session_manager.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
1253 session_manager.close_session(session);
1254@@ -200,17 +175,9 @@
1255
1256 namespace
1257 {
1258-
1259 struct SessionManagerSessionEventsSetup : public testing::Test
1260 {
1261- SessionManagerSessionEventsSetup()
1262- : session_manager(mt::fake_shared(surface_coordinator),
1263- mt::fake_shared(container),
1264- mt::fake_shared(focus_setter),
1265- std::make_shared<mtd::NullSnapshotStrategy>(),
1266- mt::fake_shared(session_event_sink),
1267- std::make_shared<ms::NullSessionListener>(),
1268- std::make_shared<mtd::NullPromptSessionManager>())
1269+ void SetUp() override
1270 {
1271 using namespace ::testing;
1272 ON_CALL(container, successor_of(_)).WillByDefault(Return((std::shared_ptr<ms::Session>())));
1273@@ -218,22 +185,109 @@
1274
1275 mtd::MockSurfaceCoordinator surface_coordinator;
1276 testing::NiceMock<MockSessionContainer> container; // Inelegant but some tests need a stub
1277- testing::NiceMock<mtd::MockFocusSetter> focus_setter; // Inelegant but some tests need a stub
1278 MockSessionEventSink session_event_sink;
1279-
1280- ms::SessionManager session_manager;
1281-};
1282-
1283-}
1284-
1285-TEST_F(SessionManagerSessionEventsSetup, session_event_sink_is_notified_of_lifecycle_and_focus)
1286+ testing::NiceMock<mtd::MockSessionListener> session_listener;
1287+
1288+ ms::SessionManager session_manager{
1289+ mt::fake_shared(surface_coordinator),
1290+ mt::fake_shared(container),
1291+ std::make_shared<mtd::NullSnapshotStrategy>(),
1292+ mt::fake_shared(session_event_sink),
1293+ mt::fake_shared(session_listener),
1294+ std::make_shared<mtd::NullPromptSessionManager>()};
1295+};
1296+}
1297+
1298+TEST_F(SessionManagerSessionEventsSetup, session_event_sink_is_notified_of_lifecycle)
1299+{
1300+ using namespace ::testing;
1301+
1302+ auto session = session_manager.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
1303+ auto session1 = session_manager.open_session(__LINE__, "Bla", std::shared_ptr<mf::EventSink>());
1304+
1305+ Mock::VerifyAndClearExpectations(&session_event_sink);
1306+
1307+ EXPECT_CALL(session_event_sink, handle_focus_change(_)).Times(AnyNumber());
1308+ EXPECT_CALL(session_event_sink, handle_no_focus()).Times(AnyNumber());
1309+
1310+ InSequence s;
1311+ EXPECT_CALL(session_event_sink, handle_session_stopping(_)).Times(1);
1312+ EXPECT_CALL(session_event_sink, handle_session_stopping(_)).Times(1);
1313+
1314+ session_manager.close_session(session1);
1315+ session_manager.close_session(session);
1316+}
1317+
1318+// TODO the following tests replace unit tests of "window management" functions
1319+// TODO that were implemented by SessionManager.
1320+// TODO They are now actually integration tests of DefaultShell + SessionManager
1321+// TODO but as I'm reworking that interaction and they use mocks that only exist
1322+// TODO in this file (e.g. MockSessionContainer) I've left them here temporarily.
1323+#include "src/server/shell/default_shell.h"
1324+#include "src/server/shell/default_focus_mechanism.h"
1325+#include "mir_test_doubles/mock_focus_setter.h"
1326+
1327+namespace msh = mir::shell;
1328+using namespace ::testing;
1329+
1330+namespace
1331+{
1332+struct DefaultShell : Test
1333+{
1334+ mtd::MockSurfaceCoordinator surface_coordinator;
1335+ NiceMock<MockSessionContainer> container;
1336+ NiceMock<MockSessionEventSink> session_event_sink;
1337+ NiceMock<mtd::MockSessionListener> session_listener;
1338+
1339+ ms::SessionManager session_manager{
1340+ mt::fake_shared(surface_coordinator),
1341+ mt::fake_shared(container),
1342+ std::make_shared<mtd::NullSnapshotStrategy>(),
1343+ mt::fake_shared(session_event_sink),
1344+ mt::fake_shared(session_listener),
1345+ std::make_shared<mtd::NullPromptSessionManager>()};
1346+
1347+ NiceMock<mtd::MockFocusSetter> focus_setter;
1348+ msh::DefaultShell shell{mt::fake_shared(focus_setter), mt::fake_shared(session_manager)};
1349+
1350+ void SetUp() override
1351+ {
1352+ ON_CALL(container, successor_of(_)).WillByDefault(Return((std::shared_ptr<ms::Session>())));
1353+ }
1354+};
1355+}
1356+
1357+TEST_F(DefaultShell, new_applications_receive_focus)
1358+{
1359+ using namespace ::testing;
1360+ std::shared_ptr<ms::Session> new_session;
1361+
1362+ EXPECT_CALL(container, insert_session(_)).Times(1);
1363+ EXPECT_CALL(focus_setter, set_focus_to(_)).WillOnce(SaveArg<0>(&new_session));
1364+
1365+ auto session = shell.open_session(__LINE__, "Visual Basic Studio", std::shared_ptr<mf::EventSink>());
1366+ EXPECT_EQ(session, new_session);
1367+}
1368+
1369+TEST_F(DefaultShell, session_listener_is_notified_of_focus)
1370+{
1371+ using namespace ::testing;
1372+
1373+ EXPECT_CALL(session_listener, focused(_)).Times(1);
1374+ EXPECT_CALL(session_listener, unfocused()).Times(1);
1375+
1376+ auto session = shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
1377+ shell.close_session(session);
1378+}
1379+
1380+TEST_F(DefaultShell, session_event_sink_is_notified_of_focus)
1381 {
1382 using namespace ::testing;
1383
1384 EXPECT_CALL(session_event_sink, handle_focus_change(_)).Times(2);
1385
1386- auto session = session_manager.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
1387- auto session1 = session_manager.open_session(__LINE__, "Bla", std::shared_ptr<mf::EventSink>());
1388+ auto session = shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
1389+ auto session1 = shell.open_session(__LINE__, "Bla", std::shared_ptr<mf::EventSink>());
1390
1391 Mock::VerifyAndClearExpectations(&session_event_sink);
1392
1393@@ -247,6 +301,6 @@
1394 WillOnce(Return(std::shared_ptr<ms::Session>()));
1395 EXPECT_CALL(session_event_sink, handle_no_focus()).Times(1);
1396
1397- session_manager.close_session(session1);
1398- session_manager.close_session(session);
1399+ shell.close_session(session1);
1400+ shell.close_session(session);
1401 }

Subscribers

People subscribed via source and target branches