Mir

Merge lp:~robertcarr/mir/reflow-input-focus-selection into lp:~mir-team/mir/trunk

Proposed by Robert Carr
Status: Merged
Approved by: Robert Carr
Approved revision: no longer in the source branch.
Merged at revision: 619
Proposed branch: lp:~robertcarr/mir/reflow-input-focus-selection
Merge into: lp:~mir-team/mir/trunk
Diff against target: 2052 lines (+739/-324)
38 files modified
include/server/mir/default_server_configuration.h (+3/-3)
include/server/mir/input/input_manager.h (+0/-1)
include/server/mir/input/null_input_manager.h (+0/-5)
include/server/mir/input/null_input_target_listener.h (+26/-11)
include/server/mir/shell/application_session.h (+4/-1)
include/server/mir/shell/input_focus_selector.h (+0/-52)
include/server/mir/shell/input_target_listener.h (+59/-0)
include/server/mir/shell/session_manager.h (+5/-2)
include/server/mir/shell/single_visibility_focus_mechanism.h (+1/-4)
include/test/mir_test_doubles/mock_input_focus_selector.h (+0/-40)
include/test/mir_test_doubles/mock_input_target_listener.h (+49/-0)
include/test/mir_test_doubles/stub_input_target_listener.h (+59/-0)
include/test/mir_test_framework/testing_server_configuration.h (+1/-1)
src/server/default_server_configuration.cpp (+8/-8)
src/server/display_server.cpp (+1/-1)
src/server/input/android/android_dispatcher_controller.cpp (+73/-23)
src/server/input/android/android_dispatcher_controller.h (+19/-6)
src/server/input/android/default_android_input_configuration.cpp (+6/-1)
src/server/input/android/default_android_input_configuration.h (+2/-0)
src/server/input/android/event_filter_dispatcher_policy.cpp (+4/-3)
src/server/input/android/event_filter_dispatcher_policy.h (+2/-1)
src/server/shell/application_session.cpp (+6/-2)
src/server/shell/session_manager.cpp (+27/-10)
src/server/shell/single_visibility_focus_mechanism.cpp (+2/-7)
tests/acceptance-tests/test_client_input.cpp (+5/-6)
tests/acceptance-tests/test_focus_selection.cpp (+21/-21)
tests/death-tests/test_application_manager_death.cpp (+4/-3)
tests/integration-tests/input/android/test_android_input_manager.cpp (+70/-12)
tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp (+1/-1)
tests/integration-tests/shell/test_session_manager.cpp (+24/-17)
tests/mir_test_framework/testing_server_options.cpp (+3/-11)
tests/unit-tests/input/android/test_android_dispatcher_controller.cpp (+145/-18)
tests/unit-tests/input/android/test_event_filter_input_dispatcher_policy.cpp (+1/-1)
tests/unit-tests/shell/test_application_session.cpp (+11/-5)
tests/unit-tests/shell/test_registration_order_focus_sequence.cpp (+16/-11)
tests/unit-tests/shell/test_session_manager.cpp (+73/-8)
tests/unit-tests/shell/test_single_visibility_focus_mechanism.cpp (+1/-24)
tests/unit-tests/shell/test_the_session_container_implementation.cpp (+7/-4)
To merge this branch: bzr merge lp:~robertcarr/mir/reflow-input-focus-selection
Reviewer Review Type Date Requested Status
Kevin DuBois (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Alan Griffiths Approve
Alexandros Frantzis (community) Needs Fixing
Review via email: mp+159225@code.launchpad.net

Commit message

Rework interface between DispatcherController and shell in terms of an InputTargetListener

Description of the change

This branch reworks the DispatcherController and shell in terms of an input target listener.

While this rework is generally useful (preparing for touch picking by maintaining full window list, general efficiency/cleanliness) it was driven by a bug in the old code. Recreating the window handles caused the input fds to be closed, so it was not possible to cycle focus (noticed this when input stops working in the demo shell after you alt tab ;))

TEST_F(AndroidInputManagerDispatcherInterceptSetup, changing_focus_changes_event_recipient)

is the test which failed before.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

"GNU Lesser General Public" outside of client/shared libraries

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

Hmm there are merge conflicts too

Revision history for this message
Robert Carr (robertcarr) wrote :

Merged trunk! Fixed licenses.

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

704 -mia::EventFilterDispatcherPolicy::EventFilterDispatcherPolicy(std::shared_ptr<mi::EventFilter> const& event_filter) :
705 - event_filter(event_filter)
706 +mia::EventFilterDispatcherPolicy::EventFilterDispatcherPolicy(std::shared_ptr<mi::EventFilter> const& event_filter, bool key_repeat_enabled) :
707 + event_filter(event_filter),
708 + key_repeat_enabled(key_repeat_enabled)

Are these changes (and other related changes) relevant to this MP?

167 +#define MIR_SHELL_INPUT_LISTENER_H_

Mismatch between file/class name and include guard.

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

Now there are merge conflicts

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote :

Trunk merged, header guards fixed.

Key-repeat-enabled changes are useful for the test. Without disabling key repeat, the tests are racey or the code becomes noisy (need to trigger key release events, handle more events, etc...)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

$ bin/unit-tests | grep "GMOCK WARNING:" | wc -l
2

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote :

Fixed gmock warnings

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

OK

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote :

looks good to me too

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/server/mir/default_server_configuration.h'
2--- include/server/mir/default_server_configuration.h 2013-04-19 15:59:41 +0000
3+++ include/server/mir/default_server_configuration.h 2013-04-22 15:55:31 +0000
4@@ -50,7 +50,7 @@
5 {
6 class SurfaceFactory;
7 class SurfaceBuilder;
8-class InputFocusSelector;
9+class InputTargetListener;
10 class SessionContainer;
11 class FocusSetter;
12 class FocusSequence;
13@@ -156,7 +156,6 @@
14 /** @name shell configuration - dependencies
15 * dependencies of shell on the rest of the Mir
16 * @{ */
17- virtual std::shared_ptr<shell::InputFocusSelector> the_input_focus_selector();
18 virtual std::shared_ptr<shell::SurfaceBuilder> the_surface_builder();
19 /** @} */
20
21@@ -178,6 +177,7 @@
22 * @{ */
23 virtual std::shared_ptr<input::android::InputConfiguration> the_input_configuration();
24 virtual std::initializer_list<std::shared_ptr<input::EventFilter> const> the_event_filters();
25+ virtual std::shared_ptr<shell::InputTargetListener> the_input_target_listener();
26 /** @} */
27
28 /** @name logging configuration - customization
29@@ -197,7 +197,7 @@
30 CachedPtr<frontend::Shell> session_manager;
31 std::shared_ptr<input::android::InputConfiguration> input_configuration;
32 CachedPtr<input::InputManager> input_manager;
33- CachedPtr<shell::InputFocusSelector> input_focus_selector;
34+ CachedPtr<shell::InputTargetListener> input_target_listener;
35 CachedPtr<graphics::Platform> graphics_platform;
36 CachedPtr<graphics::BufferInitializer> buffer_initializer;
37 CachedPtr<compositor::GraphicBufferAllocator> buffer_allocator;
38
39=== modified file 'include/server/mir/input/input_manager.h'
40--- include/server/mir/input/input_manager.h 2013-04-16 09:08:29 +0000
41+++ include/server/mir/input/input_manager.h 2013-04-22 15:55:31 +0000
42@@ -21,7 +21,6 @@
43 #define MIR_INPUT_INPUT_MANAGER_H_
44
45 #include "mir/input/input_channel_factory.h"
46-#include "mir/shell/input_focus_selector.h"
47
48 #include <memory>
49
50
51=== modified file 'include/server/mir/input/null_input_manager.h'
52--- include/server/mir/input/null_input_manager.h 2013-04-16 09:08:29 +0000
53+++ include/server/mir/input/null_input_manager.h 2013-04-22 15:55:31 +0000
54@@ -40,11 +40,6 @@
55 return std::shared_ptr<InputChannel>();
56 }
57
58- virtual void set_input_focus_to(std::shared_ptr<input::SessionTarget> const& /* session */,
59- std::shared_ptr<input::SurfaceTarget> const& /* surface */)
60- {
61- }
62-
63 protected:
64 NullInputManager(const NullInputManager&) = delete;
65 NullInputManager& operator=(const NullInputManager&) = delete;
66
67=== renamed file 'include/server/mir/input/null_input_focus_selector.h' => 'include/server/mir/input/null_input_target_listener.h'
68--- include/server/mir/input/null_input_focus_selector.h 2013-04-17 02:04:35 +0000
69+++ include/server/mir/input/null_input_target_listener.h 2013-04-22 15:55:31 +0000
70@@ -16,33 +16,48 @@
71 * Authored by: Robert Carr <robert.carr@canonical.com>
72 */
73
74-#ifndef MIR_INPUT_NULL_INPUT_FOCUS_SELECTOR_H_
75-#define MIR_INPUT_NULL_INPUT_FOCUS_SELECTOR_H_
76+#ifndef MIR_INPUT_NULL_INPUT_TARGET_LISTENER_H_
77+#define MIR_INPUT_NULL_INPUT_TARGET_LISTENER_H_
78
79-#include "mir/shell/input_focus_selector.h"
80+#include "mir/shell/input_target_listener.h"
81
82 namespace mir
83 {
84 namespace input
85 {
86
87-class NullInputFocusSelector : public shell::InputFocusSelector
88+class NullInputTargetListener : public shell::InputTargetListener
89 {
90 public:
91- NullInputFocusSelector() {};
92- virtual ~NullInputFocusSelector() {}
93+ NullInputTargetListener() {};
94+ virtual ~NullInputTargetListener() noexcept(true) {}
95
96- virtual void set_input_focus_to(std::shared_ptr<input::SessionTarget> const&,
97- std::shared_ptr<input::SurfaceTarget> const&)
98+ virtual void input_application_opened(std::shared_ptr<input::SessionTarget> const&)
99+ {
100+ }
101+ virtual void input_application_closed(std::shared_ptr<input::SessionTarget> const&)
102+ {
103+ }
104+ virtual void input_surface_opened(std::shared_ptr<input::SessionTarget> const&,
105+ std::shared_ptr<input::SurfaceTarget> const&)
106+ {
107+ }
108+ virtual void input_surface_closed(std::shared_ptr<input::SurfaceTarget> const&)
109+ {
110+ }
111+ virtual void focus_changed(std::shared_ptr<input::SurfaceTarget> const&)
112+ {
113+ }
114+ virtual void focus_cleared()
115 {
116 }
117
118 protected:
119- NullInputFocusSelector(const NullInputFocusSelector&) = delete;
120- NullInputFocusSelector& operator=(const NullInputFocusSelector&) = delete;
121+ NullInputTargetListener(const NullInputTargetListener&) = delete;
122+ NullInputTargetListener& operator=(const NullInputTargetListener&) = delete;
123 };
124
125 }
126 }
127
128-#endif // MIR_INPUT_NULL_INPUT_FOCUS_SELECTOR_H_
129+#endif // MIR_INPUT_NULL_INPUT_TARGET_LISTENER_H_
130
131=== modified file 'include/server/mir/shell/application_session.h'
132--- include/server/mir/shell/application_session.h 2013-04-16 17:42:26 +0000
133+++ include/server/mir/shell/application_session.h 2013-04-22 15:55:31 +0000
134@@ -30,11 +30,13 @@
135 {
136 class SurfaceFactory;
137 class Surface;
138+class InputTargetListener;
139
140 class ApplicationSession : public Session
141 {
142 public:
143- explicit ApplicationSession(std::shared_ptr<SurfaceFactory> const& surface_factory, std::string const& session_name);
144+ explicit ApplicationSession(std::shared_ptr<SurfaceFactory> const& surface_factory,
145+ std::shared_ptr<InputTargetListener> const& input_target_listener, std::string const& session_name);
146 ~ApplicationSession();
147
148 frontend::SurfaceId create_surface(frontend::SurfaceCreationParameters const& params);
149@@ -58,6 +60,7 @@
150
151 private:
152 std::shared_ptr<SurfaceFactory> const surface_factory;
153+ std::shared_ptr<InputTargetListener> const input_target_listener;
154 std::string const session_name;
155
156 frontend::SurfaceId next_id();
157
158=== removed file 'include/server/mir/shell/input_focus_selector.h'
159--- include/server/mir/shell/input_focus_selector.h 2013-04-16 09:08:29 +0000
160+++ include/server/mir/shell/input_focus_selector.h 1970-01-01 00:00:00 +0000
161@@ -1,52 +0,0 @@
162-/*
163- * Copyright © 2013 Canonical Ltd.
164- *
165- * This program is free software: you can redistribute it and/or modify it
166- * under the terms of the GNU General Public License version 3,
167- * as published by the Free Software Foundation.
168- *
169- * This program is distributed in the hope that it will be useful,
170- * but WITHOUT ANY WARRANTY; without even the implied warranty of
171- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
172- * GNU General Public License for more details.
173- *
174- * You should have received a copy of the GNU General Public License
175- * along with this program. If not, see <http://www.gnu.org/licenses/>.
176- *
177- * Authored by: Robert Carr <robert.carr@canonical.com>
178- */
179-
180-#ifndef MIR_SHELL_INPUT_FOCUS_SELECTOR_H_
181-#define MIR_SHELL_INPUT_FOCUS_SELECTOR_H_
182-
183-#include <memory>
184-
185-namespace mir
186-{
187-namespace input
188-{
189-class SessionTarget;
190-class SurfaceTarget;
191-}
192-
193-namespace shell
194-{
195-
196-class InputFocusSelector
197-{
198-public:
199- virtual ~InputFocusSelector() {}
200-
201- virtual void set_input_focus_to(std::shared_ptr<input::SessionTarget> const& focus_application,
202- std::shared_ptr<input::SurfaceTarget> const& focus_surface) = 0;
203-
204-protected:
205- InputFocusSelector() = default;
206- InputFocusSelector(InputFocusSelector const&) = delete;
207- InputFocusSelector& operator=(InputFocusSelector const&) = delete;
208-};
209-
210-}
211-} // namespace mir
212-
213-#endif // MIR_SHELL_INPUT_FOCUS_SELECTOR_H_
214
215=== added file 'include/server/mir/shell/input_target_listener.h'
216--- include/server/mir/shell/input_target_listener.h 1970-01-01 00:00:00 +0000
217+++ include/server/mir/shell/input_target_listener.h 2013-04-22 15:55:31 +0000
218@@ -0,0 +1,59 @@
219+/*
220+ * Copyright © 2013 Canonical Ltd.
221+ *
222+ * This program is free software: you can redistribute it and/or modify it
223+ * under the terms of the GNU General Public License version 3,
224+ * as published by the Free Software Foundation.
225+ *
226+ * This program is distributed in the hope that it will be useful,
227+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
228+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
229+ * GNU General Public License for more details.
230+ *
231+ * You should have received a copy of the GNU General Public License
232+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
233+ *
234+ * Authored by: Robert Carr <robert.carr@canonical.com>
235+ */
236+
237+#ifndef MIR_SHELL_INPUT_TARGET_LISTENER_H_
238+#define MIR_SHELL_INPUT_TARGET_LISTENER_H_
239+
240+#include <memory>
241+
242+namespace mir
243+{
244+namespace input
245+{
246+class SessionTarget;
247+class SurfaceTarget;
248+}
249+
250+namespace shell
251+{
252+
253+class InputTargetListener
254+{
255+public:
256+ virtual ~InputTargetListener() = default;
257+
258+ virtual void input_application_opened(std::shared_ptr<input::SessionTarget> const& application) = 0;
259+ virtual void input_application_closed(std::shared_ptr<input::SessionTarget> const& application) = 0;
260+
261+ virtual void input_surface_opened(std::shared_ptr<input::SessionTarget> const& application,
262+ std::shared_ptr<input::SurfaceTarget> const& opened_surface) = 0;
263+ virtual void input_surface_closed(std::shared_ptr<input::SurfaceTarget> const& closed_surface) = 0;
264+
265+ virtual void focus_changed(std::shared_ptr<input::SurfaceTarget> const& focus_surface) = 0;
266+ virtual void focus_cleared() = 0;
267+
268+protected:
269+ InputTargetListener() = default;
270+ InputTargetListener(InputTargetListener const&) = delete;
271+ InputTargetListener& operator=(InputTargetListener const&) = delete;
272+};
273+
274+}
275+} // namespace mir
276+
277+#endif // MIR_SHELL_INPUT_TARGET_LISTENER_H_
278
279=== modified file 'include/server/mir/shell/session_manager.h'
280--- include/server/mir/shell/session_manager.h 2013-04-19 09:15:31 +0000
281+++ include/server/mir/shell/session_manager.h 2013-04-22 15:55:31 +0000
282@@ -40,15 +40,17 @@
283 class SessionContainer;
284 class FocusSequence;
285 class FocusSetter;
286+class InputTargetListener;
287 class Session;
288
289 class SessionManager : public frontend::Shell
290 {
291 public:
292 explicit SessionManager(std::shared_ptr<SurfaceFactory> const& surface_factory,
293- std::shared_ptr<SessionContainer> const& session_container,
294+ std::shared_ptr<SessionContainer> const& app_container,
295 std::shared_ptr<FocusSequence> const& focus_sequence,
296- std::shared_ptr<FocusSetter> const& focus_setter);
297+ std::shared_ptr<FocusSetter> const& focus_setter,
298+ std::shared_ptr<InputTargetListener> const& input_target_listener);
299 virtual ~SessionManager();
300
301 virtual std::shared_ptr<frontend::Session> open_session(std::string const& name);
302@@ -71,6 +73,7 @@
303 std::shared_ptr<SessionContainer> const app_container;
304 std::shared_ptr<FocusSequence> const focus_sequence;
305 std::shared_ptr<FocusSetter> const focus_setter;
306+ std::shared_ptr<InputTargetListener> const input_target_listener;
307
308 std::mutex mutex;
309 std::weak_ptr<Session> focus_application;
310
311=== modified file 'include/server/mir/shell/single_visibility_focus_mechanism.h'
312--- include/server/mir/shell/single_visibility_focus_mechanism.h 2013-04-16 09:08:29 +0000
313+++ include/server/mir/shell/single_visibility_focus_mechanism.h 2013-04-22 15:55:31 +0000
314@@ -28,13 +28,11 @@
315 namespace shell
316 {
317 class SessionContainer;
318-class InputFocusSelector;
319
320 class SingleVisibilityFocusMechanism : public FocusSetter
321 {
322 public:
323- explicit SingleVisibilityFocusMechanism(std::shared_ptr<SessionContainer> const& app_container,
324- std::shared_ptr<shell::InputFocusSelector> const& input_selector);
325+ explicit SingleVisibilityFocusMechanism(std::shared_ptr<SessionContainer> const& app_container);
326 virtual ~SingleVisibilityFocusMechanism() {}
327
328 void set_focus_to(std::shared_ptr<shell::Session> const& new_focus);
329@@ -44,7 +42,6 @@
330 SingleVisibilityFocusMechanism& operator=(const SingleVisibilityFocusMechanism&) = delete;
331 private:
332 std::shared_ptr<SessionContainer> const app_container;
333- std::shared_ptr<shell::InputFocusSelector> const input_selector;
334 };
335
336 }
337
338=== removed file 'include/test/mir_test_doubles/mock_input_focus_selector.h'
339--- include/test/mir_test_doubles/mock_input_focus_selector.h 2013-04-16 09:08:29 +0000
340+++ include/test/mir_test_doubles/mock_input_focus_selector.h 1970-01-01 00:00:00 +0000
341@@ -1,40 +0,0 @@
342-/*
343- * Copyright © 2013 Canonical Ltd.
344- *
345- * This program is free software: you can redistribute it and/or modify it
346- * under the terms of the GNU General Public License version 3,
347- * as published by the Free Software Foundation.
348- *
349- * This program is distributed in the hope that it will be useful,
350- * but WITHOUT ANY WARRANTY; without even the implied warranty of
351- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
352- * GNU General Public License for more details.
353- *
354- * You should have received a copy of the GNU General Public License
355- * along with this program. If not, see <http://www.gnu.org/licenses/>.
356- *
357- * Authored by: Robert Carr <robert.carr@canonical.com>
358- */
359-
360-#ifndef MIR_TEST_DOUBLES_MOCK_INPUT_FOCUS_SELECTOR_H_
361-#define MIR_TEST_DOUBLES_MOCK_INPUT_FOCUS_SELECTOR_H_
362-
363-#include "mir/shell/input_focus_selector.h"
364-
365-namespace mir
366-{
367-namespace test
368-{
369-namespace doubles
370-{
371-
372-struct MockInputFocusSelector : public shell::InputFocusSelector
373-{
374- MOCK_METHOD2(set_input_focus_to, void(std::shared_ptr<input::SessionTarget> const&, std::shared_ptr<input::SurfaceTarget> const&));
375-};
376-
377-}
378-}
379-} // namespace mir
380-
381-#endif // MIR_TEST_DOUBLES_MOCK_INPUT_FOCUS_SELECTOR_H_
382
383=== added file 'include/test/mir_test_doubles/mock_input_target_listener.h'
384--- include/test/mir_test_doubles/mock_input_target_listener.h 1970-01-01 00:00:00 +0000
385+++ include/test/mir_test_doubles/mock_input_target_listener.h 2013-04-22 15:55:31 +0000
386@@ -0,0 +1,49 @@
387+/*
388+ * Copyright © 2013 Canonical Ltd.
389+ *
390+ * This program is free software: you can redistribute it and/or modify it
391+ * under the terms of the GNU General Public License version 3,
392+ * as published by the Free Software Foundation.
393+ *
394+ * This program is distributed in the hope that it will be useful,
395+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
396+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
397+ * GNU General Public License for more details.
398+ *
399+ * You should have received a copy of the GNU General Public License
400+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
401+ *
402+ * Authored by: Robert Carr <robert.carr@canonical.com>
403+ */
404+
405+#ifndef MIR_TEST_DOUBLES_MOCK_INPUT_TARGET_LISTENER_H_
406+#define MIR_TEST_DOUBLES_MOCK_INPUT_TARGET_LISTENER_H_
407+
408+#include "mir/shell/input_target_listener.h"
409+
410+#include <gmock/gmock.h>
411+
412+namespace mir
413+{
414+namespace test
415+{
416+namespace doubles
417+{
418+
419+struct MockInputTargetListener : public shell::InputTargetListener
420+{
421+ virtual ~MockInputTargetListener() noexcept(true) {}
422+ MOCK_METHOD1(input_application_opened, void(std::shared_ptr<input::SessionTarget> const& application));
423+ MOCK_METHOD1(input_application_closed, void(std::shared_ptr<input::SessionTarget> const& application));
424+ MOCK_METHOD2(input_surface_opened, void(std::shared_ptr<input::SessionTarget> const& application,
425+ std::shared_ptr<input::SurfaceTarget> const& opened_surface));
426+ MOCK_METHOD1(input_surface_closed, void(std::shared_ptr<input::SurfaceTarget> const& closed_surface));
427+ MOCK_METHOD1(focus_changed, void(std::shared_ptr<input::SurfaceTarget> const& focus_surface));
428+ MOCK_METHOD0(focus_cleared, void());
429+};
430+
431+}
432+}
433+} // namespace mir
434+
435+#endif // MIR_TEST_DOUBLES_MOCK_INPUT_TARGET_LISTENER_H_
436
437=== added file 'include/test/mir_test_doubles/stub_input_target_listener.h'
438--- include/test/mir_test_doubles/stub_input_target_listener.h 1970-01-01 00:00:00 +0000
439+++ include/test/mir_test_doubles/stub_input_target_listener.h 2013-04-22 15:55:31 +0000
440@@ -0,0 +1,59 @@
441+/*
442+ * Copyright © 2013 Canonical Ltd.
443+ *
444+ * This program is free software: you can redistribute it and/or modify it
445+ * under the terms of the GNU General Public License version 3,
446+ * as published by the Free Software Foundation.
447+ *
448+ * This program is distributed in the hope that it will be useful,
449+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
450+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
451+ * GNU General Public License for more details.
452+ *
453+ * You should have received a copy of the GNU General Public License
454+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
455+ *
456+ * Authored by: Robert Carr <robert.carr@canonical.com>
457+ */
458+
459+#ifndef MIR_TEST_DOUBLES_STUB_INPUT_LISTENER_H_
460+#define MIR_TEST_DOUBLES_STUB_INPUT_LISTENER_H_
461+
462+#include "mir/shell/input_target_listener.h"
463+
464+namespace mir
465+{
466+namespace test
467+{
468+namespace doubles
469+{
470+
471+struct StubInputTargetListener : public shell::InputTargetListener
472+{
473+ void input_application_opened(std::shared_ptr<input::SessionTarget> const&)
474+ {
475+ }
476+ void input_application_closed(std::shared_ptr<input::SessionTarget> const&)
477+ {
478+ }
479+ void input_surface_opened(std::shared_ptr<input::SessionTarget> const&,
480+ std::shared_ptr<input::SurfaceTarget> const&)
481+ {
482+ }
483+ void input_surface_closed(std::shared_ptr<input::SurfaceTarget> const&)
484+ {
485+ }
486+ void focus_changed(std::shared_ptr<input::SurfaceTarget> const&)
487+ {
488+ }
489+
490+ void focus_cleared()
491+ {
492+ }
493+};
494+
495+}
496+}
497+} // namespace mir
498+
499+#endif // MIR_TEST_DOUBLES_STUB_INPUT_LISTENER_H_
500
501=== modified file 'include/test/mir_test_framework/testing_server_configuration.h'
502--- include/test/mir_test_framework/testing_server_configuration.h 2013-04-16 09:08:29 +0000
503+++ include/test/mir_test_framework/testing_server_configuration.h 2013-04-22 15:55:31 +0000
504@@ -49,7 +49,7 @@
505 // to avoid starting and stopping the full android input stack for tests
506 // which do not leverage input.
507 std::shared_ptr<input::InputManager> the_input_manager();
508- std::shared_ptr<shell::InputFocusSelector> the_input_focus_selector();
509+ std::shared_ptr<shell::InputTargetListener> the_input_target_listener();
510
511 virtual std::string the_socket_file() const;
512 using DefaultServerConfiguration::the_options;
513
514=== modified file 'src/server/default_server_configuration.cpp'
515--- src/server/default_server_configuration.cpp 2013-04-19 12:49:42 +0000
516+++ src/server/default_server_configuration.cpp 2013-04-22 15:55:31 +0000
517@@ -45,7 +45,7 @@
518 #include "mir/graphics/buffer_initializer.h"
519 #include "mir/graphics/null_display_report.h"
520 #include "mir/input/null_input_manager.h"
521-#include "mir/input/null_input_focus_selector.h"
522+#include "mir/input/null_input_target_listener.h"
523 #include "input/android/default_android_input_configuration.h"
524 #include "input/android/android_input_manager.h"
525 #include "input/android/android_dispatcher_controller.h"
526@@ -310,8 +310,7 @@
527 [this]
528 {
529 return std::make_shared<msh::SingleVisibilityFocusMechanism>(
530- the_shell_session_container(),
531- the_input_focus_selector());
532+ the_shell_session_container());
533 });
534 }
535
536@@ -347,7 +346,8 @@
537 the_shell_surface_factory(),
538 the_shell_session_container(),
539 the_shell_focus_sequence(),
540- the_shell_focus_setter());
541+ the_shell_focus_setter(),
542+ the_input_target_listener());
543 });
544 }
545
546@@ -562,15 +562,15 @@
547 return the_input_manager();
548 }
549
550-std::shared_ptr<msh::InputFocusSelector> mir::DefaultServerConfiguration::the_input_focus_selector()
551+std::shared_ptr<msh::InputTargetListener> mir::DefaultServerConfiguration::the_input_target_listener()
552 {
553- return input_focus_selector(
554- [&]() -> std::shared_ptr<msh::InputFocusSelector>
555+ return input_target_listener(
556+ [&]() -> std::shared_ptr<msh::InputTargetListener>
557 {
558 if (the_options()->get("enable-input", false))
559 return std::make_shared<mia::DispatcherController>(the_input_configuration());
560 else
561- return std::make_shared<mi::NullInputFocusSelector>();
562+ return std::make_shared<mi::NullInputTargetListener>();
563 });
564 }
565
566
567=== modified file 'src/server/display_server.cpp'
568--- src/server/display_server.cpp 2013-04-19 14:52:23 +0000
569+++ src/server/display_server.cpp 2013-04-22 15:55:31 +0000
570@@ -31,9 +31,9 @@
571
572 namespace mc = mir::compositor;
573 namespace mf = mir::frontend;
574-namespace msh = mir::shell;
575 namespace mg = mir::graphics;
576 namespace mi = mir::input;
577+namespace msh = mir::shell;
578
579 namespace
580 {
581
582=== modified file 'src/server/input/android/android_dispatcher_controller.cpp'
583--- src/server/input/android/android_dispatcher_controller.cpp 2013-04-11 23:06:12 +0000
584+++ src/server/input/android/android_dispatcher_controller.cpp 2013-04-22 15:55:31 +0000
585@@ -25,35 +25,85 @@
586
587 #include <InputDispatcher.h>
588
589+#include <boost/throw_exception.hpp>
590+
591+#include <stdexcept>
592+#include <mutex>
593+
594 namespace mi = mir::input;
595 namespace mia = mi::android;
596
597 mia::DispatcherController::DispatcherController(std::shared_ptr<mia::InputConfiguration> const& config) :
598- input_dispatcher(config->the_dispatcher()),
599- focused_window_handle(0),
600- focused_application_handle(0)
601-{
602-}
603-
604-void mia::DispatcherController::set_input_focus_to(std::shared_ptr<mi::SessionTarget> const& session,
605- std::shared_ptr<mi::SurfaceTarget> const& surface)
606-{
607- if (focused_window_handle.get())
608- {
609- input_dispatcher->unregisterInputChannel(focused_window_handle->getInfo()->inputChannel);
610- focused_window_handle.clear();
611- focused_application_handle.clear();
612- }
613+ input_dispatcher(config->the_dispatcher())
614+{
615+}
616+
617+void mia::DispatcherController::input_application_opened(std::shared_ptr<mi::SessionTarget> const& session)
618+{
619+ std::unique_lock<std::mutex> lock(handles_mutex);
620+ if (application_handles.find(session) != application_handles.end())
621+ BOOST_THROW_EXCEPTION(std::logic_error("An application was opened twice"));
622+ application_handles[session] = new mia::InputApplicationHandle(session);
623+}
624+
625+void mia::DispatcherController::input_application_closed(std::shared_ptr<mi::SessionTarget> const& session)
626+{
627+ std::unique_lock<std::mutex> lock(handles_mutex);
628+ if (application_handles.find(session) == application_handles.end())
629+ BOOST_THROW_EXCEPTION(std::logic_error("An application was closed twice"));
630+ application_handles.erase(session);
631+}
632+
633+void mia::DispatcherController::input_surface_opened(std::shared_ptr<mi::SessionTarget> const& session,
634+ std::shared_ptr<input::SurfaceTarget> const& opened_surface)
635+{
636+ std::unique_lock<std::mutex> lock(handles_mutex);
637+ auto application_handle = application_handles.find(session);
638+ if (application_handle == application_handles.end())
639+ BOOST_THROW_EXCEPTION(std::logic_error("A surface was opened for an unopened application"));
640+ if (window_handles.find(opened_surface) != window_handles.end())
641+ BOOST_THROW_EXCEPTION(std::logic_error("A surface was opened twice"));
642+
643+ droidinput::sp<droidinput::InputWindowHandle> window_handle = new mia::InputWindowHandle(application_handle->second, opened_surface);
644+ input_dispatcher->registerInputChannel(window_handle->getInfo()->inputChannel, window_handle, false);
645+
646+ window_handles[opened_surface] = window_handle;
647+}
648+
649+void mia::DispatcherController::input_surface_closed(std::shared_ptr<input::SurfaceTarget> const& closed_surface)
650+{
651+ std::unique_lock<std::mutex> lock(handles_mutex);
652+ auto it = window_handles.find(closed_surface);
653+ if (it == window_handles.end())
654+ BOOST_THROW_EXCEPTION(std::logic_error("A surface was closed twice"));
655+
656+ input_dispatcher->unregisterInputChannel(it->second->getInfo()->inputChannel);
657+ window_handles.erase(it);
658+}
659+
660+void mia::DispatcherController::focus_cleared()
661+{
662+ droidinput::Vector<droidinput::sp<droidinput::InputWindowHandle>> empty_windows;
663+ droidinput::sp<droidinput::InputApplicationHandle> null_application = nullptr;
664+
665+ input_dispatcher->setFocusedApplication(null_application);
666+ input_dispatcher->setInputWindows(empty_windows);
667+}
668+
669+void mia::DispatcherController::focus_changed(std::shared_ptr<mi::SurfaceTarget> const& surface)
670+{
671+ std::unique_lock<std::mutex> lock(handles_mutex);
672+
673+ auto window_handle = window_handles[surface];
674+
675+ if (!window_handle.get())
676+ BOOST_THROW_EXCEPTION(std::logic_error("Focus changed to an unopened surface"));
677+ auto application_handle = window_handle->inputApplicationHandle;
678+
679+ input_dispatcher->setFocusedApplication(application_handle);
680
681 droidinput::Vector<droidinput::sp<droidinput::InputWindowHandle>> windows;
682- if (surface)
683- {
684- focused_application_handle = new mia::InputApplicationHandle(session);
685- focused_window_handle = new mia::InputWindowHandle(focused_application_handle, surface);
686- input_dispatcher->setFocusedApplication(focused_application_handle);
687+ windows.push_back(window_handle);
688
689- input_dispatcher->registerInputChannel(focused_window_handle->getInfo()->inputChannel, focused_window_handle, false);
690- windows.push_back(focused_window_handle);
691- }
692 input_dispatcher->setInputWindows(windows);
693 }
694
695=== modified file 'src/server/input/android/android_dispatcher_controller.h'
696--- src/server/input/android/android_dispatcher_controller.h 2013-04-11 23:06:12 +0000
697+++ src/server/input/android/android_dispatcher_controller.h 2013-04-22 15:55:31 +0000
698@@ -19,10 +19,13 @@
699 #ifndef MIR_INPUT_ANDROID_DISPATCHER_CONTROLLER_H_
700 #define MIR_INPUT_ANDROID_DISPATCHER_CONTROLLER_H_
701
702-#include "mir/shell/input_focus_selector.h"
703+#include "mir/shell/input_target_listener.h"
704
705 #include <utils/StrongPointer.h>
706
707+#include <map>
708+#include <mutex>
709+
710 namespace android
711 {
712 class InputDispatcherInterface;
713@@ -40,13 +43,21 @@
714 {
715 class InputConfiguration;
716
717-class DispatcherController : public shell::InputFocusSelector
718+class DispatcherController : public shell::InputTargetListener
719 {
720 public:
721 explicit DispatcherController(std::shared_ptr<InputConfiguration> const& input_configuration);
722- virtual ~DispatcherController() = default;
723+ virtual ~DispatcherController() noexcept(true) {}
724
725- void set_input_focus_to(std::shared_ptr<input::SessionTarget> const& session, std::shared_ptr<input::SurfaceTarget> const& surface);
726+ void input_application_opened(std::shared_ptr<input::SessionTarget> const& application);
727+ void input_application_closed(std::shared_ptr<input::SessionTarget> const& application);
728+
729+ void input_surface_opened(std::shared_ptr<input::SessionTarget> const& application,
730+ std::shared_ptr<input::SurfaceTarget> const& opened_surface);
731+ void input_surface_closed(std::shared_ptr<input::SurfaceTarget> const& closed_surface);
732+
733+ void focus_changed(std::shared_ptr<input::SurfaceTarget> const& focus_surface);
734+ void focus_cleared();
735
736 protected:
737 DispatcherController(const DispatcherController&) = delete;
738@@ -55,8 +66,10 @@
739 private:
740 droidinput::sp<droidinput::InputDispatcherInterface> input_dispatcher;
741
742- droidinput::sp<droidinput::InputWindowHandle> focused_window_handle;
743- droidinput::sp<droidinput::InputApplicationHandle> focused_application_handle;
744+ std::map<std::shared_ptr<input::SessionTarget>, droidinput::sp<droidinput::InputApplicationHandle>> application_handles;
745+ std::map<std::shared_ptr<input::SurfaceTarget>, droidinput::sp<droidinput::InputWindowHandle>> window_handles;
746+
747+ std::mutex handles_mutex;
748 };
749
750 }
751
752=== modified file 'src/server/input/android/default_android_input_configuration.cpp'
753--- src/server/input/android/default_android_input_configuration.cpp 2013-04-16 09:08:29 +0000
754+++ src/server/input/android/default_android_input_configuration.cpp 2013-04-22 15:55:31 +0000
755@@ -98,7 +98,7 @@
756 return dispatcher_policy(
757 [this]()
758 {
759- return new mia::EventFilterDispatcherPolicy(filter_chain);
760+ return new mia::EventFilterDispatcherPolicy(filter_chain, is_key_repeat_enabled());
761 });
762 }
763
764@@ -149,3 +149,8 @@
765 new droidinput::InputReaderThread(the_reader()));
766 });
767 }
768+
769+bool mia::DefaultInputConfiguration::is_key_repeat_enabled()
770+{
771+ return true;
772+}
773
774=== modified file 'src/server/input/android/default_android_input_configuration.h'
775--- src/server/input/android/default_android_input_configuration.h 2013-04-16 09:08:29 +0000
776+++ src/server/input/android/default_android_input_configuration.h 2013-04-22 15:55:31 +0000
777@@ -69,6 +69,8 @@
778
779 virtual droidinput::sp<droidinput::InputDispatcherPolicyInterface> the_dispatcher_policy();
780 virtual droidinput::sp<droidinput::InputReaderPolicyInterface> the_reader_policy();
781+
782+ virtual bool is_key_repeat_enabled();
783
784 protected:
785 DefaultInputConfiguration(DefaultInputConfiguration const&) = delete;
786
787=== modified file 'src/server/input/android/event_filter_dispatcher_policy.cpp'
788--- src/server/input/android/event_filter_dispatcher_policy.cpp 2013-04-16 09:27:00 +0000
789+++ src/server/input/android/event_filter_dispatcher_policy.cpp 2013-04-22 15:55:31 +0000
790@@ -21,8 +21,9 @@
791 namespace mi = mir::input;
792 namespace mia = mi::android;
793
794-mia::EventFilterDispatcherPolicy::EventFilterDispatcherPolicy(std::shared_ptr<mi::EventFilter> const& event_filter) :
795- event_filter(event_filter)
796+mia::EventFilterDispatcherPolicy::EventFilterDispatcherPolicy(std::shared_ptr<mi::EventFilter> const& event_filter, bool key_repeat_enabled) :
797+ event_filter(event_filter),
798+ key_repeat_enabled(key_repeat_enabled)
799 {
800 }
801
802@@ -46,7 +47,7 @@
803
804 bool mia::EventFilterDispatcherPolicy::isKeyRepeatEnabled()
805 {
806- return true;
807+ return key_repeat_enabled;
808 }
809
810 bool mia::EventFilterDispatcherPolicy::filterInputEvent(const droidinput::InputEvent* input_event, uint32_t /*policy_flags*/)
811
812=== modified file 'src/server/input/android/event_filter_dispatcher_policy.h'
813--- src/server/input/android/event_filter_dispatcher_policy.h 2013-04-16 09:08:29 +0000
814+++ src/server/input/android/event_filter_dispatcher_policy.h 2013-04-22 15:55:31 +0000
815@@ -40,7 +40,7 @@
816 class EventFilterDispatcherPolicy : public droidinput::InputDispatcherPolicyInterface
817 {
818 public:
819- EventFilterDispatcherPolicy(std::shared_ptr<EventFilter> const& event_filter);
820+ EventFilterDispatcherPolicy(std::shared_ptr<EventFilter> const& event_filter, bool key_repeat_enabled);
821 virtual ~EventFilterDispatcherPolicy() {}
822
823 void notifyConfigurationChanged(nsecs_t when);
824@@ -71,6 +71,7 @@
825 EventFilterDispatcherPolicy& operator=(const EventFilterDispatcherPolicy&) = delete;
826 private:
827 std::shared_ptr<EventFilter> event_filter;
828+ bool key_repeat_enabled;
829 };
830
831 }
832
833=== modified file 'src/server/shell/application_session.cpp'
834--- src/server/shell/application_session.cpp 2013-04-16 17:42:26 +0000
835+++ src/server/shell/application_session.cpp 2013-04-22 15:55:31 +0000
836@@ -18,8 +18,8 @@
837
838 #include "mir/shell/application_session.h"
839 #include "mir/shell/surface.h"
840-
841 #include "mir/shell/surface_factory.h"
842+#include "mir/shell/input_target_listener.h"
843
844 #include <boost/throw_exception.hpp>
845
846@@ -32,9 +32,11 @@
847 namespace msh = mir::shell;
848
849 msh::ApplicationSession::ApplicationSession(
850- std::shared_ptr<SurfaceFactory> const& surface_factory,
851+ std::shared_ptr<msh::SurfaceFactory> const& surface_factory,
852+ std::shared_ptr<msh::InputTargetListener> const& input_target_listener,
853 std::string const& session_name) :
854 surface_factory(surface_factory),
855+ input_target_listener(input_target_listener),
856 session_name(session_name),
857 next_surface_id(0)
858 {
859@@ -46,6 +48,7 @@
860 std::unique_lock<std::mutex> lock(surfaces_mutex);
861 for (auto const& pair_id_surface : surfaces)
862 {
863+ input_target_listener->input_surface_closed(pair_id_surface.second);
864 pair_id_surface.second->destroy();
865 }
866 }
867@@ -95,6 +98,7 @@
868 std::unique_lock<std::mutex> lock(surfaces_mutex);
869 auto p = checked_find(id);
870
871+ input_target_listener->input_surface_closed(p->second);
872 p->second->destroy();
873 surfaces.erase(p);
874 }
875
876=== modified file 'src/server/shell/session_manager.cpp'
877--- src/server/shell/session_manager.cpp 2013-04-19 09:15:31 +0000
878+++ src/server/shell/session_manager.cpp 2013-04-22 15:55:31 +0000
879@@ -23,6 +23,8 @@
880 #include "mir/shell/focus_sequence.h"
881 #include "mir/shell/focus_setter.h"
882 #include "mir/shell/session.h"
883+#include "mir/shell/surface.h"
884+#include "mir/shell/input_target_listener.h"
885
886 #include <memory>
887 #include <cassert>
888@@ -31,20 +33,22 @@
889 namespace mf = mir::frontend;
890 namespace msh = mir::shell;
891
892-msh::SessionManager::SessionManager(
893- std::shared_ptr<msh::SurfaceFactory> const& surface_factory,
894+msh::SessionManager::SessionManager(std::shared_ptr<msh::SurfaceFactory> const& surface_factory,
895 std::shared_ptr<msh::SessionContainer> const& container,
896 std::shared_ptr<msh::FocusSequence> const& sequence,
897- std::shared_ptr<msh::FocusSetter> const& focus_setter) :
898+ std::shared_ptr<msh::FocusSetter> const& focus_setter,
899+ std::shared_ptr<msh::InputTargetListener> const& input_target_listener) :
900 surface_factory(surface_factory),
901 app_container(container),
902 focus_sequence(sequence),
903- focus_setter(focus_setter)
904+ focus_setter(focus_setter),
905+ input_target_listener(input_target_listener)
906 {
907 assert(surface_factory);
908 assert(sequence);
909 assert(container);
910 assert(focus_setter);
911+ assert(input_target_listener);
912 }
913
914 msh::SessionManager::~SessionManager()
915@@ -53,25 +57,36 @@
916
917 std::shared_ptr<mf::Session> msh::SessionManager::open_session(std::string const& name)
918 {
919- auto new_session = std::make_shared<msh::ApplicationSession>(surface_factory, name);
920+ auto new_session = std::make_shared<msh::ApplicationSession>(surface_factory, input_target_listener, name);
921
922 app_container->insert_session(new_session);
923+
924+ input_target_listener->input_application_opened(new_session);
925
926 set_focus_to_locked(std::unique_lock<std::mutex>(mutex), new_session);
927
928 return new_session;
929 }
930
931-inline void msh::SessionManager::set_focus_to_locked(std::unique_lock<std::mutex> const&, std::shared_ptr<Session> const& next_focus)
932+inline void msh::SessionManager::set_focus_to_locked(std::unique_lock<std::mutex> const&, std::shared_ptr<Session> const& shell_session)
933 {
934- focus_application = next_focus;
935- focus_setter->set_focus_to(next_focus);
936+ auto old_focus = focus_application.lock();
937+
938+ focus_application = shell_session;
939+ focus_setter->set_focus_to(shell_session);
940+
941+ if (shell_session && shell_session->default_surface())
942+ input_target_listener->focus_changed(shell_session->default_surface());
943+ else if (shell_session == old_focus || !shell_session)
944+ input_target_listener->focus_cleared();
945 }
946
947 void msh::SessionManager::close_session(std::shared_ptr<mf::Session> const& session)
948 {
949 auto shell_session = std::dynamic_pointer_cast<Session>(session);
950
951+ input_target_listener->input_application_closed(shell_session);
952+
953 app_container->remove_session(shell_session);
954
955 std::unique_lock<std::mutex> lock(mutex);
956@@ -133,9 +148,11 @@
957 mf::SurfaceCreationParameters const& params)
958 {
959 auto shell_session = std::dynamic_pointer_cast<Session>(session);
960- auto id = session->create_surface(params);
961+ auto id = shell_session->create_surface(params);
962+
963+ input_target_listener->input_surface_opened(shell_session,
964+ std::dynamic_pointer_cast<msh::Surface>(shell_session->get_surface(id)));
965 set_focus_to_locked(std::unique_lock<std::mutex>(mutex), shell_session);
966
967 return id;
968 }
969-
970
971=== modified file 'src/server/shell/single_visibility_focus_mechanism.cpp'
972--- src/server/shell/single_visibility_focus_mechanism.cpp 2013-04-18 22:57:01 +0000
973+++ src/server/shell/single_visibility_focus_mechanism.cpp 2013-04-22 15:55:31 +0000
974@@ -19,7 +19,6 @@
975 #include "mir/shell/session_container.h"
976 #include "mir/frontend/session.h"
977 #include "mir/shell/single_visibility_focus_mechanism.h"
978-#include "mir/shell/input_focus_selector.h"
979
980 #include "mir/shell/session.h"
981 #include "mir/shell/surface.h"
982@@ -27,10 +26,8 @@
983 namespace mf = mir::frontend;
984 namespace msh = mir::shell;
985
986-msh::SingleVisibilityFocusMechanism::SingleVisibilityFocusMechanism(std::shared_ptr<msh::SessionContainer> const& app_container,
987- std::shared_ptr<msh::InputFocusSelector> const& input_selector)
988- : app_container(app_container),
989- input_selector(input_selector)
990+msh::SingleVisibilityFocusMechanism::SingleVisibilityFocusMechanism(std::shared_ptr<msh::SessionContainer> const& app_container)
991+ : app_container(app_container)
992 {
993 }
994
995@@ -41,8 +38,6 @@
996 if (session == focus_session)
997 {
998 session->show();
999-
1000- input_selector->set_input_focus_to(focus_session, focus_session->default_surface());
1001 }
1002 else
1003 {
1004
1005=== modified file 'tests/acceptance-tests/test_client_input.cpp'
1006--- tests/acceptance-tests/test_client_input.cpp 2013-04-17 07:31:40 +0000
1007+++ tests/acceptance-tests/test_client_input.cpp 2013-04-22 15:55:31 +0000
1008@@ -65,10 +65,9 @@
1009
1010 }
1011
1012- void set_input_focus_to(
1013- std::shared_ptr<mi::SessionTarget> const& session, std::shared_ptr<mi::SurfaceTarget> const& surface) override
1014+ void focus_changed(std::shared_ptr<mi::SurfaceTarget> const& surface) override
1015 {
1016- DispatcherController::set_input_focus_to(session, surface);
1017+ DispatcherController::focus_changed(surface);
1018
1019 // We need a synchronization primitive inorder to halt test event injection
1020 // until after a surface has taken focus (lest the events be discarded).
1021@@ -122,10 +121,10 @@
1022 });
1023 }
1024
1025- std::shared_ptr<msh::InputFocusSelector>
1026- the_input_focus_selector() override
1027+ std::shared_ptr<msh::InputTargetListener>
1028+ the_input_target_listener() override
1029 {
1030- return input_focus_selector(
1031+ return input_target_listener(
1032 [this]()
1033 {
1034 return std::make_shared<FocusNotifyingDispatcherController>(mt::fake_shared(input_config), on_focus_set);
1035
1036=== modified file 'tests/acceptance-tests/test_focus_selection.cpp'
1037--- tests/acceptance-tests/test_focus_selection.cpp 2013-04-18 02:52:30 +0000
1038+++ tests/acceptance-tests/test_focus_selection.cpp 2013-04-22 15:55:31 +0000
1039@@ -24,11 +24,11 @@
1040 #include "mir/shell/organising_surface_factory.h"
1041 #include "mir/shell/session_manager.h"
1042 #include "mir/graphics/display.h"
1043-#include "mir/shell/input_focus_selector.h"
1044+#include "mir/shell/input_target_listener.h"
1045
1046 #include "mir_test_framework/display_server_test_fixture.h"
1047 #include "mir_test_doubles/mock_focus_setter.h"
1048-#include "mir_test_doubles/mock_input_focus_selector.h"
1049+#include "mir_test_doubles/mock_input_target_listener.h"
1050
1051 #include <gtest/gtest.h>
1052 #include <gmock/gmock.h>
1053@@ -36,7 +36,8 @@
1054 namespace mf = mir::frontend;
1055 namespace msh = mir::shell;
1056 namespace mi = mir::input;
1057-namespace mtd = mir::test::doubles;
1058+namespace mt = mir::test;
1059+namespace mtd = mt::doubles;
1060 namespace mtf = mir_test_framework;
1061
1062 namespace
1063@@ -46,6 +47,7 @@
1064
1065 namespace
1066 {
1067+
1068 struct ClientConfigCommon : TestingClientConfiguration
1069 {
1070 ClientConfigCommon() :
1071@@ -121,18 +123,10 @@
1072 {
1073 return arg != std::shared_ptr<msh::Session>();
1074 }
1075-MATCHER(NonNullSessionTarget, "")
1076-{
1077- return arg != std::shared_ptr<mi::SessionTarget>();
1078-}
1079 MATCHER(NonNullSurfaceTarget, "")
1080 {
1081 return arg != std::shared_ptr<mi::SurfaceTarget>();
1082 }
1083-MATCHER(NullSurfaceTarget, "")
1084-{
1085- return arg == std::shared_ptr<mi::SurfaceTarget>();
1086-}
1087 }
1088
1089 TEST_F(BespokeDisplayServerTestFixture, sessions_creating_surface_receive_focus)
1090@@ -148,7 +142,6 @@
1091 using namespace ::testing;
1092
1093 auto focus_setter = std::make_shared<mtd::MockFocusSetter>();
1094-
1095 {
1096 InSequence seq;
1097 // Once on application registration and once on surface creation
1098@@ -174,30 +167,37 @@
1099 {
1100 struct ServerConfig : TestingServerConfiguration
1101 {
1102- std::shared_ptr<mtd::MockInputFocusSelector> focus_selector;
1103+ std::shared_ptr<mtd::MockInputTargetListener> target_listener;
1104 bool expected;
1105
1106 ServerConfig()
1107- : focus_selector(std::make_shared<mtd::MockInputFocusSelector>()),
1108+ : target_listener(std::make_shared<mtd::MockInputTargetListener>()),
1109 expected(false)
1110 {
1111 }
1112
1113- std::shared_ptr<msh::InputFocusSelector>
1114- the_input_focus_selector() override
1115+ std::shared_ptr<msh::InputTargetListener>
1116+ the_input_target_listener() override
1117 {
1118 using namespace ::testing;
1119
1120 if (!expected)
1121 {
1122- InSequence seq;
1123+
1124+ EXPECT_CALL(*target_listener, input_application_opened(_)).Times(AtLeast(0));
1125+ EXPECT_CALL(*target_listener, input_application_closed(_)).Times(AtLeast(0));
1126+ EXPECT_CALL(*target_listener, input_surface_opened(_,_)).Times(AtLeast(0));
1127+ EXPECT_CALL(*target_listener, input_surface_closed(_)).Times(AtLeast(0));
1128+ EXPECT_CALL(*target_listener, focus_cleared()).Times(AtLeast(0));
1129
1130- EXPECT_CALL(*focus_selector, set_input_focus_to(NonNullSessionTarget(), NullSurfaceTarget())).Times(1);
1131- EXPECT_CALL(*focus_selector, set_input_focus_to(NonNullSessionTarget(), NonNullSurfaceTarget())).Times(1);
1132- expected = true;
1133+ {
1134+ InSequence seq;
1135+ EXPECT_CALL(*target_listener, focus_changed(NonNullSurfaceTarget())).Times(1);
1136+ expected = true;
1137+ }
1138 }
1139
1140- return focus_selector;
1141+ return target_listener;
1142 }
1143 } server_config;
1144
1145
1146=== modified file 'tests/death-tests/test_application_manager_death.cpp'
1147--- tests/death-tests/test_application_manager_death.cpp 2013-03-21 03:32:59 +0000
1148+++ tests/death-tests/test_application_manager_death.cpp 2013-04-22 15:55:31 +0000
1149@@ -30,11 +30,12 @@
1150 // ::testing::FLAGS_gtest_death_test_style = "threadsafe";
1151 // leads to the test failing under valgrind
1152 EXPECT_EXIT(
1153- std::shared_ptr<msh::SurfaceFactory> factory;
1154- mir::shell::SessionManager app(factory,
1155+ std::shared_ptr<msh::SurfaceFactory> surface_factory;
1156+ mir::shell::SessionManager app(surface_factory,
1157 std::shared_ptr<msh::SessionContainer>(),
1158 std::shared_ptr<msh::FocusSequence>(),
1159- std::shared_ptr<msh::FocusSetter>()),
1160+ std::shared_ptr<msh::FocusSetter>(),
1161+ std::shared_ptr<msh::InputTargetListener>()),
1162 ::testing::KilledBySignal(SIGABRT),
1163 ".*");
1164 }
1165
1166=== modified file 'tests/integration-tests/input/android/test_android_input_manager.cpp'
1167--- tests/integration-tests/input/android/test_android_input_manager.cpp 2013-04-10 23:48:23 +0000
1168+++ tests/integration-tests/input/android/test_android_input_manager.cpp 2013-04-22 15:55:31 +0000
1169@@ -171,7 +171,7 @@
1170 struct MockDispatcherPolicy : public mia::EventFilterDispatcherPolicy
1171 {
1172 MockDispatcherPolicy(std::shared_ptr<mi::EventFilter> const& filter)
1173- : EventFilterDispatcherPolicy(filter)
1174+ : EventFilterDispatcherPolicy(filter, false)
1175 {
1176 }
1177 MOCK_METHOD3(interceptKeyBeforeDispatching, nsecs_t(droidinput::sp<droidinput::InputWindowHandle> const&,
1178@@ -211,24 +211,31 @@
1179 ON_CALL(viewable_area, view_area())
1180 .WillByDefault(Return(default_view_area));
1181 input_manager = std::make_shared<mia::InputManager>(configuration);
1182- input_focus_selector = std::make_shared<mia::DispatcherController>(configuration);
1183+ input_target_listener = std::make_shared<mia::DispatcherController>(configuration);
1184
1185 dispatcher_policy = configuration->the_mock_dispatcher_policy();
1186
1187 }
1188
1189+ ~AndroidInputManagerDispatcherInterceptSetup()
1190+ {
1191+ input_manager->stop();
1192+ }
1193+
1194 // TODO: It would be nice if it were possible to mock the interface between
1195 // droidinput::InputChannel and droidinput::InputDispatcher rather than use
1196 // valid fds to allow non-throwing construction of a real input channel.
1197 void SetUp()
1198 {
1199- test_input_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
1200 input_manager->start();
1201 }
1202- void TearDown()
1203+
1204+ int test_fd()
1205 {
1206- input_manager->stop();
1207- close(test_input_fd);
1208+ int fds[2];
1209+ // Closed by droidinput InputChannel on shutdown
1210+ socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds);
1211+ return fds[0];
1212 }
1213
1214 MockEventFilter event_filter;
1215@@ -238,9 +245,7 @@
1216 droidinput::sp<MockDispatcherPolicy> dispatcher_policy;
1217
1218 std::shared_ptr<mia::InputManager> input_manager;
1219- std::shared_ptr<msh::InputFocusSelector> input_focus_selector;
1220-
1221- int test_input_fd;
1222+ std::shared_ptr<msh::InputTargetListener> input_target_listener;
1223 };
1224
1225 MATCHER_P(WindowHandleWithInputFd, input_fd, "")
1226@@ -259,14 +264,18 @@
1227 mt::WaitCondition wait_condition;
1228
1229 mtd::StubSessionTarget session;
1230- mtd::StubSurfaceTarget surface(test_input_fd);
1231+
1232+ auto input_fd = test_fd();
1233+ mtd::StubSurfaceTarget surface(input_fd);
1234
1235 EXPECT_CALL(event_filter, handles(_)).Times(1).WillOnce(Return(false));
1236 // We return -1 here to skip publishing of the event (to an unconnected test socket!).
1237- EXPECT_CALL(*dispatcher_policy, interceptKeyBeforeDispatching(WindowHandleWithInputFd(test_input_fd), _, _))
1238+ EXPECT_CALL(*dispatcher_policy, interceptKeyBeforeDispatching(WindowHandleWithInputFd(input_fd), _, _))
1239 .Times(1).WillOnce(DoAll(mt::WakeUp(&wait_condition), Return(-1)));
1240
1241- input_focus_selector->set_input_focus_to(mt::fake_shared(session), mt::fake_shared(surface));
1242+ input_target_listener->input_application_opened(mt::fake_shared(session));
1243+ input_target_listener->input_surface_opened(mt::fake_shared(session), mt::fake_shared(surface));
1244+ input_target_listener->focus_changed(mt::fake_shared(surface));
1245
1246 fake_event_hub->synthesize_builtin_keyboard_added();
1247 fake_event_hub->synthesize_device_scan_complete();
1248@@ -275,3 +284,52 @@
1249
1250 wait_condition.wait_for_at_most_seconds(1);
1251 }
1252+
1253+TEST_F(AndroidInputManagerDispatcherInterceptSetup, changing_focus_changes_event_recipient)
1254+{
1255+ using namespace ::testing;
1256+
1257+ mt::WaitCondition wait1, wait2, wait3;
1258+
1259+ mtd::StubSessionTarget session;
1260+
1261+ auto input_fd_1 = test_fd();
1262+ mtd::StubSurfaceTarget surface1(input_fd_1);
1263+ auto input_fd_2 = test_fd();
1264+ mtd::StubSurfaceTarget surface2(input_fd_2);
1265+
1266+ input_target_listener->input_application_opened(mt::fake_shared(session));
1267+ input_target_listener->input_surface_opened(mt::fake_shared(session), mt::fake_shared(surface1));
1268+ input_target_listener->input_surface_opened(mt::fake_shared(session), mt::fake_shared(surface2));
1269+
1270+ EXPECT_CALL(event_filter, handles(_)).Times(3).WillRepeatedly(Return(false));
1271+
1272+ {
1273+ InSequence seq;
1274+
1275+ EXPECT_CALL(*dispatcher_policy, interceptKeyBeforeDispatching(WindowHandleWithInputFd(input_fd_1), _, _))
1276+ .Times(1).WillOnce(DoAll(mt::WakeUp(&wait1), Return(-1)));
1277+ EXPECT_CALL(*dispatcher_policy, interceptKeyBeforeDispatching(WindowHandleWithInputFd(input_fd_2), _, _))
1278+ .Times(1).WillOnce(DoAll(mt::WakeUp(&wait2), Return(-1)));
1279+ EXPECT_CALL(*dispatcher_policy, interceptKeyBeforeDispatching(WindowHandleWithInputFd(input_fd_1), _, _))
1280+ .Times(1).WillOnce(DoAll(mt::WakeUp(&wait3), Return(-1)));
1281+ }
1282+
1283+ fake_event_hub->synthesize_builtin_keyboard_added();
1284+ fake_event_hub->synthesize_device_scan_complete();
1285+
1286+ input_target_listener->focus_changed(mt::fake_shared(surface1));
1287+ fake_event_hub->synthesize_event(mis::a_key_down_event()
1288+ .of_scancode(KEY_1));
1289+ wait1.wait_for_at_most_seconds(1);
1290+
1291+ input_target_listener->focus_changed(mt::fake_shared(surface2));
1292+ fake_event_hub->synthesize_event(mis::a_key_down_event()
1293+ .of_scancode(KEY_2));
1294+ wait2.wait_for_at_most_seconds(1);
1295+
1296+ input_target_listener->focus_changed(mt::fake_shared(surface1));
1297+ fake_event_hub->synthesize_event(mis::a_key_down_event()
1298+ .of_scancode(KEY_3));
1299+ wait3.wait_for_at_most_seconds(5);
1300+}
1301
1302=== modified file 'tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp'
1303--- tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp 2013-04-02 18:26:40 +0000
1304+++ tests/integration-tests/input/android/test_fake_event_hub_to_event_filter.cpp 2013-04-22 15:55:31 +0000
1305@@ -56,7 +56,7 @@
1306 void SetUp()
1307 {
1308 event_hub = new mia::FakeEventHub();
1309- dispatcher_policy = new mia::EventFilterDispatcherPolicy(mt::fake_shared(event_filter));
1310+ dispatcher_policy = new mia::EventFilterDispatcherPolicy(mt::fake_shared(event_filter), false);
1311 reader_policy = new mia::RudimentaryInputReaderPolicy();
1312 dispatcher = new droidinput::InputDispatcher(dispatcher_policy);
1313 reader = new droidinput::InputReader(event_hub, reader_policy, dispatcher);
1314
1315=== modified file 'tests/integration-tests/shell/test_session_manager.cpp'
1316--- tests/integration-tests/shell/test_session_manager.cpp 2013-04-18 00:00:55 +0000
1317+++ tests/integration-tests/shell/test_session_manager.cpp 2013-04-22 15:55:31 +0000
1318@@ -33,6 +33,7 @@
1319 #include "mir_test/fake_shared.h"
1320 #include "mir_test_doubles/mock_surface_factory.h"
1321 #include "mir_test_doubles/mock_focus_setter.h"
1322+#include "mir_test_doubles/stub_input_target_listener.h"
1323
1324 namespace mc = mir::compositor;
1325 namespace mf = mir::frontend;
1326@@ -44,19 +45,22 @@
1327 TEST(TestSessionManagerAndFocusSelectionStrategy, cycle_focus)
1328 {
1329 using namespace ::testing;
1330+
1331 mtd::MockSurfaceFactory surface_factory;
1332 std::shared_ptr<msh::DefaultSessionContainer> container(new msh::DefaultSessionContainer());
1333 msh::RegistrationOrderFocusSequence sequence(container);
1334- mtd::MockFocusSetter focus_changer;
1335+ mtd::MockFocusSetter focus_setter;
1336 std::shared_ptr<mf::Session> new_session;
1337+ mtd::StubInputTargetListener input_target_listener;
1338
1339 msh::SessionManager session_manager(
1340 mt::fake_shared(surface_factory),
1341 container,
1342 mt::fake_shared(sequence),
1343- mt::fake_shared(focus_changer));
1344-
1345- EXPECT_CALL(focus_changer, set_focus_to(_)).Times(3);
1346+ mt::fake_shared(focus_setter),
1347+ mt::fake_shared(input_target_listener));
1348+
1349+ EXPECT_CALL(focus_setter, set_focus_to(_)).Times(3);
1350
1351 auto session1 = session_manager.open_session("Visual Basic Studio");
1352 auto session2 = session_manager.open_session("Microsoft Access");
1353@@ -64,9 +68,9 @@
1354
1355 {
1356 InSequence seq;
1357- EXPECT_CALL(focus_changer, set_focus_to(Eq(session1))).Times(1);
1358- EXPECT_CALL(focus_changer, set_focus_to(Eq(session2))).Times(1);
1359- EXPECT_CALL(focus_changer, set_focus_to(Eq(session3))).Times(1);
1360+ EXPECT_CALL(focus_setter, set_focus_to(Eq(session1))).Times(1);
1361+ EXPECT_CALL(focus_setter, set_focus_to(Eq(session2))).Times(1);
1362+ EXPECT_CALL(focus_setter, set_focus_to(Eq(session3))).Times(1);
1363 }
1364
1365 session_manager.focus_next();
1366@@ -77,19 +81,22 @@
1367 TEST(TestSessionManagerAndFocusSelectionStrategy, closing_applications_transfers_focus)
1368 {
1369 using namespace ::testing;
1370+
1371 mtd::MockSurfaceFactory surface_factory;
1372- std::shared_ptr<msh::DefaultSessionContainer> model(new msh::DefaultSessionContainer());
1373- msh::RegistrationOrderFocusSequence sequence(model);
1374- mtd::MockFocusSetter focus_changer;
1375+ std::shared_ptr<msh::DefaultSessionContainer> container(new msh::DefaultSessionContainer());
1376+ msh::RegistrationOrderFocusSequence sequence(container);
1377+ mtd::MockFocusSetter focus_setter;
1378 std::shared_ptr<mf::Session> new_session;
1379+ mtd::StubInputTargetListener input_target_listener;
1380
1381 msh::SessionManager session_manager(
1382- mt::fake_shared(surface_factory),
1383- model,
1384- mt::fake_shared(sequence),
1385- mt::fake_shared(focus_changer));
1386+ mt::fake_shared(surface_factory),
1387+ container,
1388+ mt::fake_shared(sequence),
1389+ mt::fake_shared(focus_setter),
1390+ mt::fake_shared(input_target_listener));
1391
1392- EXPECT_CALL(focus_changer, set_focus_to(_)).Times(3);
1393+ EXPECT_CALL(focus_setter, set_focus_to(_)).Times(3);
1394
1395 auto session1 = session_manager.open_session("Visual Basic Studio");
1396 auto session2 = session_manager.open_session("Microsoft Access");
1397@@ -97,8 +104,8 @@
1398
1399 {
1400 InSequence seq;
1401- EXPECT_CALL(focus_changer, set_focus_to(Eq(session2))).Times(1);
1402- EXPECT_CALL(focus_changer, set_focus_to(Eq(session1))).Times(1);
1403+ EXPECT_CALL(focus_setter, set_focus_to(Eq(session2))).Times(1);
1404+ EXPECT_CALL(focus_setter, set_focus_to(Eq(session1))).Times(1);
1405 }
1406
1407 session_manager.close_session(session3);
1408
1409=== modified file 'tests/mir_test_framework/testing_server_options.cpp'
1410--- tests/mir_test_framework/testing_server_options.cpp 2013-04-18 15:20:45 +0000
1411+++ tests/mir_test_framework/testing_server_options.cpp 2013-04-22 15:55:31 +0000
1412@@ -29,7 +29,7 @@
1413 #include "mir/compositor/graphic_buffer_allocator.h"
1414 #include "mir/input/input_channel.h"
1415 #include "mir/input/input_manager.h"
1416-#include "mir/shell/input_focus_selector.h"
1417+#include "mir/input/null_input_target_listener.h"
1418 #include "src/server/input/android/android_input_manager.h"
1419 #include "src/server/input/android/android_dispatcher_controller.h"
1420
1421@@ -159,14 +159,6 @@
1422 }
1423 };
1424
1425-class StubInputFocusSelector : public msh::InputFocusSelector
1426-{
1427-public:
1428- void set_input_focus_to(std::shared_ptr<mi::SessionTarget> const& /* session */, std::shared_ptr<mi::SurfaceTarget> const& /* surface */)
1429- {
1430- }
1431-};
1432-
1433 }
1434
1435 mtf::TestingServerConfiguration::TestingServerConfiguration() :
1436@@ -184,14 +176,14 @@
1437 return std::make_shared<StubInputManager>();
1438 }
1439
1440-std::shared_ptr<msh::InputFocusSelector> mtf::TestingServerConfiguration::the_input_focus_selector()
1441+std::shared_ptr<msh::InputTargetListener> mtf::TestingServerConfiguration::the_input_target_listener()
1442 {
1443 auto options = the_options();
1444
1445 if (options->get("tests-use-real-input", false))
1446 return std::make_shared<mia::DispatcherController>(the_input_configuration());
1447 else
1448- return std::make_shared<StubInputFocusSelector>();
1449+ return std::make_shared<mi::NullInputTargetListener>();
1450 }
1451
1452 std::shared_ptr<mg::Platform> mtf::TestingServerConfiguration::the_graphics_platform()
1453
1454=== modified file 'tests/unit-tests/input/android/test_android_dispatcher_controller.cpp'
1455--- tests/unit-tests/input/android/test_android_dispatcher_controller.cpp 2013-04-15 14:39:18 +0000
1456+++ tests/unit-tests/input/android/test_android_dispatcher_controller.cpp 2013-04-22 15:55:31 +0000
1457@@ -31,6 +31,8 @@
1458 #include <sys/types.h>
1459 #include <sys/socket.h>
1460
1461+#include <stdexcept>
1462+
1463 namespace mi = mir::input;
1464 namespace mia = mi::android;
1465 namespace mt = mir::test;
1466@@ -47,12 +49,16 @@
1467 void SetUp() override
1468 {
1469 test_input_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
1470+
1471+ dispatcher = new mtd::MockInputDispatcher();
1472 }
1473 void TearDown() override
1474 {
1475 close(test_input_fd);
1476 }
1477 int test_input_fd;
1478+ droidinput::sp<mtd::MockInputDispatcher> dispatcher;
1479+ mtd::MockInputConfiguration config;
1480 };
1481
1482 static bool
1483@@ -104,30 +110,151 @@
1484
1485 }
1486
1487-TEST_F(AndroidDispatcherControllerFdSetup, set_input_focus)
1488-{
1489- using namespace ::testing;
1490-
1491- auto dispatcher = new mtd::MockInputDispatcher(); // We need droidinput::sp
1492- mtd::MockInputConfiguration config;
1493- EXPECT_CALL(config, the_dispatcher()).Times(1)
1494- .WillOnce(Return(dispatcher));
1495-
1496- auto session = std::make_shared<mtd::StubSessionTarget>();
1497- auto surface = std::make_shared<mtd::StubSurfaceTarget>(test_input_fd);
1498+TEST_F(AndroidDispatcherControllerFdSetup, input_application_opened_behavior)
1499+{
1500+ using namespace ::testing;
1501+
1502+ EXPECT_CALL(config, the_dispatcher()).Times(1)
1503+ .WillOnce(Return(dispatcher));
1504+ mia::DispatcherController controller(mt::fake_shared(config));
1505+
1506+ auto session = std::make_shared<mtd::StubSessionTarget>();
1507+ controller.input_application_opened(session);
1508+ EXPECT_THROW({
1509+ // An application can not be opened twice!
1510+ controller.input_application_opened(session);
1511+ }, std::logic_error);
1512+}
1513+
1514+TEST_F(AndroidDispatcherControllerFdSetup, input_application_closed_behavior)
1515+{
1516+ using namespace ::testing;
1517+
1518+ EXPECT_CALL(config, the_dispatcher()).Times(1)
1519+ .WillOnce(Return(dispatcher));
1520+ mia::DispatcherController controller(mt::fake_shared(config));
1521+
1522+ auto session = std::make_shared<mtd::StubSessionTarget>();
1523+ EXPECT_THROW({
1524+ // We can't close an application which is not open
1525+ controller.input_application_closed(session);
1526+ }, std::logic_error);
1527+ controller.input_application_opened(session);
1528+ controller.input_application_closed(session);
1529+ EXPECT_THROW({
1530+ // Nor can we close an application twice
1531+ controller.input_application_closed(session);
1532+ }, std::logic_error);
1533+}
1534+
1535+TEST_F(AndroidDispatcherControllerFdSetup, input_surface_opened_behavior)
1536+{
1537+ using namespace ::testing;
1538+
1539+ auto session = std::make_shared<mtd::StubSessionTarget>();
1540+ auto surface = std::make_shared<mtd::StubSurfaceTarget>(test_input_fd);
1541+
1542+ EXPECT_CALL(config, the_dispatcher()).Times(1)
1543+ .WillOnce(Return(dispatcher));
1544+ EXPECT_CALL(*dispatcher, registerInputChannel(_, WindowHandleFor(session, surface), false)).Times(1)
1545+ .WillOnce(Return(droidinput::OK));
1546+
1547+ mia::DispatcherController controller(mt::fake_shared(config));
1548+
1549+ EXPECT_THROW({
1550+ // We can't open a surface with an unopened session!
1551+ controller.input_surface_opened(session, surface);
1552+ }, std::logic_error);
1553+ controller.input_application_opened(session);
1554+ controller.input_surface_opened(session, surface);
1555+ EXPECT_THROW({
1556+ // We can't open a surface twice
1557+ controller.input_surface_opened(session, surface);
1558+ }, std::logic_error);
1559+}
1560+
1561+TEST_F(AndroidDispatcherControllerFdSetup, input_surface_closed_behavior)
1562+{
1563+ using namespace ::testing;
1564+
1565+ auto session = std::make_shared<mtd::StubSessionTarget>();
1566+ auto surface = std::make_shared<mtd::StubSurfaceTarget>(test_input_fd);
1567+
1568+ EXPECT_CALL(config, the_dispatcher()).Times(1)
1569+ .WillOnce(Return(dispatcher));
1570+ EXPECT_CALL(*dispatcher, registerInputChannel(_, WindowHandleFor(session, surface), false)).Times(1)
1571+ .WillOnce(Return(droidinput::OK));
1572+ EXPECT_CALL(*dispatcher, unregisterInputChannel(_)).Times(1);
1573+ mia::DispatcherController controller(mt::fake_shared(config));
1574+
1575+ controller.input_application_opened(session);
1576+
1577+ EXPECT_THROW({
1578+ // We can't close a surface which hasn't been opened
1579+ controller.input_surface_closed(surface);
1580+ }, std::logic_error);
1581+ controller.input_surface_opened(session, surface);
1582+ controller.input_surface_closed(surface);
1583+ EXPECT_THROW({
1584+ // Nor can we close a surface twice
1585+ controller.input_surface_closed(surface);
1586+ }, std::logic_error);
1587+}
1588+
1589+TEST_F(AndroidDispatcherControllerFdSetup, on_focus_cleared)
1590+{
1591+ using namespace ::testing;
1592+
1593+ EXPECT_CALL(config, the_dispatcher()).Times(1)
1594+ .WillOnce(Return(dispatcher));
1595+
1596+ EXPECT_CALL(*dispatcher, setFocusedApplication(droidinput::sp<droidinput::InputApplicationHandle>(0))).Times(1);
1597+ EXPECT_CALL(*dispatcher, setInputWindows(EmptyVector())).Times(1);
1598+
1599+ mia::DispatcherController controller(mt::fake_shared(config));
1600+
1601+ controller.focus_cleared();
1602+}
1603+
1604+TEST_F(AndroidDispatcherControllerFdSetup, on_focus_changed)
1605+{
1606+ using namespace ::testing;
1607+
1608+ auto session = std::make_shared<mtd::StubSessionTarget>();
1609+ auto surface = std::make_shared<mtd::StubSurfaceTarget>(test_input_fd);
1610+
1611+ EXPECT_CALL(config, the_dispatcher()).Times(1)
1612+ .WillOnce(Return(dispatcher));
1613+ EXPECT_CALL(*dispatcher, registerInputChannel(_, WindowHandleFor(session, surface), false)).Times(1)
1614+ .WillOnce(Return(droidinput::OK));
1615
1616 {
1617 InSequence seq;
1618 EXPECT_CALL(*dispatcher, setFocusedApplication(ApplicationHandleFor(session))).Times(1);
1619- EXPECT_CALL(*dispatcher, registerInputChannel(_, WindowHandleFor(session, surface), false)).Times(1)
1620- .WillOnce(Return(droidinput::OK));
1621 EXPECT_CALL(*dispatcher, setInputWindows(VectorContainingWindowHandleFor(session, surface))).Times(1);
1622- EXPECT_CALL(*dispatcher, unregisterInputChannel(_)).Times(1);
1623- EXPECT_CALL(*dispatcher, setInputWindows(EmptyVector())).Times(1);
1624 }
1625
1626 mia::DispatcherController controller(mt::fake_shared(config));
1627-
1628- controller.set_input_focus_to(session, surface);
1629- controller.set_input_focus_to(session, std::shared_ptr<mi::SurfaceTarget>());
1630+
1631+ controller.input_application_opened(session);
1632+ controller.input_surface_opened(session, surface);
1633+
1634+ controller.focus_changed(surface);
1635+}
1636+
1637+TEST_F(AndroidDispatcherControllerFdSetup, on_focus_changed_throw_behavior)
1638+{
1639+ using namespace ::testing;
1640+
1641+ EXPECT_CALL(config, the_dispatcher()).Times(1)
1642+ .WillOnce(Return(dispatcher));
1643+
1644+ auto surface = std::make_shared<mtd::StubSurfaceTarget>(test_input_fd);
1645+
1646+ mia::DispatcherController controller(mt::fake_shared(config));
1647+
1648+ EXPECT_THROW({
1649+ // We can't focus surfaces which never opened
1650+ controller.focus_changed(surface);
1651+ }, std::logic_error);
1652 }
1653
1654=== modified file 'tests/unit-tests/input/android/test_event_filter_input_dispatcher_policy.cpp'
1655--- tests/unit-tests/input/android/test_event_filter_input_dispatcher_policy.cpp 2013-03-22 16:41:59 +0000
1656+++ tests/unit-tests/input/android/test_event_filter_input_dispatcher_policy.cpp 2013-04-22 15:55:31 +0000
1657@@ -37,7 +37,7 @@
1658 using namespace ::testing;
1659 droidinput::KeyEvent ev;
1660 mtd::MockEventFilter filter;
1661- mia::EventFilterDispatcherPolicy policy(mt::fake_shared(filter));
1662+ mia::EventFilterDispatcherPolicy policy(mt::fake_shared(filter), true);
1663 uint32_t policy_flags;
1664
1665 EXPECT_CALL(filter, handles(_)).Times(1).WillOnce(Return(false));
1666
1667=== modified file 'tests/unit-tests/shell/test_application_session.cpp'
1668--- tests/unit-tests/shell/test_application_session.cpp 2013-04-17 18:18:31 +0000
1669+++ tests/unit-tests/shell/test_application_session.cpp 2013-04-22 15:55:31 +0000
1670@@ -22,6 +22,7 @@
1671 #include "mir_test/fake_shared.h"
1672 #include "mir_test_doubles/mock_surface_factory.h"
1673 #include "mir_test_doubles/mock_surface.h"
1674+#include "mir_test_doubles/stub_input_target_listener.h"
1675 #include "mir_test_doubles/stub_surface_builder.h"
1676 #include "mir_test_doubles/stub_surface.h"
1677
1678@@ -51,7 +52,8 @@
1679 EXPECT_CALL(surface_factory, create_surface(_));
1680 EXPECT_CALL(*mock_surface, destroy());
1681
1682- msh::ApplicationSession session(mt::fake_shared(surface_factory), "Foo");
1683+ mtd::StubInputTargetListener input_listener;
1684+ msh::ApplicationSession session(mt::fake_shared(surface_factory), mt::fake_shared(input_listener), "Foo");
1685
1686 mf::SurfaceCreationParameters params;
1687 auto surf = session.create_surface(params);
1688@@ -75,7 +77,8 @@
1689 .WillOnce(Return(std::make_shared<NiceMock<mtd::MockSurface>>(mt::fake_shared(surface_builder))));
1690 }
1691
1692- msh::ApplicationSession app_session(mt::fake_shared(surface_factory), "Foo");
1693+ mtd::StubInputTargetListener input_listener;
1694+ msh::ApplicationSession app_session(mt::fake_shared(surface_factory), mt::fake_shared(input_listener), "Foo");
1695
1696 mf::SurfaceCreationParameters params;
1697 auto id1 = app_session.create_surface(params);
1698@@ -105,7 +108,8 @@
1699 mtd::MockSurfaceFactory surface_factory;
1700 ON_CALL(surface_factory, create_surface(_)).WillByDefault(Return(mock_surface));
1701
1702- msh::ApplicationSession app_session(mt::fake_shared(surface_factory), "Foo");
1703+ mtd::StubInputTargetListener input_listener;
1704+ msh::ApplicationSession app_session(mt::fake_shared(surface_factory), mt::fake_shared(input_listener), "Foo");
1705
1706 EXPECT_CALL(surface_factory, create_surface(_));
1707
1708@@ -130,7 +134,8 @@
1709 using namespace ::testing;
1710
1711 mtd::MockSurfaceFactory surface_factory;
1712- msh::ApplicationSession app_session(mt::fake_shared(surface_factory), "Foo");
1713+ mtd::StubInputTargetListener input_listener;
1714+ msh::ApplicationSession app_session(mt::fake_shared(surface_factory), mt::fake_shared(input_listener), "Foo");
1715 mf::SurfaceId invalid_surface_id(1);
1716
1717 EXPECT_THROW({
1718@@ -143,7 +148,8 @@
1719 using namespace ::testing;
1720
1721 mtd::MockSurfaceFactory surface_factory;
1722- msh::ApplicationSession app_session(mt::fake_shared(surface_factory), "Foo");
1723+ mtd::StubInputTargetListener input_listener;
1724+ msh::ApplicationSession app_session(mt::fake_shared(surface_factory), mt::fake_shared(input_listener), "Foo");
1725 mf::SurfaceId invalid_surface_id(1);
1726
1727 EXPECT_THROW({
1728
1729=== modified file 'tests/unit-tests/shell/test_registration_order_focus_sequence.cpp'
1730--- tests/unit-tests/shell/test_registration_order_focus_sequence.cpp 2013-04-18 00:00:55 +0000
1731+++ tests/unit-tests/shell/test_registration_order_focus_sequence.cpp 2013-04-22 15:55:31 +0000
1732@@ -22,8 +22,11 @@
1733 #include "mir/shell/registration_order_focus_sequence.h"
1734 #include "mir/frontend/surface_creation_parameters.h"
1735 #include "mir/surfaces/surface.h"
1736+
1737 #include "mir_test_doubles/mock_buffer_bundle.h"
1738 #include "mir_test_doubles/mock_surface_factory.h"
1739+#include "mir_test_doubles/stub_input_target_listener.h"
1740+#include "mir_test/fake_shared.h"
1741
1742 #include <gmock/gmock.h>
1743 #include <gtest/gtest.h>
1744@@ -32,7 +35,8 @@
1745 namespace mc = mir::compositor;
1746 namespace msh = mir::shell;
1747 namespace ms = mir::surfaces;
1748-namespace mtd = mir::test::doubles;
1749+namespace mt = mir::test;
1750+namespace mtd = mt::doubles;
1751
1752 namespace
1753 {
1754@@ -45,6 +49,7 @@
1755 }
1756 std::shared_ptr<mtd::MockSurfaceFactory> factory;
1757 std::shared_ptr<msh::DefaultSessionContainer> container;
1758+ mtd::StubInputTargetListener input_listener;
1759
1760 static std::string const testing_app_name1;
1761 static std::string const testing_app_name2;
1762@@ -60,9 +65,9 @@
1763 {
1764 using namespace ::testing;
1765
1766- auto app1 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name1);
1767- auto app2 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name2);
1768- auto app3 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name3);
1769+ auto app1 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name1);
1770+ auto app2 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name2);
1771+ auto app3 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name3);
1772
1773 container->insert_session(app1);
1774 container->insert_session(app2);
1775@@ -78,9 +83,9 @@
1776 {
1777 using namespace ::testing;
1778
1779- auto app1 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name1);
1780- auto app2 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name2);
1781- auto app3 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name3);
1782+ auto app1 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name1);
1783+ auto app2 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name2);
1784+ auto app3 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name3);
1785 container->insert_session(app1);
1786 container->insert_session(app2);
1787 container->insert_session(app3);
1788@@ -95,7 +100,7 @@
1789 {
1790 using namespace ::testing;
1791
1792- auto app1 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name1);
1793+ auto app1 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name1);
1794 container->insert_session(app1);
1795
1796 msh::RegistrationOrderFocusSequence focus_sequence(container);
1797@@ -107,8 +112,8 @@
1798 {
1799 using namespace ::testing;
1800
1801- auto app1 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name1);
1802- auto app2 = std::make_shared<msh::ApplicationSession>(factory, testing_app_name2);
1803+ auto app1 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name1);
1804+ auto app2 = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name2);
1805 auto null_session = std::shared_ptr<msh::ApplicationSession>();
1806
1807 msh::RegistrationOrderFocusSequence focus_sequence(container);
1808@@ -124,7 +129,7 @@
1809 {
1810 using namespace ::testing;
1811
1812- auto invalid_session = std::make_shared<msh::ApplicationSession>(factory, testing_app_name1);
1813+ auto invalid_session = std::make_shared<msh::ApplicationSession>(factory, mt::fake_shared(input_listener), testing_app_name1);
1814 auto null_session = std::shared_ptr<msh::ApplicationSession>();
1815
1816 msh::RegistrationOrderFocusSequence focus_sequence(container);
1817
1818=== modified file 'tests/unit-tests/shell/test_session_manager.cpp'
1819--- tests/unit-tests/shell/test_session_manager.cpp 2013-04-18 22:29:24 +0000
1820+++ tests/unit-tests/shell/test_session_manager.cpp 2013-04-22 15:55:31 +0000
1821@@ -21,15 +21,19 @@
1822 #include "mir/shell/session_manager.h"
1823 #include "mir/shell/default_session_container.h"
1824 #include "mir/shell/session.h"
1825+#include "mir/shell/input_target_listener.h"
1826 #include "mir/frontend/surface_creation_parameters.h"
1827 #include "mir/surfaces/surface.h"
1828 #include "mir/input/input_channel.h"
1829+
1830+#include "mir_test/fake_shared.h"
1831 #include "mir_test_doubles/mock_buffer_bundle.h"
1832-#include "mir_test/fake_shared.h"
1833 #include "mir_test_doubles/mock_surface_factory.h"
1834 #include "mir_test_doubles/mock_focus_setter.h"
1835 #include "mir_test_doubles/null_buffer_bundle.h"
1836 #include "mir_test_doubles/stub_surface_builder.h"
1837+#include "mir_test_doubles/stub_input_target_listener.h"
1838+#include "mir_test_doubles/mock_input_target_listener.h"
1839
1840 #include "mir/shell/surface.h"
1841
1842@@ -56,7 +60,7 @@
1843 ~MockSessionContainer() noexcept {}
1844 };
1845
1846-struct MockFocusSequence: public msh::FocusSequence
1847+struct MockFocusSequence : public msh::FocusSequence
1848 {
1849 MOCK_CONST_METHOD1(successor_of, std::shared_ptr<msh::Session>(std::shared_ptr<msh::Session> const&));
1850 MOCK_CONST_METHOD1(predecessor_of, std::shared_ptr<msh::Session>(std::shared_ptr<msh::Session> const&));
1851@@ -68,16 +72,18 @@
1852 SessionManagerSetup()
1853 : session_manager(mt::fake_shared(surface_factory),
1854 mt::fake_shared(container),
1855- mt::fake_shared(sequence),
1856- mt::fake_shared(focus_setter))
1857+ mt::fake_shared(focus_sequence),
1858+ mt::fake_shared(focus_setter),
1859+ mt::fake_shared(input_target_listener))
1860 {
1861 }
1862
1863 mtd::StubSurfaceBuilder surface_builder;
1864 mtd::MockSurfaceFactory surface_factory;
1865 testing::NiceMock<MockSessionContainer> container; // Inelegant but some tests need a stub
1866- MockFocusSequence sequence;
1867+ MockFocusSequence focus_sequence;
1868 testing::NiceMock<mtd::MockFocusSetter> focus_setter; // Inelegant but some tests need a stub
1869+ mtd::StubInputTargetListener input_target_listener;
1870
1871 msh::SessionManager session_manager;
1872 };
1873@@ -93,7 +99,7 @@
1874 EXPECT_CALL(focus_setter, set_focus_to(_));
1875 EXPECT_CALL(focus_setter, set_focus_to(std::shared_ptr<msh::Session>())).Times(1);
1876
1877- EXPECT_CALL(sequence, default_focus()).WillOnce(Return((std::shared_ptr<msh::Session>())));
1878+ EXPECT_CALL(focus_sequence, default_focus()).WillOnce(Return((std::shared_ptr<msh::Session>())));
1879
1880 auto session = session_manager.open_session("Visual Basic Studio");
1881 session_manager.close_session(session);
1882@@ -118,7 +124,7 @@
1883 EXPECT_CALL(focus_setter, set_focus_to(_)).Times(1);
1884 EXPECT_CALL(focus_setter, set_focus_to(std::shared_ptr<msh::Session>())).Times(1);
1885
1886- EXPECT_CALL(sequence, default_focus()).WillOnce(Return((std::shared_ptr<msh::Session>())));
1887+ EXPECT_CALL(focus_sequence, default_focus()).WillOnce(Return((std::shared_ptr<msh::Session>())));
1888
1889 auto session = session_manager.open_session("Visual Basic Studio");
1890 session->create_surface(mf::a_surface().of_size(geom::Size{geom::Width{1024}, geom::Height{768}}));
1891@@ -164,7 +170,7 @@
1892 session_manager.tag_session_with_lightdm_id(session1, 1);
1893 session_manager.focus_session_with_lightdm_id(1);
1894
1895- EXPECT_CALL(sequence, default_focus()).WillOnce(Return(shell_session2));
1896+ EXPECT_CALL(focus_sequence, default_focus()).WillOnce(Return(shell_session2));
1897 EXPECT_CALL(focus_setter, set_focus_to(Eq(shell_session2)));
1898
1899 session_manager.close_session(session1);
1900@@ -193,3 +199,62 @@
1901 session_manager.create_surface_for(session1, mf::a_surface());
1902 }
1903
1904+namespace
1905+{
1906+
1907+struct SessionManagerInputTargetListenerSetup : public testing::Test
1908+{
1909+ SessionManagerInputTargetListenerSetup()
1910+ : session_manager(mt::fake_shared(surface_factory),
1911+ mt::fake_shared(container),
1912+ mt::fake_shared(focus_sequence),
1913+ mt::fake_shared(focus_setter),
1914+ mt::fake_shared(input_target_listener))
1915+ {
1916+ }
1917+
1918+ mtd::StubSurfaceBuilder surface_builder;
1919+ mtd::MockSurfaceFactory surface_factory;
1920+ testing::NiceMock<MockSessionContainer> container; // Inelegant but some tests need a stub
1921+ testing::NiceMock<MockFocusSequence> focus_sequence;
1922+ testing::NiceMock<mtd::MockFocusSetter> focus_setter; // Inelegant but some tests need a stub
1923+ mtd::MockInputTargetListener input_target_listener;
1924+
1925+ msh::SessionManager session_manager;
1926+};
1927+
1928+}
1929+
1930+TEST_F(SessionManagerInputTargetListenerSetup, listener_is_notified_of_session_and_surfacelifecycle)
1931+{
1932+ using namespace ::testing;
1933+
1934+ std::shared_ptr<mi::InputChannel> null_input_channel;
1935+ ON_CALL(surface_factory, create_surface(_)).WillByDefault(
1936+ Return(std::make_shared<msh::Surface>(
1937+ mt::fake_shared(surface_builder),
1938+ mf::a_surface(),
1939+ null_input_channel)));
1940+ EXPECT_CALL(surface_factory, create_surface(_)).Times(1);
1941+
1942+ EXPECT_CALL(focus_sequence, default_focus()).WillOnce(Return((std::shared_ptr<msh::Session>())));
1943+ {
1944+ InSequence seq;
1945+
1946+ EXPECT_CALL(input_target_listener, input_application_opened(_))
1947+ .Times(1);
1948+ EXPECT_CALL(input_target_listener, input_surface_opened(_, _)).Times(1);
1949+ EXPECT_CALL(input_target_listener, focus_changed(_)).Times(1);
1950+ EXPECT_CALL(input_target_listener, input_surface_closed(_)).Times(1);
1951+ EXPECT_CALL(input_target_listener, input_application_closed(_))
1952+ .Times(1);
1953+ EXPECT_CALL(input_target_listener, focus_cleared()).Times(1);
1954+ }
1955+
1956+ {
1957+ auto session = session_manager.open_session("test");
1958+ auto surf = session_manager.create_surface_for(session, mf::a_surface());
1959+ session->destroy_surface(surf);
1960+ session_manager.close_session(session);
1961+ }
1962+}
1963
1964=== modified file 'tests/unit-tests/shell/test_single_visibility_focus_mechanism.cpp'
1965--- tests/unit-tests/shell/test_single_visibility_focus_mechanism.cpp 2013-04-19 15:33:04 +0000
1966+++ tests/unit-tests/shell/test_single_visibility_focus_mechanism.cpp 2013-04-22 15:55:31 +0000
1967@@ -27,7 +27,6 @@
1968 #include "mir_test_doubles/mock_buffer_bundle.h"
1969 #include "mir_test/fake_shared.h"
1970 #include "mir_test_doubles/mock_surface_factory.h"
1971-#include "mir_test_doubles/mock_input_focus_selector.h"
1972 #include "mir_test_doubles/stub_surface.h"
1973 #include "mir_test_doubles/mock_surface.h"
1974 #include "mir_test_doubles/stub_surface_builder.h"
1975@@ -64,8 +63,6 @@
1976 {
1977 using namespace ::testing;
1978
1979- NiceMock<mtd::MockInputFocusSelector> input_focus_selector;
1980-
1981 NiceMock<MockShellSession> app1, app2, app3;
1982 msh::DefaultSessionContainer model;
1983
1984@@ -73,7 +70,7 @@
1985 ON_CALL(app2, default_surface()).WillByDefault(Return(std::shared_ptr<msh::Surface>()));
1986 ON_CALL(app3, default_surface()).WillByDefault(Return(std::shared_ptr<msh::Surface>()));
1987
1988- msh::SingleVisibilityFocusMechanism focus_mechanism(mt::fake_shared(model), mt::fake_shared(input_focus_selector));
1989+ msh::SingleVisibilityFocusMechanism focus_mechanism(mt::fake_shared(model));
1990
1991 EXPECT_CALL(app1, show()).Times(1);
1992 EXPECT_CALL(app2, hide()).Times(1);
1993@@ -89,23 +86,3 @@
1994
1995 focus_mechanism.set_focus_to(mt::fake_shared(app1));
1996 }
1997-
1998-TEST(SingleVisibilityFocusMechanism, mechanism_sets_input_focus_from_default_surface)
1999-{
2000- using namespace ::testing;
2001-
2002- mtd::MockInputFocusSelector input_focus_selector;
2003- msh::DefaultSessionContainer model;
2004- auto session = std::make_shared<NiceMock<MockShellSession>>();
2005- auto surface = std::make_shared<mtd::MockSurface>(std::make_shared<mtd::StubSurfaceBuilder>());
2006-
2007- msh::SingleVisibilityFocusMechanism focus_mechanism(mt::fake_shared(model), mt::fake_shared(input_focus_selector));
2008-
2009- EXPECT_CALL(*session, default_surface()).Times(1).WillOnce(Return(surface));
2010-
2011- EXPECT_CALL(input_focus_selector, set_input_focus_to(Eq(session), Eq(surface))).Times(1);
2012-
2013- model.insert_session(session);
2014- focus_mechanism.set_focus_to(session);
2015-}
2016-
2017
2018=== modified file 'tests/unit-tests/shell/test_the_session_container_implementation.cpp'
2019--- tests/unit-tests/shell/test_the_session_container_implementation.cpp 2013-04-18 00:00:55 +0000
2020+++ tests/unit-tests/shell/test_the_session_container_implementation.cpp 2013-04-22 15:55:31 +0000
2021@@ -22,6 +22,7 @@
2022 #include "mir/frontend/surface_creation_parameters.h"
2023 #include "mir/surfaces/surface.h"
2024 #include "mir_test_doubles/mock_buffer_bundle.h"
2025+#include "mir_test_doubles/stub_input_target_listener.h"
2026 #include "mir_test_doubles/mock_surface_factory.h"
2027
2028 #include <gmock/gmock.h>
2029@@ -38,8 +39,10 @@
2030 auto factory = std::make_shared<mtd::MockSurfaceFactory>();
2031 msh::DefaultSessionContainer container;
2032
2033- container.insert_session(std::make_shared<msh::ApplicationSession>(factory, "Visual Studio 7"));
2034- container.insert_session(std::make_shared<msh::ApplicationSession>(factory, "Visual Studio 8"));
2035+ container.insert_session(std::make_shared<msh::ApplicationSession>(factory, std::make_shared<mtd::StubInputTargetListener>(),
2036+ "Visual Studio 7"));
2037+ container.insert_session(std::make_shared<msh::ApplicationSession>(factory, std::make_shared<mtd::StubInputTargetListener>(),
2038+ "Visual Studio 8"));
2039
2040 struct local
2041 {
2042@@ -64,8 +67,8 @@
2043 auto factory = std::make_shared<mtd::MockSurfaceFactory>();
2044 msh::DefaultSessionContainer container;
2045
2046- auto session = std::make_shared<msh::ApplicationSession>(factory,
2047- "Visual Studio 7");
2048+ auto session = std::make_shared<msh::ApplicationSession>(factory, std::make_shared<mtd::StubInputTargetListener>(),
2049+ "Visual Studio 7");
2050 EXPECT_THROW({
2051 container.remove_session(session);
2052 }, std::logic_error);

Subscribers

People subscribed via source and target branches